Dans l'article Parsing Expressions by Recursive Descent de Theodore Norvell (1999), l'auteur commence par la grammaire suivante pour les expressions arithmétiques:
E --> E "+" E | E "-" E | "-" E | E "*" E | E "/" E | E "^" E | "(" E ")" | v
ce qui est assez mauvais, car il est ambigu et récursif à gauche. Il commence donc par en supprimer la récursion gauche, et son résultat est comme tel:
E --> P {B P}
P --> v | "(" E ")" | U P
B --> "+" | "-" | "*" | "/" | "^"
U --> "-"
Mais je n'arrive pas à comprendre comment il est arrivé à ce résultat. Lorsque j'essaie de supprimer moi-même la récursion gauche, je le fais de la manière suivante:
Premièrement, je regroupe les productions qui n'ont pas laissé de récursivité dans un groupe, et d'autres (gauche-récursive) dans un autre groupe:
E --> E "+" E | E "-" E | E "*" E | E "/" E | E "^" E // L-recursive E --> v | "(" E ")" | "-" E
Ensuite, je les nomme et facteur pour des manipulations plus faciles:
E --> E B E // L-recursive; B stands for "Binary operator" E --> P // not L-recursive; P stands for "Primary Expression" P --> v | "(" E ")" | U E // U stands for "Unary operator" B --> "+" | "-" | "*" | "/" | "^" P --> "-"
Maintenant, je n'ai plus besoin que des deux premières productions, qui sont désormais plus faciles à gérer.
Je réécris ces deux premières productions en partant de la production non récursive (qui est simplement
P
l'expression primaire) et en la suivant par la queue facultativeT
, que je définis comme le reste de la production originale moins la première non récursive gauche non terminale (c'est-à-dire, justeB E
) suivi de la queueT
, ou qui pourrait être vide:E --> P T T --> B E T |
(notez l'alternative vide pour la queue).
Ces deux productions que je peux maintenant réécrire en EBNF comme ceci:
E --> P {B E}
ce qui est presque ce que l'auteur obtient, mais j'ai
E
au lieu deP
là à l'intérieur du modèle de répétition zéro ou plus (la queue). Les autres productions que je reçois sont presque les mêmes que lui:P --> v | "(" E ")" | U E B -> "+" | "-" | "*" | "/" | "^" U -> "-"
mais là aussi j'ai
E
au lieu deP
dans la première production pourP
.
Alors, ma question est: qu'est-ce que je manque? De quelle transformation algébrique de la syntaxe dois-je procéder maintenant pour obtenir la même forme exacte que celle obtenue par l'auteur? J'ai essayé des substitutions pour E
, mais cela ne me mène qu'à des boucles. Je pense que je dois en quelque sorte de remplacer P
pour E
, mais je ne sais pas toute transformation juridique pour le justifier. Peut-être savez-vous quelle est la dernière étape manquante?
Réponses:
L'étape manquante:
réécrire E en T:
Simplifiez T:
Équivalent à:
Et voilà.
la source
T
s en un seulT
? Y a-t-il une règle pour cela? (Je soupçonne que cela pourrait être en quelque sorte similaire à la règle de la logique algébrique booléenne qui dit "aa = a".)*
? J'ai vu cela dans "Dragon Book" (3.3, p.91)x** = x*
. Est-ce la même règle que vous avez utilisée?