#lang racket ;;; parser1.rkt - Sections 15.1 et 15.2 du chapitre 15 (Analyseurs Syntaxiques) ;;; Livre PCPS : "Premiers Cours de Programmation avec Scheme" ;;; Langage determine par le source (require "show.rkt") ; pour les tests (provide string->poly) ;;; Un analyseur syntaxique de polynomes en x ;;; (string->poly "+53x^4+1-25.6x") --> ((53 4) (-25.6 1) (1 0)) (require parser-tools/lex) (require parser-tools/yacc) (provide get-lexeme parse string->poly) ;;; le lexeur == analyseur lexical [il cherche les mots a partir des caracteres] (define-lex-abbrevs (chiffre (char-range "0" "9")) (entier (repetition 1 +inf.0 chiffre)) (flottant (concatenation entier "." entier)) (nombre (union entier flottant)) (var (union "x" "X"))) (define-tokens value-tokens (NUM)) (define-empty-tokens op-tokens (x + - ^ FINI)) (define get-lexeme (lexer [(eof) 'FINI] [(union "+" "-" "^") (string->symbol lexeme)] [var 'x] [nombre (token-NUM (string->number lexeme))])) ; testing the lexer (define str-poly "-5x^8+x^7-2.51x+450") (show str-poly) (call-with-output-file "poly.txt" ; fichier contenant le polynome (lambda (p-out) (fprintf p-out "~a" str-poly)) #:exists 'replace) (define (test-lexer p-in) ; test du lexeur sur le port d'entree p-in (let ((lexeur (lambda () (get-lexeme p-in)))) (do ((i 0 (+ i 1)) (obj (lexeur) (lexeur))) ((equal? obj 'FINI) (printf "~a lexemes ont ete lus.\n" i)) (printf "~a\n" obj)))) "test du lexeur avec le fichier poly.txt" (define (test-lexer-file) (call-with-input-file "poly.txt" test-lexer)) (show (test-lexer-file)) "test du lexeur avec la chaine" (define (test-lexer-string) (call-with-input-string str-poly test-lexer)) ; (show (test-lexer-string)) "test du lexeur interactif" (define (test-lexer-toplevel) (printf "Entrez un polynome : ") (call-with-input-string (read-line) test-lexer)) ;(show (test-lexer-toplevel)) ;;; le parseur == analyseur syntaxique [il cherche la phrase a partir des mots] (define parse (parser (start poly) ; j'essaye de reconnaitre un polynome (end FINI) ; l'analyse stoppe sur le lexeme FINI (tokens value-tokens op-tokens) ; definis dans le lexeur (error (lambda (a b c) (printf "Erreur d'analyse : ~a\n" (list a b c)))) (grammar ; la grammaire en style Yacc (poly [() '()] ; le polynome identiquement nul se represente par '() [(poly mono) `(,@$1 ,$2)]) ; recursivite GAUCHE (mono [(+ NUM x ^ NUM) `(,$2 ,$5)] ; +23x^4 [(- NUM x ^ NUM) `(,(- $2) ,$5)] ; -23x^4 [(+ NUM x) `(,$2 1)] ; +24x [(+ NUM) `(,$2 0)] ; +24 [(- NUM x) `(,(- $2) 1)] ; -24x [(- NUM) `(,(- $2) 0)] ; -24 [(+ x) `(1 1)] ; +x [(+ x ^ NUM) `(1 ,$4)] ; +x^4 [(- x) `(-1 1)] ; -x [(- x ^ NUM) `(-1 ,$4)])))) ; -x^4 (define (string->poly str) (when (not (member (string-ref str 0) '(#\+ #\-))) (set! str (string-append "+" str))) (let* ((p-in (open-input-string str)) (lexeur (lambda () (get-lexeme p-in))) (L (parse lexeur))) (sort L (lambda (monome1 monome2) (>= (second monome1) (second monome2)))))) "test de string->poly" (define (test-parser) (let* ((str "53.0x^2+x-256.789X^3-x^8-1.5+x^4") (p (string->poly str))) (printf "Je teste string->poly :\n~s --> ~a\n" str p))) (show (test-parser)) (define (test-interactive-parser) (printf "Entrez un polynome en x : ") (let* ((str (read-line)) (p (string->poly str))) (printf "Je teste string->poly :\n~s --> ~a\n" str p))) (show (test-interactive-parser))