generalized lr laurent wouters laurent.wouters@eads.net 01/06/2012

Post on 03-Apr-2015

119 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Generalized LR

Laurent WOUTERS

laurent.wouters@eads.net

01/06/2012

2

Plan

Partie 1 – Introduction

Partie 2 – Méthode GLR

1 – Historique et Variantes

2 – Graph-Structured Stack

3 – Algorithme GLR

4 – Shared Packed Parse Forest

5 – Right-Nulled GLR

6 – Complexités

Partie 3 – Outils

Partie 4 – Ouverture

3

INTRODUCTION

4

Langage de programmation

Pour des langages de programmation modernes, la grammaire est en général accessible:

- Documents de standardisation: C: ISO/IEC 9899:1999 C++: ISO/IEC 14882:2011 C#: ECMA-334

- Site web pour des projets open source: Java: http://docs.oracle.com/javase/specs/

- Documents de spécification pour d’autres: Visual Basic: http://www.microsoft.com/en-us/download/details.aspx?id=15039

5

Ambigüité des grammaires

Les grammaires des « gros » langages sont de plus en plus complexes:C: 210 règles syntaxiques BNFECMA Script: 270 règles syntaxiques BNFC# : 1200 règles syntaxiques BNF

Ces grammaires sont aussi ambigües, avec des ambigüités difficiles à résoudre tout en gardant la grammaire lisible pour un être humain.

Langage Nb états LALR(1) Conflits LR

C 375 38

ECMA Script 513 38

C# 2021 457

6

Exemple de conflit

type → NAME

primary → NAMEprimary → ( exp )

exp → primaryexp → ( type ) exp

( NAME ▪ ) …

Exemple de conflit LR classique dans les langages avec une syntaxe de type C :

exp → ( type ) exp → ( NAME ) exp

exp → primary → ( exp ) → ( primary ) → ( NAME )

7

MÉTHODE GLR

8

Idée Générale

Utiliser un automate LR.

Lors d’un conflit, explorer les différentes options en parallèle.

A tout moment dans la lecture de l’entrée, conserver l’ensemble des états accessibles de l’automate LR pour l’entrée lue.

9

Historique GLR

Knuth 65LR parsing

De Remer 69LALR parsing

De Remer 71SLR parsing

Tomita 85 86GLR parsing

Farshi 91Correct GLR

Rekers 92Compact Parse Forest

Johnstone & Scott 02 06Right Nulled parsing

Hilfinger 03GLR mode dans Bison

10

Algorithmes GLR (1)

TomitaAlgorithme 0 : Algorithme pour le cas où la grammaire n’a pas de conflit.

Algorithme 1: Fonctionne pour toutes les grammaires hors contexte sans règle vide.

Algorithme 2: Fonctionne pour toutes les grammaires hors contexte qui n’ont pas de récursivité à gauche cachés (non terminaison).

Algorithme 3: Même contrainte que 2 mais optimise la gestion de la pile.

Algorithme 4: Même contrainte que 2 et construit l’arbre syntaxique abstrait.

L’algorithme 2 est souvent considéré comme la référence.

FarshiModification de l’algorithme 1 pour le faire fonctionner pour toutes les grammaires hors

contexte. Mais complexe et inefficace.

11

Algorithmes GLR (2)

Scott & JohnstoneAlgorithme 1e: Modification de l’algorithme 1 pour traiter les règles vides mais ne supportant

pas la récursivité à droite.

Algorithme RNGLR: Algorithme final supportant toutes les grammaires hors contexte.

12

Exemple 1

type → NAMEtype → NAME . type

primary → NAMEprimary → ( exp )primary → primary . NAME

exp → primaryexp → ( type ) expS → exp $

( myvar )( string ) myvar( nmspce.ClassA ) obj.field

13

0S → ▪ exp $exp → ▪ primary $exp → ▪ ( type ) exp $primary → ▪ NAME $ .primary → ▪ ( exp ) $ .primary → ▪ primary . NAME $ .

1: S → exp ▪ $ 5: S → exp $ ▪

2exp → primary ▪ $ )primary → primary ▪ . NAME $ . )

6: primary → primary . ▪ NAME $. )

A: primary → primary . NAME ▪ $ . )

