Dans un analyseur LALR(1), les règles de la grammaire sont converties en une table d'analyse qui dit effectivement "Si vous avez cette entrée jusqu'ici, et que le token lookahead est X, alors passez à l'état Y, ou réduisez par la règle R".
J'ai réussi à construire un analyseur LALR(1) dans un langage interprété (ruby), sans utiliser de générateur, mais en calculant une table d'analyse à l'exécution et en évaluant l'entrée en utilisant cette table d'analyse. Cela fonctionne étonnamment bien et la génération de la table est assez triviale (ce qui m'a quelque peu surpris), supportant les règles autoréférentielles et l'association gauche/droite.
Cependant, j'ai du mal à comprendre comment yacc/bison traite conceptuellement les définitions de règles vides. Mon analyseur syntaxique ne peut pas les gérer, car en générant la table, il examine chaque symbole dans chaque règle, de manière récursive, et "vide" n'est tout simplement pas quelque chose qui viendra du lexer, ni qui sera réduit par une règle. Alors, comment les analyseurs LALR(1) traitent-ils la règle vide ? La traitent-ils spécialement, ou est-ce un concept "naturel" avec lequel un algorithme valide devrait simplement travailler, sans même avoir besoin d'avoir une conscience particulière d'un tel concept ?
Par exemple, une règle qui peut faire correspondre un nombre quelconque de parenthèses appariées sans rien au milieu :
expr: /* empty */
| '(' expr ')'
;
Une entrée comme la suivante correspondrait à cette règle :
((((()))))
Cela signifie qu'à la lecture de '(' et à la vue de ')' dans le token lookahead, l'analyseur choisit :
- Décalez le ')' (pas possible)
- Réduire l'entrée selon une autre règle (pas possible)
- Autre chose...
ne correspondent pas tout à fait à l'algorithme de base de "shift" ou "reduce". L'analyseur syntaxique a effectivement besoin de ne rien déplacer sur la pile, de réduire "rien" en expr
puis déplace le jeton suivant ')'
donnant '(' expr ')'
qui se réduit bien sûr à expr
et ainsi de suite.
C'est le "shift nothing" qui me perturbe. Comment la table d'analyse syntaxique transmet-elle un tel concept ? Considérez également qu'il devrait être possible d'invoquer une action sémantique qui renvoie une valeur à $$
sur la réduction de la valeur vide, donc une vue plutôt simpliste de juste sauter cela de la table d'analyse et de dire que '('
sur la pile et ')'
dans le lookahead devrait simplement se traduire par un décalage, ne produirait pas véritablement la séquence '(' expr ')'
mais produirait simplement la séquence '(' ')'
.