Dans la conception du compilateur, pourquoi la récursion gauche devrait-elle être éliminée dans les grammaires? Je lis que c'est parce que cela peut provoquer une récursion infinie, mais n'est-ce pas également vrai pour une grammaire récursive correcte?
20
Réponses:
Les grammaires récursives gauches ne sont pas nécessairement une mauvaise chose. Ces grammaires sont facilement analysées à l'aide d'une pile pour garder une trace des phrases déjà analysées, comme c'est le cas dans l' analyseur LR .
Rappelons qu'une règle récursive gauche d'une grammaire CF est de la forme:G = ( V, Σ , R , S)
avec un élément de V et β un élément de V ∪ Σ . (Voir la définition formelle complète du tuple ( V , Σ , R , S ) ici ).α V β V∪Σ (V,Σ,R,S)
Chaque fois qu'un nouveau terminal est reçu par l'analyseur grammatical (à partir du lexer), ce terminal est poussé au sommet de la pile: cette opération est appelée décalage .
Chaque fois que le côté droit d'une règle correspond à un groupe d'éléments consécutifs en haut de la pile, ce groupe est remplacé par un seul élément représentant la phrase nouvellement mise en correspondance. Ce remplacement s'appelle une réduction .
Avec de bonnes grammaires récursives, la pile peut croître indéfiniment jusqu'à ce qu'une réduction se produise, limitant ainsi de façon assez spectaculaire les possibilités d'analyse. Cependant, ceux récursifs laissés permettront au compilateur de générer des réductions plus tôt (en fait, dès que possible). Voir l' entrée wikipedia pour plus d'informations.
la source
Considérez cette règle:
Considérons maintenant un analyseur LL essayant de faire correspondre une chaîne qui ne correspond pas
'b'
à cette règle. Puisque'a'
ne correspond pas, il essaiera de correspondreexample 'b'
. Mais pour ce faire, il doit correspondreexample
... c'est ce qu'il essayait de faire en premier lieu. Il pourrait rester bloqué en essayant pour toujours de voir s'il peut correspondre, car il essaie toujours de faire correspondre le même flux de jetons à la même règle.Pour éviter cela, vous devez soit analyser à droite (ce qui est assez rare, pour autant que je sache, et faire à la place la bonne récursivité le problème), limiter artificiellement la quantité d'imbrication autorisée, ou correspondre un jeton avant le début de la récursivité donc il y a toujours un cas de base (à savoir, où tous les jetons ont été consommés et il n'y a toujours pas de correspondance complète). Puisqu'une règle récursive droite fait déjà le troisième, elle n'a pas le même problème.
la source
(Je sais que cette question est assez ancienne maintenant, mais au cas où d'autres personnes auraient la même question ...)
Demandez-vous dans le contexte des analyseurs de descente récursive? Par exemple, pour la grammaire
expr:: = expr + term | term
, pourquoi quelque chose comme ça (à gauche récursif):est problématique, mais pas cela (droit récursif)?
Il ressemble aux deux versions de
expr()
s'appeler. Mais la différence importante est le contexte - c'est-à-dire le jeton actuel lorsque cet appel récursif est effectué.Dans le cas récursif gauche,
expr()
s'appelle continuellement avec le même jeton et aucun progrès n'est fait. Dans le cas récursif de droite, il consomme une partie de l'entrée dans l'appel àterm()
et le jeton PLUS avant d'atteindre l'appel àexpr()
. Donc, à ce stade, l'appel récursif peut appeler term, puis se terminer avant d'atteindre à nouveau le test if.Par exemple, envisagez d'analyser 2 + 3 + 4. L'analyseur récursif gauche appelle
expr()
infiniment tout en étant bloqué sur le premier jeton, tandis que l'analyseur récursif droit consomme "2 +" avant d'appeler àexpr()
nouveau. Le deuxième appelexpr()
correspond à "3 +" et appelleexpr()
avec seulement le 4 restant. Le 4 correspond à un terme et l'analyse se termine sans plus d'appels àexpr()
.la source
Du manuel Bison:
"Tout type de séquence peut être défini en utilisant la récursion gauche ou la récursivité droite, mais vous devez toujours utiliser la récursion gauche , car elle peut analyser une séquence de n'importe quel nombre d'éléments avec un espace de pile limité. La récursivité droite utilise de l'espace sur la pile Bison dans proportionnelle au nombre d'éléments dans la séquence, car tous les éléments doivent être déplacés sur la pile avant que la règle ne puisse être appliquée une seule fois. Voir l'algorithme de l'analyseur de bisons, pour plus d'explications. "
http://www.gnu.org/software/bison/manual/html_node/Recursion.html
Cela dépend donc de l'algorithme de l'analyseur, mais comme indiqué dans d'autres réponses, certains analyseurs peuvent tout simplement ne pas fonctionner avec la récursion gauche
la source