diff options
-rw-r--r-- | argot.lisp | 23 | ||||
-rw-r--r-- | examples/calc.lisp | 6 |
2 files changed, 24 insertions, 5 deletions
@@ -50,6 +50,9 @@ expression. Such expressions look like (OP . ARGS) where OP is one of (:@ (and (var? (first more)) (not (third more)) (pattern? (second more)))) + (:{} (and (car more) + (symbolp (car more)) + (endp (cdr more)))) ((:item :eof) (endp more))))))) (defun var-pattern? (pat) @@ -101,7 +104,6 @@ and it returns VAR in that case." (symbolp (second s)) (endp (cddr s))))) - (defmacro deflanguage (name (&key (documentation "")) &body ruledefs) (let ((bindings-var (gensym "BINDINGS"))) (labels ((collect-let-bindings (lhs vars) @@ -269,6 +271,24 @@ any pattern fails the whole parse fails." (succeed nil) (fail))) +(defun find-grammar (name) + (and (symbolp name) + (boundp name) + (let ((val (symbol-value name))) + (and (typep val 'grammar) + val)))) + +(defun parse-grammar-pattern (language) + (if-parse (subtokens) (parse-item) + (if (listp subtokens) + (if-let (grammar (find-grammar language)) + (let ((*grammar* grammar) + (*position* 0) + (*tokens* (coerce subtokens 'vector))) + (parse-rule (start-rule grammar))) + (error "No grammar called ~s" language)) + (fail)))) + (defun parse-pattern (pattern) (if (nonterminal? pattern) (parse-rule pattern) @@ -286,6 +306,7 @@ any pattern fails the whole parse fails." (:?= (parse-optional-literal (first args))) (:seq= (parse-literal-sequence args)) (:@ (parse-binding-pattern (first args) (second args))) + (:{} (parse-grammar-pattern (first args))) (:item (parse-item)) (:eof (parse-eof)))))) diff --git a/examples/calc.lisp b/examples/calc.lisp index 4d8766a..d3140ee 100644 --- a/examples/calc.lisp +++ b/examples/calc.lisp @@ -6,7 +6,7 @@ (in-package #:argot.examples.calc) (deflanguage calc (:documentation "A calculator language") - (<calc> + (<start> :match (:or (:seq <subexpr> (:eof)) (:seq <value> (:eof)) @@ -16,9 +16,7 @@ (<expr> :match (:or <subexpr> <value> <unop> <binop>)) (<subexpr> - :match (:item) - :if listp - :then (argot:parse calc <subexpr>)) + :match (:{} calc)) (<value> :match (:item) :if numberp) |