méthode LR(1)

Transcription

méthode LR(1)
Compilateurs - notes séance 10
Gérard Dethier
2009–2010
Préambule
Ce document reprend des notes prises à la dixième séance du cours de « Compilateurs » (INFO0085-1) donné par le professeur Xavier Boyen le mardi 27/04/2010.
1
Rappel sur la méthode SLR
Un item LR(0) est composé d’une règle de production et d’un marqueur et est noté :
[A -> α . βγ] où le point est un marqueur.
Dans la méthode SLR, on construit un DFA dont les états sont des ensembles
d’items.
Un chemin parcouru dans l’automate correspond à tous les préfixes viables que l’on
peut rencontrer dans une dérivation la plus à droite. Un préfixe est viable lorsqu’on n’a
pas encore rencontré d’erreur.
Se trouver en un état du DFA signifie qu’on a rencontré un préfixe viable qui correspond à un des items de l’état.
2
Méthode LR(1) canonique
La méthode canonique capture toutes les grammaires LR(1). L’ensemble des grammaires SLR(1) est inclus dans l’ensemble des grammaires LR(1).
La méthode SLR n’est cependant pas assez puissante pour représenter certains
types de grammaires pourtant simples.
Exemple de conflit dans la méthode SLR :
[A -> α . a β ] => shift sur le a
[A -> γ . ] et a ∈ FOLLOW(A) => reduce sur le a
Si ces deux items appartiennent au même état, on a un conflit.
Il se peut que le deuxième item ne soit possible que dans un certain contexte dans
lequel il n’y a pas de shift possible. Générer des reduce pour tous les a ∈ follow(A) est
donc potentiellement une source de conflits inexistants en pratique.
Soit la grammaire suivante qui représente une assignation :
S -> L = R
S -> R
L -> * R
L -> id
R -> L
1
Cette grammaire n’est pas SLR(1), il n’est pas possible de construire une table
d’analyse SLR sans conflit au niveau des actions : Imaginons que l’on soit dans un
état s contenant l’item [R -> L.]. On a alors que action[s, ’=’] vaut "reduce" or cette
situation n’arrive jamais dans une dérivation valide.
La méthode canonique LR(1) utilise des items canoniques LR(1) (et plus LR(0)
comme c’est le cas pour la méthode SLR), on ajoute un symbole de lookahead aux
items : [A -> α . β, a] où a correspond à un symbole de lookahead (le préfixe viable
correspondant est suivi directement par le symbole a).
Si on reprend le cas problématique des méthodes SLR avec l’item [A -> γ .] nécessitant des reduce pour tous les a ∈ follow(A), la méthode LR(1) permet de "particulariser" et de ne générer de reduce que sur le sous-ensemble utile de follow(A). Dans le
contexte de la grammaire présentée précédemment, il n’y a alors plus de conflit.
2.1
Construction de l’ensemble des items canoniques LR(1)
in : G’ (grammaire augmentée, voir méthode SLR)
out : Une collection C d’ensembles Ii d’items LR(1) valides pour au moins un préfixe
viable dans G’ avec C = {I0 , I1 , ..., In }
2.1.1
Fermeture
Soit un ensemble d’items associé à une configuration valide, la fermeture de cet
ensemble contient tous les items associés à cette même configuration valide.
Soit la notation suivante :
... ( α | β ) a ...
où α est un préfixe viable, αβ un handle et a un symbole de lookahead.
Soit une configuration viable (résultat d’une dérivation valide) : ... (α | B β) a ...
Si on a une prod. B -> γ alors
... (α | γ β) a ...
Si en plus b ∈ FIRST(βa) alors
... (α | γ b β 0 ) a ...
et le préfixe est donc viable aussi pour l’item [B -> . γ, b].
D’où l’algorithme suivant :
function closure(I : set of LR(1) items) : set of LR(1) items;
repeat
if \exists item [A -> \alpha . B \beta, a] \in I and
\exists prod B -> \gamma \in G’ and
\exists term. b \in FIRST(\beta a) such as
[B -> .\gamma, b] \notin I
then
I := I \union {[B -> .\gamma, b]}
until "No more items can be added to I"
2.1.2
Goto
Soit un ensemble d’items associé au préfixe viable et au handle suivants :
... (α | X β ) a
On cherche l’ensemble d’items correspondant au préfixe viable et au handle suivants :
... (α X | β ) a
Algorithme :
2
function goto(I : set of LR(1) items, X : NT)
J := {[A -> \alpha X . \beta, a] such as [A -> \alpha X . \beta, a] \in I}
return closure(J)
2.1.3
Construction de C
procedure items(G’ : extended grammar) : set of LR(1) items set;
I_0 := closure({[S’ -> . S, $]});
C := {I_0}
repeat
if \exists I \in C and \exists symb. X tels que goto(I, X) \neq 0 and
goto(I, X) \not\in C then
"ajouter goto(I, X) à C"
until "convergence"
2.2
Contruction de la table d’analyse canonique LR(1)
in : Grammaire étendue G’
out : tables actions et goto
1. Construire C = I0 , I1 , ..., In pour G’
2. Construction de la table actions :
(a) Créer état i pour chaque Ii
(b) Définir les actions pour l’état i :
i. Si [A -> α . a β, b] ∈ Ii et goto(Ii , a) = Ij et a est terminal, alors
actions[i, a] := "shift j"
ii. Si [A -> α ., a] ∈ Ii pour A 6= S’, alors actions[i, a] := "reduce A -> α"
iii. Si [S’ -> S ., $] ∈ Ii , alors actions[i, $] := "accept"
3. Pour tout Ii et A, si goto(Ii , A) = Ij , alors goto[i, A] := j.
4. Initialiser toutes les entrées des tables actions et goto non définies à "error".
L’état initial utilisé par l’analyseur est celui construit à partir de [S’ -> .S, $] (I0 par
construction).
En cas de conflit, la grammaire n’est pas LR(1).
3
Discussion de la méthode LR(1) canonique
La méthode LR(1) canonique a un inconvénient par rapport à la méthode SLR :
un nombre d’états plus élevé d’où des tables d’analyse plus grandes. Par exemple, le
langage Pascal requiert quelques centaines d’états avec la méthode SLR mais plusieurs
milliers avec la méthode LR(1) canonique.
Une méthode intermédiaire, appelée LALR, ne requiert pas plus d’états que la méthode SLR mais est plus puissante que celle-ci (tout en restant plus faible que la méthode LR(1) canonique).
Les méthodes SLR et LR(1) peuvent être comparées par rapport aux états du DFA
servant de base à la constructions des tables d’analyse :
– SLR : les états sont des ensembles d’items LR(0)
– LR(1) canonique : les états sont des ensembles d’items LR(1)
3
Avec la méthode LALR, les états sont des ensembles d’items LR(1) mais on va fusionner les états dont les items sont les mêmes au symbole de lookahead près (soit l’item
LR(1) [A -> α . β, a], l’item suivant est identique au symbole de lookahead près : [A
-> α . β, b]).
À noter qu’avec des machines modernes, la méthode LR(1) canonique est devenue
adéquate.
4

Documents pareils