Le problème est que vous ne tenez pas compte du changement/réduire les conflits que vous obtenez de votre générateur d'analyseur syntaxique. Alors que yacc/bison (et vraisemblablement PLY) va résoudre les erreurs pour vous, cette résolution pourrait ne pas faire ce que vous voulez, et pourrait aboutir à un analyseur qui analyse une langauge autre que celle que vous essayez d'analyser. Chaque fois que vous obtenez un décalage/réduit (ou réduit/réduit) conflit d'un générateur d'analyseur LR, vous devez vraiment comprendre quel est le conflit (et pourquoi il se produit) pour savoir si vous pouvez l'ignorer ou si vous avez besoin réparer. permet donc corriger votre grammaire en se débarrassant de la « bidouille » (ce qui est manifestement erronée et non quelque chose que vous voulez analyser), ainsi que la règle « vide » inutile (qui confond juste les choses):
%token FILE NUMBER
%%
algebraic_notation : piece start_position capture end_position promotion
piece : 'K' | 'Q' | 'B' | 'N' | 'R' | /*pawn*/
start_position : FILE | NUMBER | FILE NUMBER | /*empty*/
end_position : FILE NUMBER
capture : 'x' | /*empty*/
promotion : '=' 'Q' | '=' 'R' | '=' 'N' | '=' 'B' | /*empty*/
Maintenant, quand vous lancez ceci dans 'bison -v' (TOUJOURS utiliser -v pour obtenir le fichier de sortie verbeux - je ne suis pas sûr de l'équivalent de PLY), vous obtenez le message concernant un changement/réduction de conflit, et si vous regardez dans le fichier .output
vous pouvez voir ce qu'il est:
state 7
1 algebraic_notation: piece . start_position capture end_position promotion
FILE shift, and go to state 9
NUMBER shift, and go to state 10
FILE [reduce using rule 11 (start_position)]
$default reduce using rule 11 (start_position)
start_position go to state 11
Ce que vous dit après avoir vu un piece
, quand le prochain jeton est FILE
, il ne sait pas s'il doit se décaler (en traitant le FILE
comme faisant partie du start_position
) ou réduire (en donnant un start_position
vide). C'est parce qu'il faut plus d'attention pour voir s'il y a une seconde position à utiliser comme end_position
pour savoir quoi faire, donc simplement ignorer le conflit résultera en un analyseur qui échoue à analyser beaucoup de choses valides (en gros, n'importe quoi start_position
et capture
). La meilleure façon de résoudre un conflit lié à la prévisualisation - réduire un conflit impliquant une production vide comme celle-ci (ou pratiquement tout conflit impliquant une production vide, en réalité) est de débloquer la grammaire - se débarrasser de la règle vide et dupliquer toute règle qui utilise le non-terminal à la fois avec et sans lui.Dans votre cas, cela vous donne les règles:
algebraic_notation : piece capture end_position promotion
algebraic_notation : piece start_position capture end_position promotion
start_position : FILE | NUMBER | FILE NUMBER
(les autres règles ne changent pas) Avec que vous avez encore un conflit de décalage réduire:
state 7
1 algebraic_notation: piece . capture end_position promotion
2 | piece . start_position capture end_position promotion
FILE shift, and go to state 9
NUMBER shift, and go to state 10
'x' shift, and go to state 11
FILE [reduce using rule 14 (capture)]
start_position go to state 12
capture go to state 13
En fait, nous venons Déplacé le conflit une étape et maintenant le problème avec la règle capture
vide. Nous avons donc unfactor cela aussi:
algebraic_notation : piece end_position promotion
algebraic_notation : piece capture end_position promotion
algebraic_notation : piece start_position end_position promotion
algebraic_notation : piece start_position capture end_position promotion
capture : 'x'
et maintenant des rapports de bison pas plus de conflits, afin que nous puissions être raisonnablement confiant, il analysera la façon dont nous voulons. Vous pouvez le simplifier un peu plus en supprimant la règle capture
et en utilisant un littéral 'x'
dans la règle algebraic_notation
. Personnellement, je préfère cela, car je pense qu'il est plus clair d'éviter l'indirection inutile:
%token FILE NUMBER
%%
algebraic_notation : piece end_position promotion
algebraic_notation : piece 'x' end_position promotion
algebraic_notation : piece start_position end_position promotion
algebraic_notation : piece start_position 'x' end_position promotion
piece : 'K' | 'Q' | 'B' | 'N' | 'R' | /*pawn*/
start_position : FILE | NUMBER | FILE NUMBER
end_position : FILE NUMBER
promotion : '=' 'Q' | '=' 'R' | '=' 'N' | '=' 'B' | /*empty*/
Yacc peut-être trop pour ce problème? – Cam
@cam Peut-être. Mais l'analyse des chaînes à la main n'est pas tout à fait claire ou lisible dans mon expérience. – Matthew
Aussi, même si BNF est trop puissant pour cette application particulière, il est toujours possible de rencontrer ce problème dans une grammaire plus complexe. De toute façon, j'ai une solution de contournement/hack; Je simplement que je veux utiliser une meilleure solution si possible. – Matthew