; ; Bootstrapping a parser generator ; ; This defines a parser for the BNF-based syntax used here. ; grammar = prod* ;grammar = prod_debug* prod_debug = {prod:p} -> (begin (when (>= *LOGLEVEL* 2) (printf "~%;>>> ~a~%" (read-parsed-text)) (pretty-print p) ) p) prod = comments name:n [ws '=' rules:rs] [action:a] -> (declare-locals n rs a) rules = seq:s {ws '|' seq}*:ss -> (if (empty? ss) s (cons 'or (cons s ss))) seq = rule:r rule*:rs -> (if (empty? rs) r (cons 'and (cons r rs))) rule = {group | option | scheme | lit | atom}:item [{'+' | '*'}]:repeat [':' name:var] -> (let ((x (cond ((equal? repeat "+") `(r+ ,item)) ((equal? repeat "*") `(r* ,item)) (else item) ))) (if var `(setf ,var ,x) x)) group = ws '{' rules:rs ws '}' -> `(and ,rs) option = ws '[' rules:rs ws ']' -> `(or ,rs #t) ; scheme = ws '(' ... ')' comments = {comment | nl}* comment = ';' not_nl* nl action = ws '->' ws atext atext = {nl {ws_ line}* | line} -> (read-parsed-text) ; (read-from-string (substring *s* __start *i*)) ; Match everything to end of line line = not_nl* nl ; Match a grammatical atom 'name' -- return it as (name) atom = {name:n} -> (list n) test = { (list ' (foo bar)):x } -> (car x)