(use eggdoc) (define doc `((eggdoc:begin (name "lalr") (description "LALR(1) parser generator written in Scheme") (author "Dominique Boucher") (history (version "2.3.0" "Updated to upstream version 2.3.0; functionality split in two modules") (version "2.1.2" "Error-handler is now called with complete token") (version "2.1.1" "Fixed missing syntax attribute in setup script")) (requires) (usage (p "To generate the parser: " (pre #< EOF )) (p "In semantic actions, the symbol " (tt "$n") " refers to the synthesized attribute " "value of the nth symbol in the production. The value associated with the non-terminal " "on the left is the result of evaluating the semantic action (it defaults to " (tt "#f")"). ") (subsubsection "Operator precedence and associativity" (p "The above grammar implicitly handles operator precedences. " "It is also possible to explicitly assign precedences and associativity " "to terminal symbols and productions a la Yacc. " "Here is a modified (and augmented) version of the grammar: " (pre #<number (apply string (reverse l))))))) (read-id (lambda (l) (let ((c (peek-char))) (if (char-alphabetic? c) (read-id (cons (read-char) l)) (string->symbol (apply string (reverse l)))))))) ;; -- skip spaces (skip-spaces) ;; -- read the next token (let loop ((c (read-char))) (cond ((eof-object? c) '*eoi*) ((char=? c #\newline) 'NEWLINE) ((char=? c #\+) '+) ((char=? c #\-) '-) ((char=? c #\*) '*) ((char=? c #\/) '/) ((char=? c #\=) '=) ((char=? c #\,) 'COMMA) ((char=? c #\() 'LPAREN) ((char=? c #\)) 'RPAREN) ((char-numeric? c) (cons 'NUM (read-number (list c)))) ((char-alphabetic? c) (cons 'ID (read-id (list c)))) (else (errorp "PARSE ERROR : illegal character: " c) (skip-spaces) (loop (read-char)))))))) (define (read-line) (let loop ((c (read-char))) (if (and (not (eof-object? c)) (not (char=? c #\newline))) (loop (read-char))))) ;;; ;;;; Environment management ;;; (define *env* (list (cons '$$ 0))) (define (init-bindings) (set-cdr! *env* '()) (add-binding 'cos cos) (add-binding 'sin sin) (add-binding 'tan tan) (add-binding 'expt expt) (add-binding 'sqrt sqrt)) (define (add-binding var val) (set! *env* (cons (cons var val) *env*)) val) (define (get-binding var) (let ((p (assq var *env*))) (if p (cdr p) 0))) (define (invoke-proc proc-name args) (let ((proc (get-binding proc-name))) (if (procedure? proc) (apply proc args) (begin (display "ERROR: invalid procedure:") (display proc-name) (newline) 0)))) ;; value display (define (display-result v) (if v (begin (display "==> ") (display v) (newline)))) ;;; ;;;; The main program ;;; (define calc (lambda () (call-with-current-continuation (lambda (k) (display "********************************") (newline) (display "* Mini calculator in Scheme *") (newline) (display "* *") (newline) (display "* Enter expressions followed *") (newline) (display "* by [RETURN] or 'quit()' to *") (newline) (display "* exit. *") (newline) (display "********************************") (newline) (init-bindings) (add-binding 'quit (lambda () (k #t))) (letrec ((errorp (lambda args (for-each display args) (newline))) (start (lambda () (calc-parser (make-lexer errorp) errorp)))) (start)))))) (calc) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; END FILE: calc.scm ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; EOF )) (license "This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA A full copy of the GPL license can be found on Debian systems in /usr/share/common-licenses/GPL-2")))) (if (eggdoc->html doc) (void))