aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--argot.lisp39
1 files changed, 22 insertions, 17 deletions
diff --git a/argot.lisp b/argot.lisp
index c434778..2d72866 100644
--- a/argot.lisp
+++ b/argot.lisp
@@ -70,23 +70,28 @@ and it returns VAR in that case."
(defmacro defgrammar (name (&key (documentation "")) &body ruledefs)
(let ((bindings-var (gensym "BINDINGS")))
- `(progn
- (defvar ,name nil ,documentation)
- (setf ,name (make-hash-table :test #'eq))
- ,@(loop :for ruledef :in ruledefs
- :for (lhs pattern vars action) := (parse-rule-def ruledef)
- :for bindings
- := (loop :for var :in vars
- :collect `(,var (cdr (assoc ',var ,bindings-var))))
- :collect `(include-rule
- ,name
- (make-rule
- :lhs ',lhs
- :pattern ',pattern
- ,@(when action
- (list
- :action `(lambda (,bindings-var) (let ,bindings ,action)))))))
- ,name)))
+ (flet ((collect-let-bindings (lhs vars)
+ "Create let-bindings forms for the body of the :action. "
+ (loop :for var :in vars
+ :collect `(,var (cdr (assoc ',var ,bindings-var))) :into bs
+ :finally (return (list* lhs `(cdr (assoc ',lhs ,bindings-var)) bs))))
+ (rule-includer (name lhs pattern &optional action bindings)
+ `(include-rule
+ ,name
+ (make-rule
+ :lhs ',lhs
+ :pattern ',pattern
+ ,@(when action
+ (list
+ :action `(lambda (,bindings-var) (let ,bindings ,action))))))))
+ `(progn
+ (defvar ,name nil ,documentation)
+ (setf ,name (make-hash-table :test #'eq))
+ ,@(loop :for ruledef :in ruledefs
+ :for (lhs pattern vars action) := (parse-rule-def ruledef)
+ :for bindings := (collect-let-bindings lhs vars)
+ :collect (rule-includer name lhs pattern action bindings))
+ ,name))))
(defvar *position*)
(defvar *grammar*)