Generalized LR Laurent WOUTERS laurent wouterseads net 01062012

  • Slides: 48
Download presentation
Generalized LR Laurent WOUTERS laurent. wouters@eads. net 01/06/2012

Generalized LR Laurent WOUTERS laurent. wouters@eads. net 01/06/2012

Plan Partie 1 – Introduction Partie 2 – Méthode GLR 1 – Historique et

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 2

INTRODUCTION 3

INTRODUCTION 3

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

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 4

Ambigüité des grammaires Les grammaires des « gros » langages sont de plus en

Ambigüité des grammaires Les grammaires des « gros » langages sont de plus en plus complexes: Ø C: 210 règles syntaxiques BNF Ø ECMA Script: 270 règles syntaxiques BNF Ø C# : 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. 5 Langage Nb états LALR(1) Conflits LR C 375 38 ECMA Script 513 38 C# 2021 457

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

Exemple de conflit LR classique dans les langages avec une syntaxe de type C : type → NAME primary → ( exp ) exp → primary → ( type ) exp ( NAME ▪ ) … exp → ( type ) exp → ( NAME ) exp → primary → ( exp ) → ( primary ) → ( NAME ) 6

MÉTHODE GLR 7

MÉTHODE GLR 7

Idée Générale Utiliser un automate LR. Lors d’un conflit, explorer les différentes options en

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. 8

Historique GLR Hilfinger 03 GLR mode dans Bison Rekers 92 Johnstone & Scott 02

Historique GLR Hilfinger 03 GLR mode dans Bison Rekers 92 Johnstone & Scott 02 06 Compact Parse Forest Right Nulled parsing Farshi 91 Correct GLR Tomita 85 86 De Remer 71 GLR parsing SLR parsing De Remer 69 LALR parsing Knuth 65 LR parsing 9

Algorithmes GLR (1) Tomita Algorithme 0 : Algorithme pour le cas où la grammaire

Algorithmes GLR (1) Tomita Algorithme 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. Farshi Modification de l’algorithme 1 pour le faire fonctionner pour toutes les grammaires hors contexte. Mais complexe et inefficace. 10

Algorithmes GLR (2) Scott & Johnstone Algorithme 1 e: Modification de l’algorithme 1 pour

Algorithmes GLR (2) Scott & Johnstone Algorithme 1 e: 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. 11

Exemple 1 type → NAME. type primary → NAME primary → ( exp )

Exemple 1 type → NAME. type primary → NAME primary → ( exp ) primary → primary. NAME exp S → primary → ( type ) exp → exp $ ( myvar ) ( string ) myvar ( nmspce. Class. A ) obj. field 12

0 S → ▪ exp $ exp → ▪ primary exp → ▪ (

0 S → ▪ exp $ exp → ▪ primary exp → ▪ ( type ) exp primary → ▪ NAME primary → ▪ ( exp ) primary → ▪ primary. NAME $ $ $. $. $. 1: S → exp ▪ $ NAME 5: S → exp $ ▪ 4: primary → NAME ▪ A: primary → primary. NAME ▪ $. ) primary NAME 2 . exp → primary ▪ $) primary → primary ▪. NAME $. ) ( ( $ exp primary ( 3 exp → ( ▪ type ) exp primary → ( ▪ exp ) type → ▪ NAME. Type exp → ▪ primary exp → ▪ ( type ) exp primary → ▪ NAME primary → ▪ ( exp ) primary → ▪ primary. NAME $) $. ) ) ). ) type exp 7: exp → ( type ▪ ) exp 8: exp → ( exp ▪ ) $) ) NAME 6: primary → primary. ▪ NAME B exp → ( type ) ▪ exp → ▪ primary exp → ▪ ( type ) exp primary → ▪ NAME primary → ▪ ( exp ) primary → ▪ primary. NAME $) $) $) $. ) exp ) C: exp → ( exp ) ▪ E: exp → ( type ) exp ▪ $. ) $) . NAME 10 NAME 9 type → NAME ▪. type primary → NAME ▪ 13 ) ). ) . type → NAME ▪. type ) ) D type → NAME. ▪ type → ▪ NAME. type ) ) ) type $. ) F: type → NAME. type ▪ ) $. )

