LL(1) 構文解釈できた

とりあえず解釈できた。やはり (setq change nil) が抜けていたのと iconst が抜けていたというバグがあった。それ以外は問題なし。ついでなので簡単なリードマクロを作った。リードマクロを使うと

(setq *rules*
        '#%END
        program         ::= statlist
        statlist        ::= stat statlist
        statlist        ::=
        stat            ::= ident = expr ;
        stat            ::= read ident ;
        stat            ::= print expr ;
        stat            ::= if ( cond ) stat
        stat            ::= { statlist }
        cond            ::= expr relop expr
        relop           ::= <
        relop           ::= >
        expr            ::= ident
        expr            ::= iconst
        END
)

とかける。だだし | はない。本格的に bnf を書こうと思うと bnf を解釈する bnf が必要だ。なんだかわからない。リードマクロの主要部分だけのせておこう。

        (if (char= #\newline curr)
          (let* ((oneline-str (string-concat "(" (coerce (nreverse oneline-char)
 'string) ")"))
                 (ln (mapcan (lambda (x)
                                 (cond ((eq x '::=) nil)
                                       ((symbolp x) (list x))
                                       ((char= x #\;) (list 'semi))
                                       ((char= x #\() (list 'lpar))
                                       ((char= x #\)) (list 'rpar))
                                       (t (error "parse error"))))
                               (read-from-string oneline-str))))
            ;(format t "~a~%" oneline-str)
            (setf oneline-char nil)
            (if (not (null ln))
              (setf output (cons ln output))))
          (progn
            (if (or (eq #\( curr)
                    (eq #\) curr)
                    (eq #\; curr))
              (progn
                (push #\# oneline-char)
                (push #\\ oneline-char)))
            (push curr oneline-char)))

リードマクロを作るマクロが欲しくなってきた。