aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcolin <colin@cicadas.surf>2023-07-29 10:22:44 -0700
committercolin <colin@cicadas.surf>2023-07-29 10:22:44 -0700
commit9289f299cffe96f87483064e71c60fb7da0cb0ad (patch)
tree1fc0e672207f587bf4fb5a74d8fa052d3718f056
parente8dfcee463d771c21c513dea4af30c5c51a2525e (diff)
Add better grammar parsing for subexpressions
-rw-r--r--argot.lisp23
-rw-r--r--examples/calc.lisp6
2 files changed, 24 insertions, 5 deletions
diff --git a/argot.lisp b/argot.lisp
index 4c1dfdc..c2b3556 100644
--- a/argot.lisp
+++ b/argot.lisp
@@ -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)