GLR: Stack Splitting ▪ ( NAME ) $ B C 0 9 7 2

GLR: Stack Splitting ▪ ( NAME ) $ B C 0 9 7 2 8 7 8 5 3 3 2 3 3 1 1 0 0 0 0 0 ØEffectuer toutes les réductions possibles ØPasser au token suivant 14

GLR: Graph-Structured Stack (1) ▪ ( 0 ( 3 NAME type ) $ 9

GLR: Graph-Structured Stack (1) ▪ ( 0 ( 3 NAME type ) $ 9 7 ) B primary 2 exp 8 ) C 1 U 0 15 U 1 U 2 U 3 $ 5 U 4

GLR: Graph-Structured Stack (2) ▪ ( NAME 9 . . D NAME ) NAME

GLR: Graph-Structured Stack (2) ▪ ( NAME 9 . . D NAME ) NAME $ 10 type 0 ( 3 F type 7 primary 2 . 6 NAME ) B 4 primary A 2 exp E primary 2 exp 8 ) C exp 16 U 0 U 1 U 2 U 3 U 4 U 5 1 U 6 $ 5 U 7

GLR: Stack Head Sharing and ε-Reduction ▪ a a File de réduction $ ((3,

GLR: Stack Head Sharing and ε-Reduction ▪ a a File de réduction $ ((3, 0), A) A ((3, 2), A) A X 3 a ((3, 3), A) 2 6 X a 0 ((3), X) ((2), X) X 3 A ((6, 3, 2), X) X X ((6, 3, 3), X) a 2 5 1 ((5, 2, 3), X) $ 4 ((5, 2, 2), X) ((6, 3, 0), X) ((5, 2, 0), X) 18 ((4, 1, 0), S)

GLR: Résumé Une réduction GLR est l’action de réduire la règle correspondante et appliquer

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 recher dans le graph tous les chemins correspondant à la règle commençant au nœud courant de la pile. 19

Table GLR 1 A→a 2 X→a. X 3 X→AX 4 X→ 5 S→X$ 0

Table GLR 1 A→a 2 X→a. X 3 X→AX 4 X→ 5 S→X$ 0 S→▪X$ X→▪AX X→▪a. X X→▪ A→▪a A 2 $ $ $a X 5: X → A X ▪ 20 a X A 0 r(X, 4, 0) p 3 p 1 p 2 1 p 4 2 r(X, 4, 0) p 3 p 5 p 2 3 r(A, 1, 1) r(X, 4, 0) r(A, 1, 1) p 3 p 6 p 2 4 acc acc 5 r(X, 3, 2) 6 r(X, 2, 2) X 1: S → X ▪ $ a A 4: S → X $ ▪ 3 X→a▪X A→a▪ X→▪AX X→▪a. X X→▪ A→▪a $ $ $ $a X $ $ a a A X→A▪X X→▪AX X→▪a. X X→▪ A→▪a $ $a $ 6: X → a X ▪ $ px = transition vers x r(V, r, l) = réduction de V avec la règle r de longueur l

GLR: Algorithme (DRIVER) Table GLR T heads rqueue DRIVER(input) start = nouveau nœud de

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 21

GLR: Algorithme (REDUCE) REDUCE(t) POUR (tous les nœuds n représentant un état s dans

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) 22

GLR: Algorithme (REDUCE_PATH) REDUCE_PATH(p, X, t) left = premier nœud dans le chemin p;

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) 23

GLR: Algorithme (REDUCE_LIMITED) REDUCE_LIMITED(link, t) POUR (tous les nœuds n représentant un état s

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 24

GLR: Algorithme (SHIFT) SHIFT(t) tails = heads; heads = {} POUR (tous les nœuds

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 25

Arbre Syntaxique A→a X→a. X X→AX X→ S→X$ a S X a $ X

Arbre Syntaxique A→a X→a. X X→AX X→ S→X$ a S X a $ X a X S $ X X A a 26 $ S X a a A X a S $ X X a A X a $ X A a X

Shared Packed Parse Forest Packed node Famille A A x 1 ai 27 …

Shared Packed Parse Forest Packed node Famille A A x 1 ai 27 … … => A xm y 1 aj ai … … yp x 1 aj ai … xm y 1 … … yp aj

Exemple SPPF A→a X→a. X X→AX X→ S→X$ a a S X a A

Exemple SPPF A→a X→a. X X→AX X→ S→X$ a a S X a A $ X a 28 $ A X

GLR: Construction du SPPF, Méthode Tomita Principe: - Chaque arc dans la pile correspond

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 29

GLR: Construction du SPPF, Méthode Tomita ▪ a a File de réduction $ SPPF

GLR: Construction du SPPF, Méthode Tomita ▪ a a File de réduction $ SPPF S ((3, 0), A 1) X 3 a 1 3 X 1 3 ((2), X 2) X 2 A 1 5 1 X 4 X 3 ((5, 2, 3), X 3) $ 4 ((5, 2, 2), X 4) ((6, 3, 0), X 5) ((4, 1, 0), S) X 2 X 1 ((5, 2, 0), X 5) 30 a 1 ((6, 3, 3), X 3) ((6, 3, 2), X 4) X 4 X 5 ((3), X 1) a 2 2 $ X 5 ((3, 2), A 3) 6 a 2 0 A 1 ((3, 3), A 2) 2 A 3 A 3 a 2 A 2

SPPF Construit avec Tomita S $ X 5 A 1 X a 1 X

SPPF Construit avec Tomita S $ X 5 A 1 X a 1 X 4 X 3 A 3 31 a X 2 X 1 a 2 S A 2 A $ X a A X

GLR: Construction du SPPF, Méthode Rekers Principe: - Similaire à la méthode de Tomita,

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é 32

GLR: Construction du SPPF, Méthode Rekers ▪ a a File de réduction $ SPPF

GLR: Construction du SPPF, Méthode Rekers ▪ a a File de réduction $ SPPF ((3, 0), A) ((3, 3), A) 2 A, 1, 2 ((3, 2), A) A, 1, 2 X, 1, 2 a, 0, 1 3 6 X, 2, 2 a, 1, 2 0 2 X, 0, 2 ((6, 3, 3), X) ((6, 3, 2), X) 5 1 a, 0, 1 A, 0, 1 X, 1, 2 a, 1, 2 A, 1, 2 ((5, 2, 3), X) $ 4 ((5, 2, 2), X) ((6, 3, 0), X) ((5, 2, 0), X) 33 $, 2, 3 ((2), X) X, 2, 2 a, 1, 2 X, 0, 2 ((3), X) 3 A, 0, 1 S, 0, 3 ((4, 1, 0), S) X, 2, 2

SPPF Construit avec Rekers S, 0, 3 S X, 0, 2 $, 2, 3

SPPF Construit avec Rekers S, 0, 3 S X, 0, 2 $, 2, 3 X a, 0, 1 34 A, 0, 1 X, 1, 2 a, 1, 2 A, 1, 2 a X, 2, 2 A $ X a A X

Right-Nulled GLR Principe: Permettre la réduction d’une règle si la partie droite du corps

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 β ⇒ 35

Table RNGLR 1 A→a 2 X→a. X 3 X→AX 4 X→ 5 S→X$ 0

Table RNGLR 1 A→a 2 X→a. X 3 X→AX 4 X→ 5 S→X$ 0 S→▪X$ X→▪AX X→▪a. X X→▪ A→▪a A 2 $ $ $a X 5: X → A X ▪ 36 a X A 0 r(X, 4, 0) p 3 p 1 p 2 1 p 4 2 r(X, 4, 0) r(X, 3, 1) p 3 p 5 p 2 3 r(A, 1, 1) r(X, 4, 0) r(X, 2, 1) r(A, 1, 1) p 3 p 6 p 2 4 acc acc 5 r(X, 3, 2) 6 r(X, 2, 2) X 1: S → X ▪ $ a A 4: S → X $ ▪ 3 X→a▪X A→a▪ X→▪AX X→▪a. X X→▪ A→▪a $ $ $ $a X $ $ a a A X→A▪X X→▪AX X→▪a. X X→▪ A→▪a $ $a $ 6: X → a X ▪ $ px = shift vers x r(V, r, l) = réduction de V avec la règle r de longueur l

RNGLR: Algorithme (PARSER) Table RNGLR T Entrée a 1 … ad U 0 …

RNGLR: Algorithme (PARSER) Table RNGLR T Entrée a 1 … ad U 0 … Ud SI (d = 0) SI (T(0, $) accepte) => Retourne succès SINON => Retourne échec Créer un nœud v 0 avec l’état 0 U 0 = {v 0}, R = {}, Q = {}, ad+1 = $ SI (T(0, a 1) contient transition vers k) Ajouter (v 0, k) à Q POUR (toutes les réduction d’une variable X en 0) Ajouter (v 0, 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) 37 R Q

RNGLR: Algorithme (REDUCER) Prendre un triplet(v, X, m) dans R χ = ensemble des

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) 38 Ajouter (u, B, t) à R

RNGLR: Algorithme (SHIFTER) SI (i = d) RETOURNE Q’ = {} TANT QUE (Q

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 39 Q = Q’

RNGLR: Construction du SPPF L’algorithme RNGLR utilise une version modifiée de la méthode de

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 ε. 40

Complexités n = taille de l’input: 41 Algorithme Pire cas Grammaire LR(1) Farshi O(n

Complexités n = taille de l’input: 41 Algorithme Pire cas Grammaire LR(1) Farshi O(n 3) O(n) Algorithme 1 e O(n 2) O(n) RNGLR O(n 2) O(n)

OUTILS 42

OUTILS 42

https: //en. wikipedia. org/wiki/Comparison_of_parser_generators Bison http: //www. gnu. org/software/bison/ C, C++, Java Elkhound http:

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# 43

OUVERTURE 44

OUVERTURE 44

LR(*) : Cas d’utilisation type → NAME. type primary → NAME primary → (

LR(*) : Cas d’utilisation type → NAME. type primary → NAME primary → ( exp ) primary → primary. NAME exp S 45 → primary → ( type ) exp → exp $

0 S → ▪ exp $ exp → ▪ primary exp → ▪ (

0 S → ▪ exp $ exp → ▪ primary exp → ▪ ( type ) exp primary → ▪ NAME primary → ▪ ( exp ) primary → ▪ primary. NAME $ $ $. $. $. 1: S → exp ▪ $ NAME 5: S → exp $ ▪ 4: primary → NAME ▪ A: primary → primary. NAME ▪ $. ) primary NAME 2 . exp → primary ▪ $) primary → primary ▪. NAME $. ) ( ( $ exp primary ( 3 exp → ( ▪ type ) exp primary → ( ▪ exp ) type → ▪ NAME. Type exp → ▪ primary exp → ▪ ( type ) exp primary → ▪ NAME primary → ▪ ( exp ) primary → ▪ primary. NAME $) $. ) ) ). ) type exp 7: exp → ( type ▪ ) exp 8: exp → ( exp ▪ ) $) ) NAME 6: primary → primary. ▪ NAME B exp → ( type ) ▪ exp → ▪ primary exp → ▪ ( type ) exp primary → ▪ NAME primary → ▪ ( exp ) primary → ▪ primary. NAME $) $) $) $. ) exp ) C: exp → ( exp ) ▪ E: exp → ( type ) exp ▪ $. ) $) . Construire un automate déterminant le bon item NAME 10 NAME 9 type → NAME ▪. type primary → NAME ▪ 46 ) ). ) . type → NAME ▪. type ) ) D type → NAME. ▪ type → ▪ NAME. type ) ) ) type $. ) F: type → NAME. type ▪ ) $. )

LR(*) : Automate de décision . . 1 NAME 3 $ 0 ) 2

LR(*) : Automate de décision . . 1 NAME 3 $ 0 ) 2 $. ) ( 47 ) 6 $. ) 5: primary → NAME ▪ 4: type → NAME ▪ ( NAME 7: Shift D

Bibliographie Scott Mc. Peak. Elkhound: A Fast, Practical GLR Parser Generator. Report No. UCB/CSD-21214,

Bibliographie Scott Mc. Peak. Elkhound: A Fast, Practical GLR Parser Generator. Report No. UCB/CSD-21214, 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. Ph. D 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. 48