Rolled match-n into grammar-n; also fixed single-character optimization.
authorD Herring <dherring@at.tentpost.dot.com>
Sat, 10 Mar 2007 18:21:30 +0000 (13:21 -0500)
committerD Herring <dherring@at.tentpost.dot.com>
Sat, 10 Mar 2007 18:21:30 +0000 (13:21 -0500)
examples/14977-5.7.lisp
parser.lisp

index 54e9025..e155b4a 100644 (file)
@@ -4,12 +4,12 @@
 
 (grammar-rule bb
   (grammar-and
-   (grammar-n* 3 aa)
+   (grammar-n 3 aa)
    (grammar-string "B")))
 
 (grammar-rule cc
   (grammar-and
-   (grammar-n* 3 (grammar-optional aa))
+   (grammar-n 3 (grammar-optional aa))
    (grammar-string "C")))
 
 (grammar-rule dd
 
 (grammar-rule ff
   (grammar-and
-   (grammar-n* 3 aa)
-   (grammar-n* 3 (grammar-optional aa))
+   (grammar-n 3 aa)
+   (grammar-n 3 (grammar-optional aa))
    (grammar-string "F")))
 
 (grammar-rule gg
   (grammar-and
-   (grammar-n* 3 (grammar-* aa))
+   (grammar-n 3 (grammar-* aa))
    (grammar-string "D")))
index 6af2ae2..cab7df0 100644 (file)
 
 ;; return a list of the children
 ;; return the end of the last child
-(defun match-n (n f string &key (start 0))
-  (if (> n 0)
-      (multiple-value-bind (end value) (funcall f string :start start)
-        (when end
-          (multiple-value-bind (e v) (match-n (1- n) f string :start end)
-            (when e
-              (if (car v)
-                  (values e (cons value v))
-                  (values e (list value)))))))
-      start))
-
 (defun kleene* (f string &key (start 0))
   (multiple-value-bind (end value) (funcall f string :start start)
     (if end
           (values e (cons value v)))
         start)))
 
-(defun kleene+ (f string &key (start 0))
-  "<rule>+ == <rule> <rule>*"
-  (multiple-value-bind (end value) (funcall f string :start start)
-    (if end
-        (multiple-value-bind (e v) (kleene* f string :start end)
-          (values e (cons value v)))
-        nil)))
-
 ;;
 ;; Construction macros
 ;;
@@ -57,7 +38,9 @@
 (defmacro grammar-string (str)
   (let ((l (length str)))
     (cond ((= l 0) '(values start ""))
-          ((= l 1) `(when (eq ,(char str 0) (char string start))
+          ((= l 1) `(when (and
+                           (< start (length string))
+                           (eq ,(char str 0) (char string start)))
                      (values (1+ start) ,str)))
           (t 
            `(when (starts-with string ,str :start start)
             (values end value)
             (grammar-or ,@rest)))))
 
-(defmacro grammar-n* (n x)
-  `(match-n ,n (grammar-wrap ,x) string :start start))
+(defmacro grammar-n (n x)
+  (if (> n 0)
+      (let ((n1 (1- n)))
+      `(multiple-value-bind (end value) (grammar-call ,x)
+        (when end
+          (let ((start end))
+            (multiple-value-bind (e v) (grammar-n ,n1 ,x)
+              (when e
+                (if (car v)
+                    (values e (cons value v))
+                    (values e (list value)))))))))
+      'start))
 
 (defmacro grammar-* (x)
   `(kleene* (grammar-wrap ,x) string :start start))