summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNoah Lavine <nlavine@haverford.edu>2011-09-19 10:30:53 -0400
committerNoah Lavine <noah.b.lavine@gmail.com>2012-01-20 08:27:16 -0500
commit5f821e7817c4aa27868ccd73c88bba9a68170436 (patch)
tree5a95544e66cff58114aff8ec32890a76ca04125a
parent603548c36c9eab6636a29e54ee5c3dfd8bf7ec22 (diff)
downloadguile-5f821e7817c4aa27868ccd73c88bba9a68170436.tar.gz
Add 'followed-by' PEG
The PEG s-expression syntax now uses '(followed-by ...)' instead of '(body & ... 1)'.
-rw-r--r--doc/ref/api-peg.texi4
-rw-r--r--module/ice-9/peg/codegen.scm20
2 files changed, 22 insertions, 2 deletions
diff --git a/doc/ref/api-peg.texi b/doc/ref/api-peg.texi
index b05a2cf85..4976b59c9 100644
--- a/doc/ref/api-peg.texi
+++ b/doc/ref/api-peg.texi
@@ -90,13 +90,13 @@ Tries to parse @var{a}. Succeeds if @var{a} succeeds.
@code{(? a)}
@end deftp
-@deftp {PEG Pattern} {and predicate} a
+@deftp {PEG Pattern} {followed by} a
Makes sure it is possible to parse @var{a}, but does not actually parse
it. Succeeds if @var{a} would succeed.
@code{"&a"}
-@code{(body & a 1)}
+@code{(followed-by a)}
@end deftp
@deftp {PEG Pattern} {not predicate} a
diff --git a/module/ice-9/peg/codegen.scm b/module/ice-9/peg/codegen.scm
index 91e499d0c..22fb1953d 100644
--- a/module/ice-9/peg/codegen.scm
+++ b/module/ice-9/peg/codegen.scm
@@ -297,6 +297,25 @@ return EXP."
#,(cggr (baf accum) 'cg-body
#'(reverse body) #'new-end)))))))))))
+(define (cg-followed-by args accum)
+ (syntax-case args ()
+ ((pat)
+ #`(lambda (str strlen at)
+ (let ((body '()))
+ (let lp ((end at) (count 0))
+ (let* ((match (#,(peg-sexp-compile #'pat (baf accum))
+ str strlen end))
+ (new-end (if match (car match) end))
+ (count (if (> new-end end) (1+ count) count)))
+ (if (> new-end end)
+ (push-not-null! body (single-filter (cadr match))))
+ (if (and (> new-end end)
+ #,#'(< count 1))
+ (lp new-end count)
+ (let ((success #,#'(= count 1)))
+ #,#`(and success
+ #,(cggr (baf accum) 'cg-body #''() #'at)))))))))))
+
;; Association list of functions to handle different expressions as PEGs
(define peg-compiler-alist '())
@@ -313,6 +332,7 @@ return EXP."
(add-peg-compiler! '* cg-*)
(add-peg-compiler! '+ cg-+)
(add-peg-compiler! '? cg-?)
+(add-peg-compiler! 'followed-by cg-followed-by)
;; Takes an arbitrary expressions and accumulation variable, then parses it.
;; E.g.: (peg-sexp-compile syntax '(and "abc" (or "-" (range #\a #\z))) 'all)