2013-10-10 56 views
1

幾周前我問了一個關於我的ANTLR語法的問題(My simple ANTLR grammar is not working as expected)。自從提出這個問題以來,我已經做了更多的挖掘和調試,並且獲得了大部分的結果。不過,我留下了一個問題。我的簡單ANTLR語法在解析時忽略了某些無效標記

我生成的解析器代碼沒有在處理的文本的特定部分中拾取無效令牌。詞法分析器正確地將事物分解爲令牌,但在某些情況下解析器不會排除無效令牌。 特別是,當無效令牌是在像「A和‘B’一語結束,解析器會忽略它 - 就像令牌甚至不存在

一些具體的例子:

  • 「A和B」 - 完全有效的
  • 「@和B」 - 解析正確拿起無效@令牌
  • 「A和@B」 - 解析正確拿起無效@令牌
  • 「A和B @」 - 這是神祕 - t他詞法分析器發現@令牌和分析器忽略它
  • 「(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添加到開始規則的末尾。 :)

+0

我不認爲EOF會這樣做 - 而且 - 我的例子並不完整。正如您現在所看到的,「(A和B @)或C」也會導致忽略「@」。 – user1193

+0

另外,我的啓動規則結束時是否已經有EOF? – user1193

+0

哦。我看到這個:解析 :表達式 ;嗯......不確定沒有深入調查。沒時間。 –