'(:* * :+ + :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 ())
+;;; Inline complex form (like :or). Returned values are same as of
(defun expand-inlinable-form (form rule pos)
(let ((generated-sym1 (gensym)))
- (let ((short-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))
+ ((atom subform)
(push subform short-subforms))
+ ((null (rest subform))
(push (first subform) short-subforms))
(push subform long-subforms))))
+ ;; Bind long subforms to one artificial nterm
(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))
(loop :for or-clause :in (rest short-subforms)
:collect `(,rule-left ,rule-action
+ ;; Short subform replaces inlinable
,@(replace (copy-list rule-right)
:start1 pos :end1 (1+ pos))))))
(push `(,generated-sym1 (:action #'list)
+ ;; First short subform happens to be complex form, it is
+ ;; processed recursively.
(multiple-value-bind (new-form2 new-rules2 transform2)
(parse-complex-form new-form rule pos)