3exp → ( ▪ type ) exp $ )primary → ( ▪ exp ) $ . )type → ▪ NAME )type → ▪ NAME . Type )exp → ▪ primary )exp → ▪ ( type ) exp )primary → ▪ NAME . )primary → ▪ ( exp ) . )primary → ▪ primary . NAME . )

7: exp → ( type ▪ ) exp $ )

Bexp → ( type ) ▪ exp $ )exp → ▪ primary $ )exp → ▪ ( type ) exp $ )primary → ▪ NAME $ . )primary → ▪ ( exp ) $ . )primary → ▪ primary . NAME $ . )

E: exp → ( type ) exp ▪ $ )

4: primary → NAME ▪ $ . )

8: exp → ( exp ▪ ) $ . )

C: exp → ( exp ) ▪ $. )

9type → NAME ▪ )type → NAME ▪ . type )primary → NAME ▪ . )

Dtype → NAME . ▪ type )type → ▪ NAME )type → ▪ NAME . type )

10type → NAME ▪ )type → NAME ▪ . type )

F: type → NAME . type ▪ )

(

exp$

primary

.

NAME

NAME

primary

NAME

(

exp

type

)

) exp

NAME

.

type

NAME

.

primary(

14

GLR: Stack Splitting

0

3

0

9

3

0

7

3

0

2

3

0

8

2

0

B C

7 8

3 3

0 0

1

0

5

1

0

( NAME ) $▪

Effectuer toutes les réductions possiblesPasser au token suivant

15

GLR: Graph-Structured Stack (1)

0 3 9

7

2

B

1

U0 U1 U2 U3

8 C

( NAME

type

primary

exp

)

)

5$

U4

( NAME ) $▪

exp

16

GLR: Graph-Structured Stack (2)

0 3

9

2

D

6

10

A

F

C

2

E

1 5

( NAME . NAME ) NAME $

(

NAME

primary

.

.

NAME

type

NAME

NAME

exp $

U0 U1 U2 U3 U4 U5 U6 U7

7

type

2primary

8exp

B)

)

4primary

exp

17

Exemple 2

A → aX → a XX → A XX → S → X $ 0

S → ▪ X $X → ▪ A X $X → ▪ a X $X → ▪ $A → ▪ a $ a

1: S → X ▪ $ 4: S → X $ ▪X $

2X → A ▪ X $X → ▪ A X $X → ▪ a X $X → ▪ $A → ▪ a $ a

3X → a ▪ X $A → a ▪ $ aX → ▪ A X $X → ▪ a X $X → ▪ $A → ▪ a $ a

5: X → A X ▪ $ 6: X → a X ▪ $

A

A

a

a

X X

A a

18

GLR: Stack Head Sharing and ε-Reduction

0

3

2

3

2

5

6

1

a

A

X

a

a

X

X

A

X

X

4$

A

((3, 0), A)

((3, 3), A)

File de réduction

((3, 2), A)

((3), X)

((2), X)

((6, 3, 3), X)

((6, 3, 2), X)

((5, 2, 3), X)

((5, 2, 2), X)

((6, 3, 0), X)

((5, 2, 0), X)

((4, 1, 0), S)

a a $▪

19

GLR: Résumé

Une réduction GLR est l’action de réduire la règle correspondante et appliquer immédiatement le shift du symbole de tête.

Il faut rechercher dans le graph tous les chemins correspondant à la règle commençant au nœud courant de la pile.

20

Table GLR $ a X A

0 r(X,4,0) p3 p1 p2

1 p4

2 r(X,4,0) p3 p5 p2

3 r(A,1,1) r(X,4,0)

r(A,1,1) p3

p6 p2

4 acc acc acc acc

5 r(X,3,2)

6 r(X,2,2)0

S → ▪ X $X → ▪ A X $X → ▪ a X $X → ▪ $A → ▪ a $ a 1: S → X ▪ $ 4: S → X $ ▪X

$

2X → A ▪ X $X → ▪ A X $X → ▪ a X $X → ▪ $A → ▪ a $ a

3X → a ▪ X $A → a ▪ $ aX → ▪ A X $X → ▪ a X $X → ▪ $A → ▪ a $ a

5: X → A X ▪ $ 6: X → a X ▪ $

A

A

a

a

X X

A a

1 A → a2 X → a X3 X → A X4 X → 5 S → X $

px = transition vers xr(V,r,l) = réduction de V avec la règle r de longueur l

21

GLR: Algorithme (DRIVER)

