- Timestamp:
- 06/23/2007 06:11:55 AM (19 years ago)
- revision id:
- svn-v3-trunk0:2948df59-2b31-0410-8e06-c40c0b09d5b6:trunk:16
- Location:
- trunk
- Files:
-
- 2 edited
-
package.lisp (modified) (1 diff)
-
parse.lisp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/package.lisp
r15 r16 1 (defpackage #: parse1 (defpackage #:dso-parse 2 2 (:documentation 3 3 "Defines macros for matching input against rules and building trees -
trunk/parse.lisp
r3 r16 1 (defpackage #:parse2 (:use #:cl #:cl-ppcre)3 (:export #:defgrammar4 #:token))5 6 (in-package #:parse)7 8 9 10 (defstruct token11 class12 string)13 14 ;;;; A parser returns, as a list, all parts matched; and, the15 ;;;; remainder of the token-list. Named parts appear as sub-trees.16 17 18 19 (defmacro with-gensyms (syms &body body)20 `(let (,@(mapcar (lambda (sym) `(,sym (gensym ,(symbol-name sym)))) syms))21 ,@body))22 23 (defun substring (string &key (start 0) end length)24 (when (and end length) (error "Specify only one of END or LENGTH."))25 (when end (setf length (- end start)))26 (unless length (setf length (- (length string) start)))27 (make-array length28 :element-type 'character29 :displaced-to string30 :displaced-index-offset start))31 32 (defmacro scase (sym &body clauses)33 (with-gensyms (sym-name)34 `(let ((,sym-name (symbol-name ,sym)))35 (cond36 ,@(mapcar #'(lambda (clause)37 (if (eq t (first clause))38 clause39 (let ((clause-sym-name (symbol-name (first clause)))40 (clause-body (rest clause)))41 `((string= ,sym-name ,clause-sym-name)42 ,@clause-body))))43 clauses)))))44 45 (defmacro specials ((&body decls) &body body)46 "Like LET, but declares the bound variables to be special."47 `(let ,decls48 (declare (special ,@(mapcar #'first decls)))49 ,@body))50 51 (defun as-list (item) (if (listp item) item (list item)))52 53 54 55 56 57 ;; This is the entry-point for now.58 59 (defun make-parser (rule)60 (declare (ignore rule))61 nil)62 63 64 65 (defun parse-sequence (rule-parsers token-list tree)66 (if rule-parsers67 (multiple-value-bind (matched rlist mtree)68 (funcall (first rule-parsers) token-list)69 (when matched70 (parse-sequence (rest rule-parsers) rlist (append tree mtree))))71 (values t token-list tree)))72 73 (defun parse-choice (rule-parsers token-list)74 (if rule-parsers75 (multiple-value-bind (matched rlist mtree)76 (funcall (first rule-parsers) token-list)77 (if matched78 (values t rlist mtree)79 (parse-choice (rest rule-parsers) token-list)))80 nil))81 82 (defun parse-anycount (rule-parser token-list tree)83 (multiple-value-bind (matched rlist mtree) (funcall rule-parser token-list)84 (if matched85 (parse-anycount rule-parser rlist (append tree mtree))86 (values t token-list tree))))87 88 (defun parse-eqcount (count rule-parser token-list tree)89 (if (> count 0)90 (multiple-value-bind (matched rlist mtree)91 (funcall rule-parser token-list)92 (when matched93 (parse-eqcount (1- count) rule-parser rlist (append tree mtree))))94 (values t token-list tree)))95 96 (defun parse-mincount (count rule-parser token-list tree)97 (if (> count 0)98 (multiple-value-bind (matched rlist mtree)99 (funcall rule-parser token-list)100 (when matched101 (parse-mincount (1- count) rule-parser rlist (append tree mtree))))102 (parse-anycount rule-parser token-list tree)))103 104 (defun parse-maxcount (count rule-parser token-list tree)105 (if (> count 0)106 (multiple-value-bind (matched rlist mtree)107 (funcall rule-parser token-list)108 (if matched109 (parse-maxcount (1- count) rule-parser rlist (append tree mtree))110 (values t token-list tree)))111 (values t token-list tree)))112 113 114 115 ;; This needs to be changed to just use the function of the given116 ;; symbol-name, so that any format of sequence may be supported.117 (defun make-token-parser (token-class)118 (declare (special definition-names119 *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))123 (if (member token-class definition-names)124 `(function ,token-class)125 (with-gensyms (token-list token)126 `(lambda (,token-list)127 (let ((,token (first ,token-list)))128 (when (and ,token-list (eq (token-class ,token) ',token-class))129 (values t (rest ,token-list) (list ,token))))))))130 131 (defun make-character-parser (ch)132 (with-gensyms (str)133 `(lambda (,str)134 (when (and (> (length ,str) 0) (char= (char ,str 0) ,ch))135 (values136 t137 (substring ,str :start 1)138 (list ,ch))))))139 140 (defun make-regex-parser (regex)141 (declare (special *regex-flags*))142 (let ((regex `(:sequence (:flags ,@*regex-flags*) :start-anchor143 (:register (:regex ,regex)))))144 (with-gensyms (str start end)145 `(lambda (,str)146 (multiple-value-bind (,start ,end) (scan (quote ,regex) ,str)147 (when ,start148 (values149 t150 (substring ,str :start ,end)151 (list (substring ,str :end ,end)))))))))152 153 154 (defun make-sequence-parser (rules)155 (with-gensyms (rule-parsers token-list)156 `(let ((,rule-parsers (list ,@(mapcar #'make-parser rules))))157 (lambda (,token-list) (parse-sequence ,rule-parsers ,token-list nil)))))158 159 (defun make-choice-parser (rules)160 (with-gensyms (rule-parsers token-list)161 `(let ((,rule-parsers (list ,@(mapcar #'make-parser rules))))162 (lambda (,token-list) (parse-choice ,rule-parsers ,token-list)))))163 164 (defun make-anycount-parser (rule)165 (with-gensyms (rule-parser token-list)166 `(let ((,rule-parser ,(make-parser rule)))167 (lambda (,token-list) (parse-anycount ,rule-parser ,token-list nil)))))168 169 (defun make-eqcount-parser (count rule)170 (with-gensyms (rule-parser token-list)171 `(let ((,rule-parser ,(make-parser rule)))172 (lambda (,token-list)173 (parse-eqcount ,count ,rule-parser ,token-list nil)))))174 175 (defun make-maxcount-parser (count rule)176 (with-gensyms (rule-parser token-list)177 `(let ((,rule-parser ,(make-parser rule)))178 (lambda (,token-list)179 (parse-maxcount ,count ,rule-parser ,token-list nil)))))180 181 (defun make-0or1-parser (rule) (make-maxcount-parser 1 rule))182 183 (defun make-+-parser (rule)184 (with-gensyms (rule-parser token-list)185 `(let ((,rule-parser ,(make-parser rule)))186 (lambda (,token-list)187 (parse-mincount 1 ,rule-parser ,token-list nil)))))188 189 (defun make-required-pred (rule)190 (with-gensyms (rule-parser token-list)191 `(let ((,rule-parser ,(make-parser rule)))192 (lambda (,token-list)193 (when (funcall ,rule-parser ,token-list)194 (values t ,token-list nil))))))195 196 (defun make-forbidden-pred (rule)197 (with-gensyms (rule-parser token-list)198 `(let ((,rule-parser ,(make-parser rule)))199 (lambda (,token-list)200 (unless (funcall ,rule-parser ,token-list)201 (values t ,token-list nil))))))202 203 (defun make-match-parser (rule)204 (with-gensyms (rule-parser token-list matched rlist)205 `(let ((,rule-parser ,(make-parser rule)))206 (lambda (,token-list)207 (multiple-value-bind (,matched ,rlist)208 (funcall ,rule-parser ,token-list)209 (when ,matched (values t ,rlist nil)))))))210 211 (defmacro dispatch (sym fun)212 `(progn213 (when (cddr rule) (error ,(format nil "~A takes one argument" sym)))214 (,fun (second rule))))215 216 (setf (symbol-function 'make-parser) (lambda (rule)217 (etypecase rule218 (symbol (make-token-parser rule))219 (character (make-character-parser rule))220 (string (make-regex-parser rule))221 (list222 (if (symbolp (first rule))223 (scase (first rule)224 (& (dispatch & make-required-pred))225 (! (dispatch ! make-forbidden-pred))226 (* (dispatch * make-anycount-parser))227 (? (dispatch ? make-0or1-parser))228 (+ (dispatch + make-+-parser))229 (= (make-match-parser (cdr rule)))230 (/ (make-choice-parser (cdr rule)))231 (t (make-sequence-parser rule)))232 (make-sequence-parser rule))))))233 234 235 236 237 1 (defun hash-names (names &optional (map (make-hash-table))) 238 2 (if names
Note: See TracChangeset
for help on using the changeset viewer.
