Changeset trunk,3 for trunk


Ignore:
Timestamp:
06/07/2007 10:11:03 PM (19 years ago)
Author:
dsowen
revision id:
svn-v3-trunk0:2948df59-2b31-0410-8e06-c40c0b09d5b6:trunk:3
Message:

Parser now fairly usable.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/parse.lisp

    r2 r3  
    88
    99
    10 
    1110(defstruct token
    1211  class
    1312  string)
    14 
    15 #|
    16 (defmacro defparser (name &body body))
    17 
    18 (defparser blah
    19 /  (simple ident)                       ; matches token class
    20 /  (seq-ex (e1 e2))                     ; matches e1 followed by e2
    21 /  (choice-ex (/ e1 e2))                        ; matches e1, or else e2
    22 /  (not-ex (! e1 e2))                   ; matches if not e1, and if not e2
    23 /  (require-ex (& e1 e2))               ; matches if e1, and if e2 (pointless)
    24   (kleene-ex1 (* e1 e2))                ; matches e1* e2*
    25   (kleene-ex2 (* (e1 e2)))              ; matches (e1 e2)*
    26   (req-ex1 (+ e1 e2))                   ; matches e1+ e2+
    27   (req-ex2 (+ (e1 e2)))                 ; (e1 e2)+
    28   (match-only (: e1 e2))                ; matches and consumes, but
    29                                         ; doesn't emit
    30   (match-only (: (e1 e2))))
    31 
    32 (defparser minijava-parser
    33   (program (main-class (* class-decl)))
    34   (main-class
    35    ((: class)
    36     ident
    37     (: lbrace public static void main lparen string lbracket rbracket ident
    38        rparen lbrace)
    39     statement
    40     (: rbrace rbrace)))
    41   (ident id)
    42   (statement (/ block if while print assign array-assign))
    43   (block ((: lbrace) (* statement) (: rbrace)))
    44   (if ((: if lparen) exp (: rparen) statement (: else) statement))
    45   (while ((: while lparen) exp (: rparen) statement))
    46   (print ((: sop lparen) exp (: rparen semicolon)))
    47   (exp (/ num)))
    48 
    49 (class (id "A") lbrace public static void main lparen string lbracket rbracket
    50        (id "args") rparen lbrace sop lparen (num 0) rparen semicolon rbrace
    51        rbrace)
    52 
    53 (program
    54  (main-class
    55   (ident "A")
    56   (statement
    57    (print
    58     (num 0)))))
    59 |#
    60 
    6113
    6214;;;; A parser returns, as a list, all parts matched; and, the
     
    9143                  clauses)))))
    9244
     45(defmacro specials ((&body decls) &body body)
     46  "Like LET, but declares the bound variables to be special."
     47  `(let ,decls
     48    (declare (special ,@(mapcar #'first decls)))
     49    ,@body))
     50
     51(defun as-list (item) (if (listp item) item (list item)))
     52
    9353
    9454
     
    153113
    154114
     115;; This needs to be changed to just use the function of the given
     116;; symbol-name, so that any format of sequence may be supported.
    155117(defun make-token-parser (token-class)
    156   (declare (special definition-names))
     118  (declare (special definition-names
     119                    *import*))
     120  (unless (or (member token-class definition-names)
     121              (member token-class *import*))
     122    (warn "Parser ~A is neither defined nor imported." token-class))
    157123  (if (member token-class definition-names)
    158124      `(function ,token-class)
     
    173139
    174140(defun make-regex-parser (regex)
    175   (let ((regex `(:sequence (:flags :single-line-mode-p) :start-anchor
     141  (declare (special *regex-flags*))
     142  (let ((regex `(:sequence (:flags ,@*regex-flags*) :start-anchor
    176143                 (:register (:regex ,regex)))))
    177144    (with-gensyms (str start end)
     
    276243
    277244(defun make-named-parser (name rule)
     245  (declare (special *filter*))
    278246  `(defun ,name (token-list)
    279247    (let ((parser ,(make-parser rule)))
    280248      (multiple-value-bind (matched rlist mtree) (funcall parser token-list)
    281249        (when matched
    282           (values t rlist (list (append (list (quote ,name)) mtree))))))))
     250          (values t
     251                  rlist
     252                  ,(if *filter*
     253                       `(list (append (list (quote ,name)) (,*filter* mtree)))
     254                       `(list (append (list (quote ,name)) mtree))
     255)))))))
    283256
    284257(defun make-named-class (name rule)
     258  (declare (special *filter*))
    285259  `(defun ,name (token-list)
    286260    (let ((parser ,(make-parser rule)))
    287       (funcall parser token-list))))
    288 
    289 (defun make-named (class-names definition)
    290   (let ((name (car definition))
    291         (rule (cadr definition)))
    292     (if (member name class-names)
    293         (make-named-class name rule)
    294         (make-named-parser name rule))))
    295 
    296 (defmacro defgrammar (classes &body definitions)
    297   (let ((definition-names (mapcar #'first definitions)))
    298     (declare (special definition-names))
    299     (let ((rule-map (hash-names definition-names))
    300           (make (lambda (definition) (make-named classes definition))))
    301       (declare (special rule-map))
     261      ,(if *filter*
     262           `(multiple-value-bind (matched rlist mtree)
     263             (funcall parser token-list)
     264             (when matched
     265               (values t rlist (,*filter* mtree))))
     266           `(funcall parser token-list)))))
     267
     268(defun make-named (definition)
     269  (declare (special *classes*))
     270  (destructuring-bind (name rule &key filter) definition
     271    (specials ((*filter* filter))
     272      (if (member name *classes*)
     273          (make-named-class name rule)
     274          (make-named-parser name rule)))))
     275
     276(defmacro defgrammar ((&key classes import regex-flags skip)
     277                      &body definitions)
     278  (specials ((*classes* classes)
     279             (*import* import)          ; used only for warnings
     280             (*regex-flags* (as-list regex-flags))
     281             (*skip* skip)              ; unused
     282             (definition-names (mapcar #'first definitions)))
     283    (let ((rule-map (hash-names definition-names)))
    302284      `(progn
    303         ,@(mapcar make definitions)))))
     285        ,@(mapcar #'make-named definitions)))))
    304286
    305287#|
    306 dot-all
    307 single-line
    308 import section
    309 skip tokens
     288dot-all dot recognizes line-breaks
     289single-line matches extend across lines
     290import section supress warnings
     291skip tokens automatically allow these between all parts
    310292|#
Note: See TracChangeset for help on using the changeset viewer.