Happy/YACC réduisant quand il devrait changer
-
15-11-2019 - |
Question
Je travaille sur un analyseur et je suis vraiment frustré.Dans le langage, on peut avoir une expression comme :
new int[3][][]
ou
new int[3]
La plupart sont analysés correctement, à l'exception des tableaux vides à la fin.Dans mon analyseur j'ai :
Expression : int
char
null
(...many others...)
new NewExpression
et puis une NewExpression est :
NewExpression : NonArrayType '[' Expression ']' EmptyArrays
| NonArrayType '[' Expression ']'
et puis EmptyArrays est une ou plusieurs accolades vides - si EmptyArrays dérive la chaîne vide, il ajoute 20 conflits de décalage/réduction :
EmptyArrays : EmptyArrays EmptyArray
| EmptyArray
EmptyArray : '[' ']'
Cependant, quand je regarde dans .info
fichier pour l'analyseur, j'obtiens ceci :
State 214¬
¬
▸ NewExpression -> NonArrayType lbrace Expression rbrace . EmptyArrays (rule 80)¬
▸ NewExpression -> NonArrayType lbrace Expression rbrace . (rule 81)¬
¬
▸ dot reduce using rule 81¬
▸ ';' reduce using rule 81¬
▸ ',' reduce using rule 81¬
▸ '+' reduce using rule 81¬
▸ '-' reduce using rule 81¬
▸ '*' reduce using rule 81¬
▸ '/' reduce using rule 81¬
▸ '<' reduce using rule 81¬
▸ '>' reduce using rule 81¬
▸ '<=' reduce using rule 81¬
▸ '>=' reduce using rule 81¬
▸ '==' reduce using rule 81¬
▸ '!=' reduce using rule 81¬
▸ ')' reduce using rule 81¬
▸ '[' reduce using rule 81 --I expect this should shift
▸ ']' reduce using rule 81¬
▸ '?' reduce using rule 81¬
▸ ':' reduce using rule 81¬
▸ '&&' reduce using rule 81¬
▸ '||' reduce using rule 81
Je m'attends cependant à ce que si nous sommes dans l'état 214 et que nous voyons une accolade gauche, nous devrions la déplacer sur la pile et continuer à analyser EmptyArrays.
Je ne suis pas exactement sûr de ce qui se passe, car lorsque je retire tout l'excédent du bagage (par exemple) en commençant l'analyse avec NewExpression
, les crochets supplémentaires sont analysés correctement.Il n'est pas possible qu'une expression, une instruction ou tout autre non-terminal de la grammaire commence par une accolade gauche.Surtout parce que j'ai une règle similaire pour les instructions if/else, qui génère un conflit shift/reduce, mais choisit de décaler si le jeton suivant est un else (ce problème est bien documenté).
Pouvez-vous m'aider à comprendre ce qui ne va pas ?J'apprécie vraiment votre aide, je m'attaque vraiment aux moulins à vent pour essayer de comprendre le problème.
La solution
Vous avez probablement une priorité définie pour '[' et/ou ']' avec quelque chose comme %left '['
ce qui provoque ce comportement.Supprimez cette déclaration de priorité, et cela révélera le conflit de décalage/réduction que vous avez ici.Quant à savoir pourquoi il s'agit d'un conflit décalage/réduction, vous avez probablement aussi une règle :
Expression: Expression '[' Expression ']'
pour un accès au tableau.Le problème étant que depuis un NewExpression
est un Expression
il peut être suivi d'un index comme celui-ci, et lorsque l'on regarde l'anticipation de '[', il ne peut pas dire s'il s'agit du début d'une expression d'index ou du début d'une expression d'index. EmptyArray
-- cela nécessiterait une anticipation de 2 jetons.
Une chose que vous pourriez essayer pour ce cas spécifique serait de demander à votre lexer d'effectuer l'anticipation supplémentaire nécessaire ici et de reconnaître []
comme un seul jeton.