Table GLR T heads rqueue

DRIVER(input)

start = nouveau nœud de la pile pour l’état 0

heads= {start}

rqueue= {}

POUR (tous les tokens t dans input)

REDUCE(t)

SHIFT(t)

RETOURNE l’ensemble des état acceptant dans heads

22

GLR: Algorithme (REDUCE)

REDUCE(t)

POUR (tous les nœuds n représentant un état s dans heads)

POUR (toutes les réductions r(X, r, l) dans T(s, t))

POUR (tous les chemins p de longueur l partant de n)

Ajouter (p, X) à rqueue

TANT QUE (rqueue n’est pas vide)

Retirer le prochain (p, X) de rqueue

REDUCE_PATH(p, X, t)

23

GLR: Algorithme (REDUCE_PATH)

REDUCE_PATH(p, X, t)

left = premier nœud dans le chemin p; o = état représenté par left

SI (il existe un nœud d pour l’état s dans heads tel que T(o, X) contient p s)

SI (il n’ existe pas de lien X de d vers left)

Créer un lien link de d vers left

REDUCE_LIMITED(link, t)

SINON

Créer le nœud d pour l’état s dans heads tel que T(o, X) contient p s

Créer un lien link de d vers left

REDUCE_LIMITED(link, t)

24

GLR: Algorithme (REDUCE_LIMITED)

REDUCE_LIMITED(link, t)

POUR (tous les nœuds n représentant un état s dans heads)

POUR (toutes les réductions r(X, r, l) dans T(s, t))

POUR (tous les chemins p de longueur l partant de n et utilisant link)

Ajouter (p, X) à rqueue

25

GLR: Algorithme (SHIFT)

SHIFT(t)

tails = heads; heads = {}

POUR (tous les nœuds n représentant un état s dans tails)

SI (T(s, t) contient p x)

SI (heads contient un nœud d pour l’état x)

Créer un lien de d vers n

SINON

Créer un nœud d pour l’état x dans heads

Créer un lien de d vers n

26

Arbre Syntaxique

A → aX → a XX → A XX → S → X $

S

X

a X

a X

$

S

X

a X

A X

$

a

S

X

A X

a X

$

S

X

A X

A X

$

a

a a

a a $

27

Shared Packed Parse Forest

A

x1 xm…

ai aj…

A

y1 yp…

ai aj…

A

y1 yp…

ai aj…

x1 xm…

=>

FamillePacked

node

28

Exemple SPPF

A → aX → a XX → A XX → S → X $

a a $

S

a

X

X

X

$

A

a A

29

GLR: Construction du SPPF, Méthode Tomita

Principe:

- Chaque arc dans la pile correspond à exactement 1 nœud dans le SPPF

- Les arcs de la pile sont labellisés avec leur nœud respectif

- Lors d’un shift, créer un nœud SPPF pour le terminal

- Lors d’une réduction

- Si le nœud SPPF existe déjà, (pas d’arc ajouté dans la pile), ajouter la nouvelle famille- Sinon, créer un nouveau nœud SPPF et une famille

30

GLR: Construction du SPPF, Méthode Tomita

0

3

2

3

2

5

6

1

a1

A1

X5

a2

a2

X3

X1

A2

X4

X2

4$

A3

((3, 0), A1)

((3, 3), A2)

File de réduction

((3, 2), A3)

((3), X1)

((2), X2)

((6, 3, 3), X3)

((6, 3, 2), X4)

((5, 2, 3), X3)

((5, 2, 2), X4)

((6, 3, 0), X5)

((5, 2, 0), X5)

((4, 1, 0), S)

a a $▪ SPPF

a2

A2

a1A1

A3

X1 X2

X3X4

X5 $

S

31

SPPF Construit avec Tomita

a2

A2

a1A1

A3

X1 X2

X3X4

X5 $

S

S

a

X

X

X

$

A

a A

32

GLR: Construction du SPPF, Méthode Rekers

Principe:

- Similaire à la méthode de Tomita, mais cherche à maximiser la réutilisation des nœuds du SPPF.

- Les nœuds du SPPF contiennent plus d’informations: 1 nœud = 1 triplet (x, i, j)

- x: symbole du nœud- i: index de départ de la sous-chaîne d’entrée matchée par ce nœud- j: index d’arrivé

33

GLR: Construction du SPPF, Méthode Rekers

