Created
December 22, 2011 09:30
-
-
Save m2ym/1509674 to your computer and use it in GitHub Desktop.
Example usage of Allegro CL's yacc module
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (in-package :cl-user) | |
| (eval-when (:compile-toplevel :load-toplevel :execute) | |
| (when (find-package :quicklisp) | |
| (quicklisp:quickload '(:anaphora :cl-ppcre))) | |
| (require :yacc)) | |
| (defpackage :calc | |
| (:use :cl :anaphora :excl.yacc)) | |
| (in-package :calc) | |
| (eval-when (:compile-toplevel :load-toplevel :execute) | |
| (defgrammar calc-grammar (excl.yacc:grammar) | |
| () | |
| (:left-associative +) | |
| (:left-associative -) | |
| (:left-associative *) | |
| (:left-associative /) | |
| (:lexemes number + - * / |(| |)|))) | |
| (defproduction (calc-grammar calc-grammar) | |
| (expr eof) | |
| ($1)) | |
| (defproduction (expr calc-grammar) | |
| (expr + fact) | |
| ((+ $1 $3))) | |
| (defproduction (expr calc-grammar) | |
| (expr - fact) | |
| ((- $1 $3))) | |
| (defproduction (expr calc-grammar) | |
| (fact) | |
| ($1)) | |
| (defproduction (fact calc-grammar) | |
| (fact * term) | |
| ((* $1 $3))) | |
| (defproduction (fact calc-grammar) | |
| (fact / term) | |
| ((/ $1 $3))) | |
| (defproduction (fact calc-grammar) | |
| (term) | |
| ($1)) | |
| (defproduction (term calc-grammar) | |
| (|(| expr |)|) | |
| ($2)) | |
| (defproduction (term calc-grammar) | |
| (number) | |
| ($1)) | |
| (build-grammar calc-grammar nil nil) | |
| (mop:finalize-inheritance (find-class 'calc-grammar)) | |
| (defstruct (buffer (:constructor make-buffer (string))) | |
| string (pos 0)) | |
| (defun buffer-eofp (buffer) | |
| (= (length (buffer-string buffer)) (buffer-pos buffer))) | |
| (defun buffer-scan (regex buffer) | |
| (with-slots (string pos) buffer | |
| (multiple-value-bind (match-start match-end reg-starts reg-ends) | |
| (ppcre:scan regex string :start pos) | |
| (when match-start | |
| (setf pos match-end) | |
| (if (zerop (length reg-starts)) | |
| (subseq string match-start match-end) | |
| (subseq string (elt reg-starts 0) (elt reg-ends 1))))))) | |
| (defun make-lexer (buffer) | |
| (lambda (&optional grammar op) | |
| (multiple-value-bind (token value) | |
| (lex buffer op) | |
| (values (tcode-1 (class-of grammar) token) | |
| value)))) | |
| (defmethod lex ((buffer buffer) (op null)) | |
| (buffer-scan "^\\s*" buffer) | |
| (when (buffer-eofp buffer) | |
| (return-from lex 'eof)) | |
| (acond | |
| ((buffer-scan "^[-+*/\\(\\)]" buffer) | |
| (values (intern it))) | |
| ((buffer-scan "^\\d+" buffer) | |
| (values 'number (parse-integer it))) | |
| (t | |
| (error "invalid token character: ~A" | |
| (char (buffer-string buffer) (buffer-pos buffer)))))) | |
| (defmethod lex ((buffer buffer) (op (eql :report-location)))) |
Author
Author
However, as you can see if you run this code like (excl.yacc:parse (make-instance 'calc-grammar :lexer (make-lexer (make-buffer "(1+2)*3-4")))), this code doesn't parse the input correctly. I don't understand why and can conclude that a reason why the lack of documentation is that aclyacc is not at production stage (no explanatory error message, no debugger, LL? or LR?). So don't use aclyacc at now.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
There is no aclyacc documentation at present. This little code tells you how to use aclyacc actually.