• Aucun résultat trouvé

D ´efinition d’un non-terminal param ´etr ´e

N/A
N/A
Protected

Academic year: 2022

Partager "D ´efinition d’un non-terminal param ´etr ´e"

Copied!
31
0
0

Texte intégral

(1)

Un aperc¸u de Menhir

Franc¸ois Pottier et Yann R ´egis-Gianas

30 mars 2006

(2)

Motivation

L’avant

Le milieu

L’arri`ere

Conclusion

(3)

Motivation

Pourquoi un nouveau g ´en ´erateur d’analyseurs syntaxiques ?

I d’abord pour tester exp ´erimentalement nos id ´ees sur le typage des parseurs LR ;

I ensuite parce que l’envie ne manquait pas d’am ´eliorer ocamlyacc.

(4)

Motivation

L’avant

Le milieu

L’arri`ere

Conclusion

(5)

Traits marquants

Le langage de sp ´ecification offre de nouvelles possibilit ´es, parmi lesquelles:

I d ´efinir des non-terminaux param ´etr ´es;

I d ´ecouper une sp ´ecification en plusieurs « modules »;

I demander le d ´eveloppement « en ligne » d’un non-terminal ; Ces traits permettent l’ ´ecriture d’une librairie standard.

(6)

D ´efinition d’un non-terminal param ´etr ´e

Voici une d ´efinition typique, issue de la librairie standard:

option(X):

| { None }

| x = X { Some x }

On remarque au passage que les valeurs s ´emantiques sont nomm ´ees.

(7)

Emploi d’un non-terminal param ´etr ´e

Voici comment on pourrait d ´efinir une liste de d ´eclarations, chacune suivie d’une virgule optionnelle:

declarations:

| { [] }

| d = declaration ; option(COMMA); ds = declarations { d :: ds } On peut ´ecrire COMMA ? au lieu de option(COMMA).

(8)

Expansion des non-terminaux param ´etr ´es

Tout se passe comme si on avait ´ecrit:

option comma:

| { None }

| x = COMMA { Some x } declarations:

| { [] }

| d = declaration ; option comma; ds = declarations { d :: ds }

Toute r ´ef ´erence `a un non-terminal param ´etr ´e est expans ´ee.

(9)

Autres exemples

La librairie standard d ´efinit ´egalement:

terminated(X, closing):

| x = X ; closing { x } list(X):

| { [] }

| x = X ; xs = list(X) { x :: xs }

Notre declarations pr ´ec ´edent peut alors s’ ´ecrire list(terminated(declaration, COMMA ?)) Est-ce tout- `a-fait ´equivalent ?

(10)

Expansion en ligne

Les perfectionnistes pourront d ´eclarer:

%inline terminated(X, closing):

| x = X ; closing { x }

La d ´efinition de terminated sera alors expans ´ee « en ligne » et une r ´eduction inutile sera ´evit ´ee.

(11)

Un exemple plus convaincant

L’expansion en ligne permet d’ ´eviter certains conflits LR(1) sans abˆımer la grammaire. Exemple tir ´e de la grammaire de Menhir:

producer:

| id = ioption(terminated(LID, EQUAL)) ; p = actual parameter

{ id, p }

ioption est identique `a option mais est d ´eclar ´e %inline. Le terminal LID appartient `a FIRST(actual parameter).

(12)

Modularit ´e

Menhir propose une forme faible de modularit ´e:

I chaque fichier forme un « (mixin) module »;

I une grammaire compl`ete est obtenue par composition ;

I les non-terminaux d ´eclar ´es %public sont partag ´es, les autres sont consid ´er ´es comme internes ;

I la d ´efinition d’un non-terminal public peut ˆetre r ´epartie sur plusieurs modules.

La librairie standard est un module comme un autre.

(13)

Traits de moindre int ´erˆet

Menhir permet ´egalement:

I d’utiliser un type token externe ;

I de partager un type token entre plusieurs grammaires ;

I de param ´etrer l’analyseur par un module Objective Caml ;

I de typer les actions s ´emantiques avant la g ´en ´eration.

(14)

Motivation

L’avant

Le milieu

L’arri`ere

Conclusion

(15)

Techniques de construction

Voici un petit rappel:

I les items LR(0) ont la forme A→ α•β; il y a conflit LR(0) d`es qu’un d ´ecalage et une r ´eduction, ou bien deux r ´eductions, sont permis dans le mˆeme ´etat ;

I les items LR(1) ont la forme A→ α•β[T] o `u T est l’ensemble des terminaux susceptibles de suivre.

L’automate non-d ´eterministe LR(1) est de taille lin ´eaire... mais la d ´eterminisation explose en pratique.

(16)

Techniques de construction

Pour approcher l’expressivit ´e de LR(1) sans en payer le prix:

I la technique SLR(1) consiste `a conserver l’automate LR(0), mais

`a attribuer `a chaque item A→. . . l’ensemble de pr ´ediction FOLLOW(A) ;

I la technique LALR(1) consiste conceptuellement `a construire l’automate LR(1) puis `a identifier les ´etats qui ont le mˆeme noyau LR(0) ;

I la technique de Pager consiste `a construire effectivement l’automate LR(1), mais en identifiant au vol les ´etats de mˆeme noyau si on peut garantir que cela ne fera apparaˆıtre aucun conflit.

(17)

Techniques de construction