0

3

2

3

2

5

6

1

a,0,1

A,0,1

X,0,2

a,1,2

a,1,2

X,1,2

X,2,2

A,1,2

X,1,2

X,2,2

4$

A,1,2

((3, 0), A)

((3, 3), A)

File de réduction

((3, 2), A)

((3), X)

((2), X)

((6, 3, 3), X)

((6, 3, 2), X)

((5, 2, 3), X)

((5, 2, 2), X)

((6, 3, 0), X)

((5, 2, 0), X)

((4, 1, 0), S)

a a $▪ SPPF

a, 0, 1 A, 0, 1

a, 1, 2 A, 1, 2 X, 2, 2

X, 1, 2

X, 0, 2 $, 2, 3

S, 0, 3

34

SPPF Construit avec Rekers

a, 0, 1 A, 0, 1

a, 1, 2 A, 1, 2 X, 2, 2

X, 1, 2

X, 0, 2 $, 2, 3

S, 0, 3

S

a

X

X

X

$

A

a A

35

Right-Nulled GLR

Principe: Permettre la réduction d’une règle si la partie droite du corps de la règle peut être vide.

Pour l’item A → α ▪ β, x

appliquer la réduction de la règle A → α β pour le lookahead x si β ⇒ ε.*

36

Table RNGLR

$ a X A

0 r(X,4,0) p3 p1 p2

1 p4

2 r(X,4,0) r(X,3,1)

p3 p5 p2

3 r(A,1,1) r(X,4,0) r(X,2,1)

r(A,1,1) p3

p6 p2

4 acc acc acc acc

5 r(X,3,2)

6 r(X,2,2)0S → ▪ X $X → ▪ A X $X → ▪ a X $X → ▪ $A → ▪ a $ a 1: S → X ▪ $ 4: S → X $ ▪X

$

2X → A ▪ X $X → ▪ A X $X → ▪ a X $X → ▪ $A → ▪ a $ a

3X → a ▪ X $A → a ▪ $ aX → ▪ A X $X → ▪ a X $X → ▪ $A → ▪ a $ a

5: X → A X ▪ $ 6: X → a X ▪ $

A

A

a

a

X X

A a

1 A → a2 X → a X3 X → A X4 X → 5 S → X $

px = shift vers xr(V,r,l) = réduction de V avec la règle r de longueur l

37

RNGLR: Algorithme (PARSER)

Table RNGLR T Entrée a1 … ad U0 … Ud R Q

SI (d = 0)

SI (T(0, $) accepte) => Retourne succès

SINON => Retourne échec

Créer un nœud v0 avec l’état 0

U0 = {v0}, R = {}, Q = {}, ad+1 = $

SI (T(0, a1) contient transition vers k)

Ajouter (v0, k) à Q

POUR (toutes les réduction d’une variable X en 0)

Ajouter (v0, X, 0) à R

POUR (i de 0 à d)

TANT QUE (Ui n’est pas vide)

TANT QUE (R n’est pas vide) => REDUCER(i)

SHIFTER(i)

38

RNGLR: Algorithme (REDUCER)

Prendre un triplet(v, X, m) dans R

χ = ensemble des nœuds accessible depuis v avec un chemin de taille m – 1, ou 0 si m = 0

POUR (tous les u dans χ)

k = l’état représenté par le nœud u

l = état successeur de k par X

SI (il existe w dans Ui représentant l)

SI (il n’y a pas d’arc de w vers u)

Créer un arc de w vers u

SI (m != 0) POUR (toutes les réduction de B à l’état l sur ai+1 de longueur t != 0)

Ajouter (u, B, t) à R

SINON

Créer un nœud w dans Ui pour l’état l et un arc de w vers u

