- Timestamp:
- 06/23/2007 04:30:57 AM (19 years ago)
- revision id:
- svn-v3-trunk0:2948df59-2b31-0410-8e06-c40c0b09d5b6:trunk:13
- File:
-
- 1 edited
-
trunk/parse3.lisp (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/parse3.lisp
r12 r13 1 (in-package #:dso-parse)1 ;(in-package #:dso-parse) 2 2 3 3 … … 29 29 `(if (and (string/= "" ,input) (char= ,char (char ,input 0))) 30 30 (let ((,next (substring ,input :start 1)) 31 (,match '(,char)))31 (,match ,char)) 32 32 ,then) 33 33 ,else)) … … 42 42 (string= ,string (substring ,input :length ,len))) 43 43 (let ((,next (substring ,input :start ,len)) 44 (,match '(,string)))44 (,match ,string)) 45 45 ,then) 46 46 ,else))) … … 58 58 (if ,start 59 59 (let ((,next (substring ,input :start ,end)) 60 (,match ( list (substring ,input :end ,end))))60 (,match (substring ,input :end ,end))) 61 61 ,then) 62 62 ,else))))) … … 86 86 `(if-matches ,input ,head (,head-next ,head-match) 87 87 (if-matches-sequence ,head-next ,tail (,next ,tail-match) 88 (let ((,match ( cons ,head-match,tail-match)))88 (let ((,match (if ,head-match (cons ,head-match ,tail-match) ,tail-match))) 89 89 ,then) 90 90 ,else) … … 92 92 (with-gensyms (tail-match) 93 93 `(if-matches ,input ,head (,next ,tail-match) 94 (let ((,match ( list ,tail-match)))94 (let ((,match (if ,tail-match (list ,tail-match) nil))) 95 95 ,then) 96 96 ,else))))) … … 110 110 (if-matches ,next ,rule (,next2 ,match2) 111 111 (setf ,next ,next2 112 ,match ( cons ,match2,match))112 ,match (if ,match2 (cons ,match2 ,match) ,match)) 113 113 (return-from ,r ,else))) 114 114 (setf ,match (nreverse ,match)) … … 131 131 (progn 132 132 (psetf ,next ,next2 133 ,match ( cons ,match2,match)133 ,match (if ,match2 (cons ,match2 ,match) ,match) 134 134 ,i (1+ ,i)) 135 135 t))))) … … 152 152 ,else))) 153 153 154 ;;; The required and forbidden rules don't quite work right, as using155 ;;; a rule like (#\a (& #\b)) will put an extaneous NIL on the end of156 ;;; the match tree.157 158 154 (defmacro if-matches-required (input rule (next match) 159 155 &body (&optional (then t) else)) 156 "Matches if RULE matches against INPUT, but neither consumes input 157 nor contributes to the parse tree." 160 158 `(if-matches ,input ,rule (,(gensym) ,(gensym)) 161 159 (let ((,next ,input) … … 166 164 (defmacro if-matches-forbidden (input rule (next match) 167 165 &body (&optional (then t) else)) 166 "Matches if RULE doesn't match against INPUT, but neither consumes 167 input nor contributes to the parse tree." 168 168 `(if-matches ,input ,rule (,(gensym) ,(gensym)) 169 169 ,else … … 174 174 (defmacro if-matches-only (input rule (next match) 175 175 &body (&optional (then t) else)) 176 (with-gensyms (match2) 177 `(if-matches ,input ,rule (,next ,match2) 178 (let ((,match nil)) 179 ,then) 180 ,else))) 176 "Matches RULE against INPUT and consumes input, but doesn't 177 contribute to the parse tree." 178 `(if-matches ,input ,rule (,next ,match) 179 (let ((,match nil)) 180 ,then) 181 ,else)) 181 182 182 183 (defmacro if-matches (input rule (next match) &body (&optional (then t) else)) 184 "Matches RULE against INPUT. If the rule is matched, the THEN form 185 is executed with NEXT bound to the remainder of the input after 186 consumption (if any), and MATCH to the parse tree. 187 188 Rules may be defined in a short-hand using this macro, and nested: 189 190 * Characters and strings match themselves. 191 192 * A regular expression is denoted as (^ regex). 193 194 * A sequence is a list of rules (rule1 rule2) that doesn't begin with 195 a reserved mark. 196 197 * An ordered choice is (/ rule1 rule2). 198 199 * A Kleene-closure is (* rule). + and ? may be used as well, and all 200 act as in regular expressions. 201 202 * Range matching is ({} min max rule). If MIN is NIL, it is treated 203 as 0. If MAX is NIL, no limit is placed on matches. 204 205 * Requiring a match without consuming or tree-building is done as (& 206 rule). Forbidding a match likewise as (! rule). 207 208 * Matching and consuming without tree-building is (= rule). 209 210 If RULE is a symbol, that symbol will be used as the name of a parsing 211 function. The function will be given the input as its only argument, 212 and is expected to return (VALUES T NEXT MATCH) (where NEXT refers to 213 the remaining, unsonsumed input, and MATCH is the generated tree), or 214 NIL otherwise." 183 215 (etypecase rule 184 216 (symbol `(if-matches-parser ,input ,rule (,next ,match) ,then ,else))
Note: See TracChangeset
for help on using the changeset viewer.
