some real-world rules now work
authorD Herring <dherring@at.tentpost.dot.com>
Tue, 13 Mar 2012 05:01:37 +0000 (01:01 -0400)
committerD Herring <dherring@at.tentpost.dot.com>
Tue, 13 Mar 2012 05:01:37 +0000 (01:01 -0400)
examples/extensible-parser-example.lisp
extensible-parser.lisp

index 40fa54f..a1c213c 100644 (file)
@@ -8,6 +8,11 @@
 
 (defparameter *c++-mode* nil "indicate that we are parsing C++ code")
 
+(defun ascii-range (string start end char0 char1)
+  (when (< start end)
+    (let ((c (char string start)))
+      (when (<= (char-code char0) (char-code c) (char-code char1))
+        (values (1+ start) c)))))
 
 ;; any                = [\t\v\f\r\n\040-\377];
 (defrule any
 
 ;; anyctrl            = [\001-\037];
 (defrule anyctrl
-    (ascii-range 1 31))
+  (ascii-range 1 31))
 
 ;; OctalDigit         = [0-7];
 (defrule octal-digit
-    (ascii-range #\0 #\7))
+  (ascii-range #\0 #\7))
 
 ;; Digit              = [0-9];
 (defrule digit
-    (ascii-range #\0 #\9))
+  (ascii-range #\0 #\9))
 
 ;; HexDigit           = [a-fA-F0-9];
 (defrule hex-digit
    (ascii-range #\0 #\9)))
 
 ;; Integer            = (("0" [xX] HexDigit+) | ("0" OctalDigit*) | ([1-9] Digit*));
-(defrule integer
-    (or
-     (and #\0 (or #\x #\X) (repeat 1 * hex-digit))
-     (and #\0 (repeat 0 * octal-digit))
-     (and (ascii-range #\1 #\9) (repeat 0 * digit))))
+(defrule r-integer
+  (or
+   (:cl
+    (let ((match (:parse (and #\0 (or #\x #\X) (repeat 1 nil (hex-digit))))))
+      (when match
+        (values match
+                (parse-integer (subseq string (+ start 2) match) :radix 16)))))
+   (:cl
+    (let ((match (:parse (and #\0 (repeat 0 nil (octal-digit))))))
+      (when match
+        (values match
+                (parse-integer (subseq string (+ start 1) match) :radix 8)))))
+   (:cl
+    (let ((match (:parse (and (ascii-range #\1 #\9) (repeat 0 nil (digit))))))
+      (when match
+        (values match
+                (parse-integer (subseq string start match) :radix 10)))))))
 
 ;; ExponentStart      = [Ee] [+-];
 (defrule exponent-start
index 854140a..8a13886 100644 (file)
@@ -280,7 +280,7 @@ or to allow changes to the rule,
                 (if (eql (car c) key)
                     (progn
                       (unless (= (length c) 2)
-                        (error "expected (:parse x), got ~S" c))
+                        (error "expected (:parse rule), got ~S" c))
                       (setf (car x) `(cpf-macro ,(cadr c) ,context)))
                     (expand-nested-parse c context key)))))
           form))
@@ -289,7 +289,12 @@ or to allow changes to the rule,
 (defmethod cpf-list ((car (eql :cl)) form context env)
   "bind a cpf context and invoke any nested call sites"
   ;; should this bind a new context?  skip for now...
-  (expand-nested-parse (cdr form) context))
+  (unless (= (length form) 2)
+    (error "expected (:cl form), got ~S" form))
+  (expand-nested-parse (cadr form) context))
+
+(defrule test-cl
+  (:cl (and (:parse "hi"))))
 
 #| original nested method
  (defmethod cpf-list ((car (eql and)) form context)