SI (T(l, ai+1) contient une transition vers h => Ajouter (w, h) à Q

POUR (toutes les réduction de B à l’état l sur ai+1 de longueur 0)

Ajouter (w, B, 0) à R

SI (m != 0) POUR (toutes les réductions de B à l’état l sur ai+1 de longueur t != 0)

Ajouter (u, B, t) à R

39

RNGLR: Algorithme (SHIFTER)

SI (i = d) RETOURNE

Q’ = {}

TANT QUE (Q != {})

Prendre un couple (v, k) dans Q

SI (il existe w dans Ui+1 représentant k)

Créer un arc de w, vers v

POUR (toutes les réductions de B à l’état k sur ai+2 de longueur t != 0)

Ajouter (v, B, t) à R

SINON

Créer w dans Ui+1 représentant k et un arc de w vers v

SI (T(k, ai+2) contient une transition vers h)

Ajouter (w, h) à Q’

POUR (toutes les réductions de B à l’état k sur ai+2 de longueur t != 0)

Ajouter (v, B, t) à R

POUR (toutes les réductions de B à l’état k sur ai+2 de longueur 0)

Ajouter (w, B, 0) à R

Q = Q’

40

RNGLR: Construction du SPPF

L’algorithme RNGLR utilise une version modifiée de la méthode de Rekers pour prendre en charge les réductions supplémentaires.

Lors de la génération de la table, il faut également construire les bouts de SPPF correspondants à la partie droite des règles pouvant se dériver en ε.

41

Complexités

n = taille de l’input:

Algorithme Pire cas Grammaire LR(1)

Farshi O(n3) O(n)

Algorithme 1e O(n2) O(n)

RNGLR O(n2) O(n)

42

OUTILS

43

https://en.wikipedia.org/wiki/Comparison_of_parser_generators

Bison http://www.gnu.org/software/bison/ C, C++, Java

Elkhound http://scottmcpeak.com/elkhound/ C++, OCaml

Wormhole http://www.mightyheave.com/blog/ C, Python

Hime Parser Generator http://himeparser.codeplex.com/ C#

44

OUVERTURE

45

LR(*) : Cas d’utilisation

type → NAMEtype → NAME . type

primary → NAMEprimary → ( exp )primary → primary . NAME

exp → primaryexp → ( type ) expS → exp $

46

0S → ▪ exp $exp → ▪ primary $exp → ▪ ( type ) exp $primary → ▪ NAME $ .primary → ▪ ( exp ) $ .primary → ▪ primary . NAME $ .

1: S → exp ▪ $ 5: S → exp $ ▪

2exp → primary ▪ $ )primary → primary ▪ . NAME $ . )

6: primary → primary . ▪ NAME $. )

A: primary → primary . NAME ▪ $ . )

3exp → ( ▪ type ) exp $ )primary → ( ▪ exp ) $ . )type → ▪ NAME )type → ▪ NAME . Type )exp → ▪ primary )exp → ▪ ( type ) exp )primary → ▪ NAME . )primary → ▪ ( exp ) . )primary → ▪ primary . NAME . )

7: exp → ( type ▪ ) exp $ )

Bexp → ( type ) ▪ exp $ )exp → ▪ primary $ )exp → ▪ ( type ) exp $ )primary → ▪ NAME $ . )primary → ▪ ( exp ) $ . )primary → ▪ primary . NAME $ . )

E: exp → ( type ) exp ▪ $ )

4: primary → NAME ▪ $ . )

8: exp → ( exp ▪ ) $ . )

C: exp → ( exp ) ▪ $. )

9type → NAME ▪ )type → NAME ▪ . type )primary → NAME ▪ . )

Dtype → NAME . ▪ type )type → ▪ NAME )type → ▪ NAME . type )

10type → NAME ▪ )type → NAME ▪ . type )

F: type → NAME . type ▪ )

(

exp$

primary

.

NAME

NAME

primary

NAME

(

exp

type

)

) exp

NAME

.

type

NAME

.

primary(

Construire un automate déterminant le bon item

47

LR(*) : Automate de décision

0

1

2

3 6

4: type → NAME ▪

5: primary → NAME ▪

7: Shift D.

)

NAME

(

$ . )

$

.

) ( NAME

$ . )

48

Bibliographie

Scott McPeak. Elkhound: A Fast, Practical GLR Parser Generator. Report No. UCB/CSD-2-1214, University of California, Berkley, December 2002.

Masaru Tomita. Efficient Parsing of Natural Language. Kluwer Academic, Boston, 1986.

R. Nozohoor-Farshi. GLR Parsing for e-Grammar. In Generalized LR Parsing, M. Tomita, Kluwer Academic, 1991.

Jan Rekers. Parser Generation for Interactive Environment. PhD thesis, University of Amsterdam, 1992.

Elizabeth Scott and Adrian Johnstone. Right-Nulled GLR Parsers. ACM Transactions on Programming Languages and Systems. Volume 28 Issue 4, July 2006.

top related