Commits

Ivan Boldyrev  committed ad2f44d

Complex form expansion is documented in sources.
Keywords: doc, generator

* fg-grammar.lisp (expand-complex-form, expand-inlinable-form):
Lot of comments are added.

  • Participants
  • Parent commits ad529e5

Comments (0)

Files changed (1)

File generator/fg-grammar.lisp

 (defparameter +complex-forms+
   '(:* * :+ + :maybe :list))
 
+;;;  Transform complex forms like "(:+ a)" into 3 values:
+;;;
+;;; 1. symbol that is used in original rule as substitution of the
+;;; form ("substitution nterm").  It may be fresh symbol or some old one.
+;;;
+;;; 2. Set of new rules.  May be empty.
+;;;
+;;; 3. Value transformer.  This is a symbol naming a function or
+;;; lambda-expression (but not result of its evaluation).  Transformer
+;;; is applied to value generated by substitution nterm.  It is handy
+;;; for efficient implementation of list forms.
 (defun expand-complex-form (form rule pos)
   (declare (ignore rule pos))
   (let ((generated-rules ())
 (defparameter +inlineable-forms+
   '(:or or))
 
+;;; Inline complex form (like :or).  Returned values are same as of
+;;; expand-complex-form.
 (defun expand-inlinable-form (form rule pos)
   (let ((generated-sym1 (gensym)))
     (ecase (first form)
       ((:or or)
-       (let ((short-subforms ())
-             (long-subforms ()))
+       (let ((short-subforms ()) ; One-element forms are just inlined.
+             (long-subforms ())) ; Forms with two or more elements
+                                 ; are implemented with fresh nterm.
          (dolist (subform (rest form))
            (cond
-             ((atom subform)
+             ((atom subform)        ; Atomic form is short
               (push subform short-subforms))
-             ((null (rest subform))
+             ((null (rest subform)) ; One-element list is short
               (push (first subform) short-subforms))
-             (t
+             (t                     ; Everything else is long subform
               (push subform long-subforms))))
+         ;; Bind long subforms to one artificial nterm
          (when long-subforms
            (push generated-sym1 short-subforms))
+
+         ;; First short subform is returned as substitution nterm.
+         ;; Rest of short subforms are inserted into new rules:
+         ;; subform replaces inlinable form in original rule.
          (let* ((rule-left (first rule))
                 (rule-action (second rule))
                 (rule-right (cddr rule))
                 (new-rules
                  (loop :for or-clause :in (rest short-subforms)
                        :collect `(,rule-left ,rule-action
+                                   ;; Short subform replaces inlinable
+                                   ;; form
                                   ,@(replace (copy-list rule-right)
                                              (list or-clause)
                                              :start1 pos :end1 (1+ pos))))))
              (push `(,generated-sym1 (:action #'list)
                      ,@subform)
                    new-rules))
+           ;; First short subform happens to be complex form, it is
+           ;; processed recursively.
            (if (consp new-form)
                (multiple-value-bind (new-form2 new-rules2 transform2)
                    (parse-complex-form new-form rule pos)