我的简单ANTLR语法在解析时忽略某些无效标记

我的简单ANTLR语法在解析时忽略某些无效标记,antlr,antlr3,Antlr,Antlr3,几周前我问了一个关于ANTLR语法的问题()。自从提出这个问题以来,我做了更多的挖掘和调试,并解决了大部分问题。不过,我还有一个问题 我生成的解析器代码没有在处理的文本的某个特定部分中拾取无效标记。lexer正确地将事物分解为标记,但是解析器在某些情况下不会剔除无效的标记特别是,当无效标记位于“a”和“B”等短语的末尾时,解析器会忽略它-就像标记根本不在那里一样。 一些具体例子: “A和B”-完全有效 “A@和B”-解析器正确地拾取无效的@token “A和@B”-解析器正确地拾取无效的@to

几周前我问了一个关于ANTLR语法的问题()。自从提出这个问题以来,我做了更多的挖掘和调试,并解决了大部分问题。不过,我还有一个问题

我生成的解析器代码没有在处理的文本的某个特定部分中拾取无效标记。lexer正确地将事物分解为标记,但是解析器在某些情况下不会剔除无效的标记特别是,当无效标记位于“a”和“B”等短语的末尾时,解析器会忽略它-就像标记根本不在那里一样。

一些具体例子:

  • “A和B”-完全有效
  • “A@和B”-解析器正确地拾取无效的@token
  • “A和@B”-解析器正确地拾取无效的@token
  • “A和B@”-这是一个谜-词法分析器找到@token,解析器忽略它(!)
  • “(A和B@)或C”-进一步的神秘-词法分析器找到@标记,解析器忽略它(!)
这是我的语法:

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!;
然后处理结果树的代码如下所示:

... 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;
}
…来自主程序
QvidianPlaybooksLexer=新的QvidianPlaybooksLexer(新的AntlStringStream(src));
QvidianPlaybooksParser=newqvidianplaybooksparser(newcommontokenstream(lexer));
parser.TreeAdaptor=新的CommonTreeAdaptor();
CommonTree=(CommonTree)parser.parse().tree;
ValidateTree(树,0,iValidIdentifierCount);
//遍历树的递归代码
公共静态RuleLogicValidationResult ValidateTree(ITree树、int深度、int条件计数)
{
RuleLogicValidationResult rlvr=null;
如果(树!=null)
{
CommonErrorNode CommonErrorNode=作为CommonErrorNode的树;
if(null!=commonErrorNode)
{
rlvr=新规则逻辑验证结果();
rlvr.IsValid=false;
rlvr.ErrorType=LogicValidationErrorType.Other;
Console.WriteLine(rlvr.ToString());
}
其他的
{
字符串strTree=Tree.ToString();
strTree=strTree.Trim();
strTree=strTree.ToUpper();
如果((Tree.ChildCount!=0)和&(Tree.ChildCount!=2))
{
rlvr=新规则逻辑验证结果();
rlvr.IsValid=false;
rlvr.ErrorType=LogicValidationErrorType.Other;
rlvr.InvalidIdentifier=strTree;
rlvr.ErrorPosition=0;
WriteLine(String.Format(“子计数{0}={1}”,strTree,tree.ChildCount));
}
//如果当前节点有效,则验证两个子节点
if(null==rlvr | | rlvr.IsValid)
{
//输出树节点
for(int i=0;i
将EOF添加到开始规则的末尾。

将EOF添加到开始规则的末尾。

我认为EOF不会做到这一点-我的示例不完整。正如您现在看到的,“(A和B@)或C”也会导致”@“被忽略了。还有,我的开始规则末尾不是已经有EOF了吗?哦。我看到了:parse:expression;嗯…不确定,没有更深入的调查。没时间了。我认为EOF做不到——而且——我的例子不完整。正如你现在看到的,“(A和B@)或C”也会导致“@”被忽略。另外,我的开始规则的末尾不是已经有了EOF吗?哦。我看到了:parse:expression;嗯…不确定,没有更深入的调查。没时间了。