#lang racket ;;; mfcalc-parser.rkt avec entiers, flottants, booleens et deux fonctions exp et log ;;; avec affectation et variables. Conditionnelle sans conflit. ;;; Les variables sont stockees avec leurs valeurs dans une table de hash-code. ;;; Exercice 15.5.5 du chapitre 15 (Analyseurs Syntaxiques) ;;; Livre PCPS : "Premiers Cours de Programmation avec Scheme" ;;; Langage determine par le source ;;; mfcalc-parser.ss avec affectation et variables. Conditionnelle sans conflit. ;;; Les variables sont stockees avec leurs valeurs dans une table de hash-code. (require "mfcalc-lexer.rkt") (require parser-tools/yacc) ; On maintient les valeurs des variables dans une table de hash-code, plus efficace qu'une A-liste (define vars (make-hash)) (define ns (make-base-namespace)) ; pour eval ; Definition du parser (define parse (parser (start S) (end EOF) (tokens value-tokens op-tokens) (error (lambda (a b c) (printf "Parsing error with token ~a\n" b))) (precs (nonassoc LOWER_THAN_ELSE) (nonassoc ELSE) (nonassoc < > <= >= == !=) (right =) (left - +) (left * /) (left NEG) (right ^)) (grammar (S [(expr) $1]) (expr [(NUM) $1] [(BOOL) (eq? $1 'true)] [(VAR) (hash-ref vars $1 (lambda () 0))] ; consultation d'une valeur de variable [(VAR = expr) (begin (hash-set! vars $1 $3) $3)] ; modification de la valeur d'une variable [(FNCT LPAR expr RPAR) ((eval $1 ns) $3)] ; appel de fonction [(expr + expr) (+ $1 $3)] [(expr - expr) (- $1 $3)] [(expr * expr) (* $1 $3)] [(expr / expr) (/ $1 $3)] [(- expr) (prec NEG) (- $2)] [(expr ^ expr) (expt $1 $3)] [(expr > expr) (> $1 $3)] [(expr >= expr) (>= $1 $3)] [(expr < expr) (< $1 $3)] [(expr <= expr) (<= $1 $3)] [(expr == expr) (equal? $1 $3)] [(expr != expr) (not (equal? $1 $3))] [(LPAR expr RPAR) $2] [(IF expr THEN expr ELSE expr) (if $2 $4 $6)] [(IF expr THEN expr) (prec LOWER_THAN_ELSE) (if $2 $4 (void))])))) (printf "Generation du mfcalc parser... ok. Aucun conflit. Utilisez des variables, ainsi que les fonctions exp et log.\n") (define (lexeur str) ; un analyseur lexical sur une string (call-with-input-string str (lambda (p-in) (lambda () (get-lexeme p-in))))) (define (mfcalc) ; le calculateur interactif de Bison (printf "? ") (let ((str (read-line))) (if (or (eof-object? str) (string=? str "quit")) 'bye (begin (printf "==> ~a\n" (parse (lexeur str))) (mfcalc))))) (mfcalc) ; run !