Skip to content

Instantly share code, notes, and snippets.

@m2ym
Created December 22, 2011 09:30
Show Gist options
  • Select an option

  • Save m2ym/1509674 to your computer and use it in GitHub Desktop.

Select an option

Save m2ym/1509674 to your computer and use it in GitHub Desktop.
Example usage of Allegro CL's yacc module
(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))))
@m2ym
Copy link
Author

m2ym commented Dec 22, 2011

There is no aclyacc documentation at present. This little code tells you how to use aclyacc actually.

@m2ym
Copy link
Author

m2ym commented Dec 22, 2011

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