Моя простая грамматика ANTLR игнорирует некоторые неверные токены при разборе

Я задал вопрос пару недель назад о моей грамматике ANTLR ( моя простая грамматика ANTLR не работает должным образом). С тех пор как я задал этот вопрос, я стал больше копать и отлаживать и получил большую часть изломов. Я остался с одной проблемой, хотя.

Мой сгенерированный код синтаксического анализатора не собирает недопустимые токены в одной определенной части текста, который обрабатывается. Лексер правильно разбивает вещи на токены, но в некоторых случаях парсер не выбрасывает недействительные токены. В частности, когда недопустимый токен находится в конце фразы, такой как "A и B", анализатор игнорирует его - как будто токена даже нет.

Некоторые конкретные примеры:

  • "А и Б" - совершенно верно
  • "A@ and B" - синтаксический анализатор правильно подбирает неверный токен @
  • "A and @B" - парсер правильно выбирает неверный токен @
  • "A и B@" - вот загадка - лексер находит маркер @, а анализатор игнорирует его (!)
  • "(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;
}

1 ответ

Добавьте EOF в конец вашего начального правила.:)

Другие вопросы по тегам