Les analyseurs SLR, LALR et LR peuvent tous être implémentés en utilisant exactement les mêmes machines pilotées par table.
Fondamentalement, l'algorithme d'analyse collecte le jeton d'entrée suivant T et consulte l'état actuel S (et les tables d'anticipation, GOTO et de réduction associées) pour décider de la marche à suivre:
- SHIFT: Si la table actuelle dit SHIFT sur le jeton T, la paire (S, T) est poussée sur la pile d'analyse, l'état est changé 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
- RÉDUIRE: chaque état a 0, 1 ou plusieurs réductions possibles qui peuvent se produire dans l'état. Si l'analyseur est LR ou LALR, le jeton est vérifié par rapport aux ensembles d'anticipation pour toutes les réductions valides pour l'état. Si le jeton correspond à un ensemble d'anticipation pour une réduction de la règle de grammaire G = R1 R2 .. Rn, une réduction et un décalage de pile se produisent: l'action sémantique pour G est appelée, la pile est sautée n (à partir de Rn) fois, la paire ( S, G) est poussé sur la pile, le nouvel état S 'est mis à 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 le état et ainsi l'action de réduction peut être effectuée aveuglément sans chercher à voir quelle réduction s'applique. Il est utile pour un analyseur SLR de savoir s'il y a aune réduction ou non; il est facile de 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.
Alors, s'ils utilisent tous les mêmes machines, à quoi ça sert?
La valeur prétendue dans SLR est sa simplicité de mise en œuvre; vous n'avez pas à parcourir les réductions possibles en vérifiant les ensembles d'anticipation car il y en a au plus un, et c'est la seule action viable s'il n'y a pas de sorties 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 rechercher. En pratique, les analyseurs L (AL) R gèrent un ensemble de langages utilement plus grand, et sont si peu de travail supplémentaire à implémenter que personne n'implémente SLR sauf comme exercice académique.
La différence entre LALR et LR a à voir avec la table générateur de. Les générateurs d'analyseurs LR gardent une trace de toutes les réductions possibles des états spécifiques et de leur ensemble d'anticipation précis; vous vous retrouvez avec des états dans lesquels chaque réduction est associée à son ensemble d'anticipation exact à partir de son contexte gauche. Cela tend à créer des ensembles d'états assez volumineux. Les générateurs d'analyseurs LALR sont prêts à combiner des états si les tables GOTO et les ensembles de têtes de recherche pour les réductions sont compatibles et ne sont 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 ensemble de langages que les analyseurs LALR, mais ont des tables d'analyseurs 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 d'état mérite d'être optimisée;
Donc: Tous les trois utilisent les mêmes machines. SLR est "facile" dans le sens où vous pouvez ignorer un tout petit peu de la machinerie, mais cela ne vaut tout simplement pas la peine. LR analyse un ensemble plus large de langages mais les tables d'état ont tendance à être assez grandes. Cela laisse LALR comme le choix pratique.
Cela dit, il vaut la peine de savoir que les analyseurs GLR peuvent analyser n'importe quel langage sans contexte, en utilisant des machines plus compliquées mais exactement les mêmes tables (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 analysera selon elle. La différence dans la machinerie est que GLR est prêt à essayer plusieurs analyses en cas de conflit entre la table GOTO et / ou les ensembles d'anticipation. (Comment GLR le fait efficacement est un pur génie [pas le mien] mais ne rentrera pas dans ce message SO).
C'est pour moi un fait extrêmement utile. Je construis des analyseurs de programmes et des transformateurs de code et des analyseurs 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 post-analyse. L'utilisation de GLR signifie que je peux relativement facilement créer des grammaires fonctionnelles, par rapport au piratage d'une grammaire pour obtenir une forme utilisable par LALR. Cela compte beaucoup lorsque vous essayez de gérer 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 l'ensemble du langage, et vous ne voulez pas passer votre vie à essayer de pirater les règles de grammaire pour répondre aux limitations de LALR (ou même LR).
Comme une sorte d'exemple célèbre, C ++ est considéré comme extrêmement difficile à analyser ... par les gars qui font l'analyse LALR. Le C ++ est simple à analyser à l'aide de la machinerie GLR en utilisant à peu près les règles fournies à l'arrière du manuel de référence C ++. (J'ai précisément un tel analyseur, et il gère non seulement le C ++ vanille, mais aussi une variété de dialectes de fournisseurs. Ceci n'est possible qu'en pratique parce que nous utilisons un analyseur GLR, IMHO).
[EDIT Novembre 2011: Nous avons étendu notre analyseur pour gérer l'ensemble de C ++ 11. GLR a rendu cela beaucoup plus facile à faire. EDIT août 2014: gère maintenant tout C ++ 17. Rien ne s'est cassé ou n'a empiré, GLR est toujours le miaulement du chat.]