15. Des Analyseurs Syntaxiques
1 Exercice 15.5.1
2 Exercice 15.5.2
3 Exercice 15.5.3
4 Exercice 15.5.4
5 Exercice 15.5.5
6 Exercice 15.5.6
6.0.1.11

15. Des Analyseurs Syntaxiques

1 Exercice 15.5.1

Je vous le laisse... Cela ne devrait pas poser de problème si vous avez étudié le chapitre 14.

2 Exercice 15.5.2

Je me contente de faire un lexeur, puis d’utiliser get-lexeme en boucle... L’exemple est interactif, mais une modification minime l’étendrait à un fichier quelconque f.

#lang racket

(require parser-tools/lex)

 

(define-lex-abbrevs

  [digit (char-range "0" "9")]

  [int (repetition 1 +inf.0 digit)]

  [float (concatenation int "." int)]

  [ratio (concatenation int "/" int)]

  [numpos (union int float ratio)]

  [num (union numpos (concatenation "-" numpos))]

  [other (char-range #\u0000 #\u00FF)])

 

(define-empty-tokens op-tokens (FINI))

 

(define get-lexeme

  (lexer

    [(eof) 'FINI]

    [num (string->number lexeme)]

    [any-char (get-lexeme input-port)]))

> (call-with-input-string "attaqueau-53.6Nord-Wcontinue!!Les105bateauxdetruitsaux11/20nesontplus"

    (lambda (p-in)

      (do ((x (get-lexeme p-in) (get-lexeme p-in)) (L '() (cons x L)))

        ((equal? x 'FINI) (reverse L)))))

(-53.6 105 11/20)

3 Exercice 15.5.3

Tout d’abord le lexeur :

#lang racket

(require parser-tools/lex parser-tools/yacc)

 

(define-lex-abbrevs

  [espace (union #\newline #\return #\tab #\space)]   ; whitespace est prédéfini !

  [other (char-range #\u0000 #\u00FF)])

 

(define-tokens word-tokens (ART NAME ADJ VERB CONJSUB))

 

(define-empty-tokens op-tokens (DOT EOF))

 

(define get-lexeme

  (lexer

    [(eof) 'EOF]

    ["." 'DOT]

    [(repetition 1 +inf.0 espace) (get-lexeme input-port)]

    [(union "le" "la") (token-ART (string->symbol lexeme))]

    [(union "chien" "souris" "chat" "cat") (token-NAME (string->symbol lexeme))]

    [(union "petit" "gentil" "petite") (token-ADJ (string->symbol lexeme))]

    [(union "mange" "aboie" "dort") (token-VERB (string->symbol lexeme))]

    [(union "qui" "que") (token-CONJSUB (string->symbol lexeme))]

    [other (error "Unparseable" (string->symbol lexeme))]))

Je teste interactivement le lexeur :

> (call-with-input-string "la petite souris mange."

    (lambda (p-in)

      (do ((i 0 (+ i 1)) (x (get-lexeme p-in) (get-lexeme p-in)))

        ((equal? x 'EOF) 'fini)

        (printf "~a : ~a~n" i x))))

0 : #(struct:token ART la)

1 : #(struct:token ADJ petite)

2 : #(struct:token NAME souris)

3 : #(struct:token VERB mange)

4 : DOT

fini

Au tour du parseur :

(define parse

  (parser

    [start phrase]

    [end EOF]

    [tokens word-tokens op-tokens]

    [error (lambda (a b c) (printf "ERROR with token : ~a~n" b))]  ; ?

    [grammar

      (phrase  [(grNom grVerb DOT) `(ph ,$1 ,$2)])

      (grNom   [(grNomSimple) $1]

               [(grNomSimple sub) `(grnoms ,$1 ,$2)])

      (grNomSimple [(ART NAME) `(gn (art ,$1) (nom ,$2))]

                   [(ART ADJ NAME) `(gn (art ,$1) (adj ,$2) (nom ,$3))])

      (sub     [(CONJSUB VERB) `(sub (conjsub ,$1) (vb ,$2))])

      (grVerb  [(VERB) `(gv (vb ,$1))]

               [(VERB grNom) `(gv (vb ,$1) ,$2)])]))

que je teste cette fois en écrivant une fonction d’analyse d’une phrase :

(define (analyser str)

  (call-with-input-string str

    (lambda (p-in)

      (parse (lambda () (get-lexeme p-in))))))

 

> (analyser "la souris mange le petit chien qui dort.")

(ph (gn (art la) (nom souris)) (gv (vb mange) (grnoms (gn (art le) (adj petit) (nom chien)) (sub (conjsub qui) (vb dort)))))

4 Exercice 15.5.4

Je vous le laisse... Analogue à 15.5.5 ci-dessous sauf que l’on génère du source au lieu de calculer.

5 Exercice 15.5.5

Le fameux exemple mfcalc du manuel Bison... Vous trouverez le lexeur et le parseur dans deux fichiers séparés mfcalc-lexer.rkt et mfcalc-parser.rkt. Je ne saurais trop conseiller de faire soi-même cet exercice, il est très instructif...

6 Exercice 15.5.6

Prendre cet exercice comme un projet personnel, que vous voudrez sans doute élargir...