J'ai posé une question il y a quelques semaines à propos de ma grammaire ANTLR (My simple ANTLR grammar is not working as expected). Depuis que j'ai posé cette question, j'ai creusé et débogué davantage et j'ai éliminé la plupart des problèmes. Je reste avec un problème, cependant.Ma simple grammaire ANTLR ignore certains jetons invalides lors de l'analyse
Mon code d'analyse généré ne récupère pas les jetons non valides dans une partie du texte traitée. Le lexer brise correctement les objets en jetons, mais l'analyseur ne supprime pas les jetons invalides dans certains cas. En particulier, lorsque le jeton invalide est à la fin d'une phrase comme « A et « B », l'analyseur ne tient pas compte - c'est comme le jeton est même pas là
Quelques exemples spécifiques:
.- "A et B" - parfaitement valable
- "A @ et B" - analyseur capte correctement le jeton invalide @
- "A et @B" - analyseur capte correctement le jeton invalide @
- "A et B @" - voici le mystère - t il lexer trouve le jeton @ et l'analyseur IGNORE il
- "(A et B @) ou C" (!) - plus mystère - (!) le lexer trouve le jeton @ et l'analyseur IGNORE il
Voici ma grammaire:
grammar QvidianPlaybooks;
options{ language=CSharp3; output=AST; ASTLabelType = CommonTree; }
public parse
: expression
;
LPAREN : '(' ;
RPAREN : ')' ;
ANDOR : 'AND'|'and'|'OR'|'or';
NAME : ('A'..'Z');
WS : ' ' { $channel = Hidden; };
THEREST : .;
// ***************** parser rules:
expression : anexpression EOF!;
anexpression : atom (ANDOR^ atom)*;
atom : NAME | LPAREN! anexpression RPAREN!;
le code qui traite ensuite l'arbre résultant ressemble à ceci:
... from the main program
QvidianPlaybooksLexer lexer = new QvidianPlaybooksLexer(new ANTLRStringStream(src));
QvidianPlaybooksParser parser = new QvidianPlaybooksParser(new CommonTokenStream(lexer));
parser.TreeAdaptor = new CommonTreeAdaptor();
CommonTree tree = (CommonTree)parser.parse().Tree;
ValidateTree(tree, 0, iValidIdentifierCount);
// recursive code that walks the tree
public static RuleLogicValidationResult ValidateTree(ITree Tree, int depth, int conditionCount)
{
RuleLogicValidationResult rlvr = null;
if (Tree != null)
{
CommonErrorNode commonErrorNode = Tree as CommonErrorNode;
if (null != commonErrorNode)
{
rlvr = new RuleLogicValidationResult();
rlvr.IsValid = false;
rlvr.ErrorType = LogicValidationErrorType.Other;
Console.WriteLine(rlvr.ToString());
}
else
{
string strTree = Tree.ToString();
strTree = strTree.Trim();
strTree = strTree.ToUpper();
if ((Tree.ChildCount != 0) && (Tree.ChildCount != 2))
{
rlvr = new RuleLogicValidationResult();
rlvr.IsValid = false;
rlvr.ErrorType = LogicValidationErrorType.Other;
rlvr.InvalidIdentifier = strTree;
rlvr.ErrorPosition = 0;
Console.WriteLine(String.Format("CHILD COUNT of {0} = {1}", strTree, tree.ChildCount));
}
// if the current node is valid, then validate the two child nodes
if (null == rlvr || rlvr.IsValid)
{
// output the tree node
for (int i = 0; i < depth; i++)
{
Console.Write(" ");
}
Console.WriteLine(Tree);
rlvr = ValidateTree(Tree.GetChild(0), depth + 1, conditionCount);
if (rlvr.IsValid)
{
rlvr = ValidateTree(Tree.GetChild(1), depth + 1, conditionCount);
}
}
else
{
Console.WriteLine(rlvr.ToString());
}
}
}
else
{
// this tree is null, return a "it's valid" result
rlvr = new RuleLogicValidationResult();
rlvr.ErrorType = LogicValidationErrorType.None;
rlvr.IsValid = true;
}
return rlvr;
}
Je ne pense pas que EOF va le faire - et - mes exemples n'étaient pas complets. Comme vous pouvez le voir maintenant, "(A et B @) ou C" entraîne également l'ignorance de "@". – user1193
Aussi, n'ai-je pas déjà une EOF à la fin de ma règle de départ? – user1193
oh. j'ai vu ceci: analyser : expression ; Hmm ... je ne suis pas sûr d'une enquête plus approfondie. pas le temps. –