Les analyseurs SLR, LALR et LR peuvent tous être mis en œuvre en utilisant exactement la même machinerie pilotée par des tables.
Fondamentalement, l'algorithme d'analyse syntaxique recueille le prochain jeton d'entrée T, et consulte l'état actuel S (et les tables de lookahead, de GOTO et de réduction associées) pour décider de ce qu'il faut faire :
- SHIFT : Si la table actuelle dit de SHIFT sur le jeton T, la paire (S,T) est poussée sur la pile d'analyse, l'état est modifié en fonction de ce que la table GOTO dit pour le jeton actuel (par exemple, GOTO(T)), un autre jeton d'entrée T' est récupéré et le processus se répète.
- REDUCE : Chaque état a 0, 1, ou plusieurs réductions possibles qui peuvent se produire dans l'état. Si l'analyseur syntaxique est LR ou LALR, le jeton est vérifié par rapport aux ensembles lookahead pour toutes les réductions valides pour l'état. Si le jeton correspond à un ensemble de lookaheads pour une réduction pour la règle de grammaire G = R1 R2 Rn, une réduction et un décalage de la pile se produisent : l'action sémantique pour G est appelée, la pile est sortie n (de Rn) fois, la paire (S,G) est poussée sur la pile, le nouvel état S' est défini comme GOTO(G), et le cycle se répète avec le même jeton T. Si l'analyseur est un analyseur SLR, il y a au plus une règle de réduction pour l'état et donc l'action de réduction peut être faite aveuglément sans chercher à savoir quelle réduction s'applique. Il est utile pour un analyseur SLR de savoir s'il existe une règle de réduction pour l'état. es une réduction ou non ; cela est facile à dire si chaque état enregistre explicitement le nombre de réductions qui lui sont associées, et ce compte est de toute façon nécessaire pour les versions L(AL)R en pratique.
- ERREUR : Si ni SHIFT ni REDUCE ne sont possibles, une erreur de syntaxe est déclarée.
Donc, s'ils utilisent tous les mêmes machines, quel est l'intérêt ?
La valeur supposée de SLR est sa simplicité d'implémentation ; il n'est pas nécessaire de parcourir les réductions possibles en vérifiant les ensembles de lookahead car il n'y en a qu'un seul, et c'est la seule action viable s'il n'y a pas de sortie SHIFT de l'état. La réduction qui s'applique peut être attachée spécifiquement à l'état, de sorte que la machine d'analyse SLR n'a pas à la chercher. Dans la pratique, les analyseurs L(AL)R gèrent un ensemble de langages beaucoup plus important, et il y a si peu de travail supplémentaire à faire que personne n'implémente SLR sauf comme un exercice académique.
La différence entre LALR et LR concerne le tableau. générateur . Les générateurs d'analyseurs LR gardent la trace de toutes les réductions possibles à partir d'états spécifiques et de leur ensemble précis de lookahead ; vous obtenez des états dans lesquels chaque réduction est associée à son ensemble exact de lookahead à partir de son contexte de gauche. Cela tend à construire des ensembles d'états plutôt grands. Les générateurs d'analyse syntaxique LALR sont disposés à combiner des états si les tables GOTO et les ensembles de lookahead pour les réductions sont compatibles et n'entrent pas en conflit ; cela produit un nombre d'états considérablement plus petit, au prix de ne pas pouvoir distinguer certaines séquences de symboles que LR peut distinguer. Ainsi, les analyseurs LR peuvent analyser un plus grand nombre de langues que les analyseurs LALR, mais ont des tables d'analyse beaucoup plus grandes. En pratique, on peut trouver des grammaires LALR qui sont suffisamment proches des langages cibles pour que la taille de la machine à états vaille la peine d'être optimisée ; les endroits où l'analyseur LR serait meilleur sont gérés par une vérification ad hoc en dehors de l'analyseur.
Donc : Les trois utilisent les mêmes machines. Le reflex est "facile" dans le sens où vous pouvez ignorer une petite partie de la machinerie, mais cela n'en vaut pas la peine. LR analyse un ensemble plus large de langues mais les tables d'état ont tendance à être assez grandes. Cela laisse LALR comme le choix pratique.
Ceci dit, il faut savoir que Analyseurs GLR peut analyser n'importe quel langage sans contexte, en utilisant des mécanismes plus compliqués. mais exactement les mêmes tableaux (y compris la version plus petite utilisée par LALR). Cela signifie que GLR est strictement plus puissant que LR, LALR et SLR ; à peu près si vous pouvez écrire une grammaire BNF standard, GLR l'analysera en fonction de celle-ci. La différence dans la machinerie est que GLR est prêt à essayer plusieurs analyses lorsqu'il y a des conflits entre la table GOTO et les ensembles lookahead. (La façon dont GLR fait cela de manière efficace est un pur génie [pas le mien] mais n'a pas sa place dans ce billet).
Pour moi, c'est un fait extrêmement utile. Je construis des analyseurs de programmes et des transformateurs de code et les analyseurs syntaxiques sont nécessaires mais "inintéressants" ; le travail intéressant est ce que vous faites avec le résultat analysé et donc l'accent est mis sur le travail de post-séparation. L'utilisation de GLR signifie que je peux construire relativement facilement des grammaires fonctionnelles, par rapport au piratage d'une grammaire pour obtenir une forme utilisable par LALR. Ceci est très important lorsqu'on essaie de traiter des langages non académiques tels que C++ ou Fortran, où vous avez littéralement besoin de milliers de règles pour bien gérer le langage entier, et vous ne voulez pas passer votre vie à essayer de modifier les règles de grammaire pour répondre aux limitations de LALR (ou même LR).
Pour citer un exemple célèbre, le C++ est considéré comme extrêmement difficile à analyser... par les personnes qui font de l'analyse LALR. Le C++ est facile à analyser en utilisant la machinerie GLR en utilisant à peu près les règles fournies à la fin du manuel de référence du C++. (J'ai précisément un tel analyseur, et il gère non seulement le C++ classique, mais aussi une variété de dialectes de fournisseurs. Ceci n'est possible en pratique que parce que nous utilisons un analyseur GLR, IMHO).
[EDIT novembre 2011 : Nous avons étendu notre analyseur pour gérer tout le C++11. GLR a rendu cela beaucoup plus facile à faire. EDIT Août 2014 : Gère maintenant tout le C++17. Rien de cassé ou d'aggravé, GLR est toujours le miaou du chat].
0 votes
Eh bien, même si je suis à la recherche d'une réponse appropriée à ce sujet, LALR(1) est juste une légère modification de LR(1), où la taille de la table est réduite de sorte que nous pouvons minimiser l'utilisation de la mémoire ...