summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--input.lisp3
-rw-r--r--package.lisp3
-rw-r--r--parser.lisp58
3 files changed, 42 insertions, 22 deletions
diff --git a/input.lisp b/input.lisp
index dcea8f6..4edf6aa 100644
--- a/input.lisp
+++ b/input.lisp
@@ -25,6 +25,9 @@
:file (file input)
:cursor (+ (cursor input) amount)))
+(defun input-sub (input1 input2)
+ (- (cursor input1) (cursor input2)))
+
(defun from-string (str)
(make-instance 'input :data str))
diff --git a/package.lisp b/package.lisp
index d742fbb..c352bd4 100644
--- a/package.lisp
+++ b/package.lisp
@@ -10,4 +10,5 @@
#:many
#:repeat
#:whitespace
- #:separated-list))
+ #:separated-list
+ #:surrounded))
diff --git a/parser.lisp b/parser.lisp
index 32d9d50..9d4be57 100644
--- a/parser.lisp
+++ b/parser.lisp
@@ -14,7 +14,8 @@
(defstruct parsing
tree
- left)
+ left
+ limit)
(defstruct failure
place
@@ -32,7 +33,6 @@
(declare (ignore lazy limit))
(make-parsing :tree tree :left input)))
-; (parser<a> (a -> parser<b>) -> b)
(defun bind (p f &key (greedy t))
(lambda (input &key limit lazy)
(let (r)
@@ -40,9 +40,10 @@
(setf r (funcall p input))
(let ((next-parser (funcall f nil input))
(limit -1))
- (do ((sweep-input input (advance sweep-input))) (limit nil)
- (when (and (has-data? sweep-input)
- (functionp (funcall next-parser sweep-input t)))
+ (do ((sweep-input input (advance sweep-input)))
+ ((or (not (has-data? sweep-input))
+ (> limit -1)) nil)
+ (when (functionp (funcall next-parser sweep-input :lazy t))
(setf limit (input-sub sweep-input input))))
(if (< limit 0)
(setf r (make-failure :place input
@@ -55,30 +56,37 @@
(funcall (funcall f (parsing-tree r) input)
(parsing-left r)
:lazy lazy
- :limit (if limit (1- limit))))
+ :limit (parsing-limit r)))
(funcall (funcall f (parsing-tree r) input)
(parsing-left r)
- :limit (if limit (1- limit))))
+ :limit (parsing-limit r)))
r))))
(defmacro comp (bindings &body body)
(if (null bindings)
`(new (progn ,@body))
- (let ((v (first (car bindings)))
- (p (second (car bindings)))
+ (let ((var (first (car bindings)))
+ (parser (second (car bindings)))
+ (lazy (third (car bindings)))
(unused (gensym)))
- (if (symbolp v)
- (if (string= (symbol-name v) "_")
- `(bind ,p (lambda (&rest ,unused)
- (declare (ignore ,unused))
- (comp ,(cdr bindings) ,@body)))
- `(bind ,p (lambda (,v &rest ,unused)
- (declare (ignore ,unused))
- (comp ,(cdr bindings) ,@body))))
- (if (and (consp v) (symbolp (car v)) (symbolp (cdr v)))
- `(bind ,p (lambda (,(car v) ,(cdr v) &rest ,unused)
- (declare (ignore ,unused))
- (comp ,(cdr bindings) ,@body)))
+ (if (symbolp var)
+ (if (string= (symbol-name var) "_")
+ `(bind ,parser
+ (lambda (&rest ,unused)
+ (declare (ignore ,unused))
+ (comp ,(cdr bindings) ,@body))
+ :greedy ,(not lazy))
+ `(bind ,parser
+ (lambda (,var &rest ,unused)
+ (declare (ignore ,unused))
+ (comp ,(cdr bindings) ,@body))
+ :greedy ,(not lazy)))
+ (if (and (consp var) (symbolp (car var)) (symbolp (cdr var)))
+ `(bind ,parser
+ (lambda (,(car var) ,(cdr var) &rest ,unused)
+ (declare (ignore ,unused))
+ (comp ,(cdr bindings) ,@body))
+ :greedy ,(not lazy))
(error "Binding must be either a symbol or a cons of symbols."))))))
(defun one-of (first-parser second-parser &rest other-parsers)
@@ -174,3 +182,11 @@
(if include-separator
(cons v (cons sep vn))
(cons v vn))))
+
+(defun surrounded (left p right &key include-surrounding)
+ (comp ((l left)
+ (body p :lazy)
+ (r right))
+ (if include-surrounding
+ (list l body r)
+ body)))