Menhir implante la technique de Pager. En pratique, l’automate obtenu est l’automate LALR(1) si la grammaire est LALR(1) et a plus d’ ´etats sinon – mais ce n’est pas un th ´eor`eme.

Implantation un peu subtile, mais apr`es optimisation le bottleneck n’est plus l `a.

(18)

Explication des conflits

J’ai implant ´e un algorithme d’explication de conflits fortement inspir ´e de celui de DeRemer et Pennello – mais adapt ´e pour Pager au lieu de LALR(1).

(19)

Une grammaire `a conflits

%token IF THEN ELSE

%start < expression > expression

%%

expression:

| . . .

| IF b = expression THEN e = expression { . . . }

| IF b = expression THEN e = expression

ELSE f = expression { . . . }

| . . .

(20)

Explication des conflits

L’outil rapporte que le conflit est atteint apr`es avoir lu la phrase (sentential form) suivante:

IF expression THEN IF expression THEN expression et lorsque le terminal suivant est ELSE.

(21)

Explication des conflits

Si on veut savoir plus, on peut demander pourquoi il est l ´egal de d ´ecaler:

expression

IF expression THEN expression

IF expression THEN expression . ELSE expression

et pourquoi il est l ´egal de r ´eduire:

expression

IF expression THEN expression ELSE expression // lookahead token appears

IF expression THEN expression .

(22)

Explication des conflits

´Evidemment, la pr ´esentation textuelle de ces arbres n’est pas tout- `a-fait au point (on d ´erive trop vers la droite).

Pour adoucir le probl`eme, Menhir factorise le contexte maximal commun aux deux (ou plus) d ´erivations.

On doit encore pouvoir faire un peu mieux – `a suivre.

(23)

Motivation

L’avant

Le milieu

L’arri`ere

Conclusion

(24)

R ´eentrance

Les analyseurs produits par Menhir sont r ´eentrants – ils ne reposent sur aucune variable globale.

Cela impose d’abandonner l’API du module Parsing actuel.

L’acc`es aux positions se fait maintenant par mots-clef.

(25)

Un fragment de code engendr ´e

Menhir engendre du code (comment ´e!), non des tables. Extrait:

let goto reversed list rule env stack v = let stack = (stack, v) in

let tok = env . token in matchtok with

| EOF−>

(∗ Shifting (EOF) to state 17∗) (∗ Not allocating top stack cell ∗) (∗ Reducing without looking ahead at # ∗) (∗ Reducing production trailer−>EOF ∗) let v : ( Syntax. trailer option ) = ( None ) in goto trailer env stack v

| . . .

(26)

Code ou tables ?

Nous produisons du code parce que le typage fin ´etait notre

motivation initiale. Toutefois, le code actuel contient encore des magic – on attend les GADTs!

Le code produit est optimis ´e pour la taille, mais reste assez gros.

Un second back-end produisant des tables est concevable.

(27)

Quelques chiffres

La grammaire d’Objective Caml: 1.5 Kloc. Automate LALR(1) `a 1040

´etats.

Avec ocamlyacc, le .ml engendr ´e fait 8 Kloc (400 Kb), le .o engendr ´e fait 215 Kb.

Avec Menhir, le .ml engendr ´e fait 30 Kloc (1.5 Mb ; plus de 1100 fonctions r ´ecursives), le .o engendr ´e fait 865 Kb.

Chiffres obtenus avec -noassert et -compact. Le code produit par Menhir serait plus gros si les positions ´etaient correctement trait ´ees.

(28)

Gestion d’erreurs

Menhir implante un m ´ecanisme compatible en apparence avec celui d’ocamlyacc (pseudo-terminal error). L’implantation est un peu modifi ´ee:

I la r ´eduction sur error est effectu ´ee ;

I la resynchronisation est optionnelle.

Faut-il laisser tomber ce m ´ecanisme (qui me semble quasi impossible

`a utiliser correctement) et adopter une autre approche ?

(29)

Gestion d’erreurs: suggestions

On pourrait laisser tomber la reprise programmable sur erreur et se contenter de construire un message d ´ependant de l’ ´etat atteint.

Nous songeons `a:

I construire automatiquement un message bas ´e sur les items LR(1) qui forment l’ ´etat atteint ;

I permettre au programmeur d’associer des messages personnalis ´es aux ´etats `a l’aide d’exemples (cf. C. Jeffery).

(30)

Motivation

L’avant

Le milieu

L’arri`ere

Conclusion

(31)

Feedback!

Références

Documents relatifs

[r]

N’oubliez pas d’indiquer sur la fiche de colle votre nom, et surtout le num´ ero de la semaine en cours!. MPB : 89 AC : 15 CP : 130

Les relations entre a, b et c, ainsi que les ´equations des directrices et l’expression de l’excentricit´e, doivent ˆetre parfaitement connues.. Les propri´et´es des

IApplications : d´etermination du centre de gravit´e d’une plaque homog`ene, d’un solide homog`ene ; calcul du moment d’inertie d’un solide homog`ene par rapport ` a un

En prenant en compte les signes et variations de x et y, en partant des param`etres t n´egatifs pour aller vers les positifs, sans utiliser Maple, conjecturer l’allure du support de

En d´ eduire que la courbe admet un point triple, et d´ eterminer les tangentes ` a ce point triple... 3) Dessiner

[r]

– rep` ere de Darboux ; courbure normale (dans une direction) : calcul au moyen d’un rep` ere de Frenet d’une courbe sur la surface et th´ eor` eme de Meusnier ;. –