antlr - 如何解决 "The following alternatives can never be matched"

标签 antlr antlr3 antlrworks

几天来我一直在努力解决解析器中的“多个替代方案”错误,但没有成功。我一直在使用 Sam Harwell 的 ANTLR3 和 VS2010 端口将 Bart Kiers 优秀的 Tiny Language(TL) 教程代码转换为 C#。感谢这两个人的出色工作。我相信我已经准确地遵循了 Bart 的教程,但由于我是 ANTLR 的新手,所以我不能确定。

我确实让 TL 代码在纯数学基础上运行良好,即没有“函数”或“if then else”或“while”(请参阅​​一个小应用程序的屏幕截图)

Simple Maths Parser based on Bart Kiers work

但是当我添加缺失部分的代码来完成教程时,我在“functionCall”和“list”中遇到解析错误(请参阅下面的代码)

grammar Paralex2;

options {
    language=CSharp3;
    TokenLabelType=CommonToken;
    output=AST;
    ASTLabelType=CommonTree;
}

tokens {
  BLOCK;
  RETURN;
  STATEMENTS;
  ASSIGNMENT;
  FUNC_CALL;
  EXP;
  EXP_LIST;
  ID_LIST;
  IF;
  TERNARY;
  U_SUB;
  NEGATE;
  FUNCTION;
  INDEXES;
  LIST;
  LOOKUP;
}

@lexer::namespace{Paralex2}
@parser::namespace{Paralex2}

/*
 * Parser Rules
 */

@parser::header {using System; using System.Collections.Generic;}

@parser::members{

public SortedList<string, Function> functions = new SortedList<string, Function>();

  private void defineFunction(string id, Object idList, Object block) {

    // `idList` is possibly null! Create an empty tree in that case. 
    CommonTree idListTree = idList == null ? new CommonTree() : (CommonTree)idList;

    // `block` is never null.
    CommonTree blockTree = (CommonTree)block;

    // The function name with the number of parameters after it the unique key
    string key = id + idListTree.Children.Count();
    functions.Add(key, new Function(id, idListTree, blockTree));
  }

}

public parse
  :  block EOF -> block
  ;

block
  :  (statement | functionDecl)* (Return exp ';')?  -> ^(BLOCK ^(STATEMENTS statement*) ^(RETURN exp?))
  ;

statement
  :  assignment ';'   -> assignment
  |  functionCall ';' -> functionCall
  |  ifStatement
  |  forStatement
  |  whileStatement
  ;

assignment
  :  Identifier indexes? '=' exp 
     -> ^(ASSIGNMENT Identifier indexes? exp)
  ;

functionCall
  :  Identifier '(' expList? ')' -> ^(FUNC_CALL Identifier expList?)
  |  Assert '(' exp ')'    -> ^(FUNC_CALL Assert exp)
  |  Size '(' exp ')'      -> ^(FUNC_CALL Size exp)
  ;

ifStatement
  :  ifStat elseIfStat* elseStat? End -> ^(IF ifStat elseIfStat* elseStat?)
  ;

ifStat
  :  If exp Do block -> ^(EXP exp block)
  ;

elseIfStat
  :  Else If exp Do block -> ^(EXP exp block)
  ;

elseStat
  :  Else Do block -> ^(EXP block)
  ;

functionDecl
  :  Def Identifier '(' idList? ')' block End 
     {defineFunction($Identifier.text, $idList.tree, $block.tree);}
  ;

forStatement
  :  For Identifier '=' exp To exp Do block End 
     -> ^(For Identifier exp exp block)
  ;

whileStatement
  :  While exp Do block End -> ^(While exp block)
  ;

idList
  :  Identifier (',' Identifier)* -> ^(ID_LIST Identifier+)
  ;


expList
  :  exp (',' exp)* -> ^(EXP_LIST exp+)
  ;

exp 
  :  condExp  
  ;  

condExp  
  :  (orExp -> orExp)   
  |  ( '?' a=exp ':' b=exp -> ^(TERNARY orExp $a $b)
  |  In exp         -> ^(In orExp exp)
  )?  
  ;  

orExp  
  :  andExp ('||'^ andExp)*  
  ;  

andExp  
  :  equExp ('&&'^ equExp)*  
  ;  

equExp  
  :  relExp (('==' | '!=')^ relExp)*  
  ;  

relExp  
  :  addExp (('>=' | '<=' | '>' | '<')^ addExp)*  
  ;

addExp
  :  mulExp ((Add | Sub)^ mulExp)*
  ;

mulExp
  :  powExp ((Mul | Div)^ powExp)*
  ;

powExp  
  :  unaryExp ('^'^ unaryExp)*  
  ;

unaryExp
  :  Sub atom -> ^(U_SUB atom)
  | '!' atom -> ^(NEGATE atom)
  |  atom
  ;

atom
  :  Nmber
  |  Bool
  |  Null
  |  lookup
  ;

list
  :  '[' expList? ']' -> ^(LIST expList?)
  ;

lookup
  :  list indexes?              -> ^(LOOKUP list indexes?)
  |  functionCall indexes?      -> ^(LOOKUP functionCall indexes?)
  |  Identifier indexes?        -> ^(LOOKUP Identifier indexes?)
  |  String indexes?            -> ^(LOOKUP String indexes?)
  |  '(' exp ')' indexes?       -> ^(LOOKUP exp indexes?)
  ;

indexes
  :  ('[' exp ']')+ -> ^(INDEXES exp+)
  ;


/*
 * Lexer Rules
 */

Assert      : 'assert';
Size        : 'size';
Def         : 'def';
If          : 'if';
Else        : 'else';
Return      : 'return';
For         : 'for';
While       : 'while';
To          : 'to';
Do          : 'do';
End         : 'end';
In          : 'in';
Null        : 'null';

Or          : '||';  
And         : '&&';  
Equals      : '==';  
NEquals     : '!=';  
GTEquals    : '>=';  
LTEquals    : '<=';  
Pow         : '^';  
GT          : '>';  
LT          : '<';
Add         : '+';
Sub         : '-';
Mul         : '*';
Div         : '/';
Modulus     : '%';
OBrace      : '{';
CBrace      : '}';
OBracket    : '[';
CBracket    : ']';
OParen      : '(';
CParen      : ')';
SColon      : ';';
Assign      : '=';
Comma       : ',';
QMark       : '?';
Colon       : ':';

Bool
    :   'true'
    |   'false'
    ;

Nmber
    : Int ('.' Digit*)?
    ;

Identifier
  :  ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | Digit)*
  ;

String
@after {
  setText(getText().substring(1, getText().length()-1).replaceAll("\\\\(.)", "$1"));
}
  :  '"'  (~('"' | '\\')  | '\\' ('\\' | '"'))* '"' 
  |  '\'' (~('\'' | '\\') | '\\' ('\\' | '\''))* '\''
  ;

Comment
  :  '//' ~('\r' | '\n')* {Skip();}
  |  '/*' .* '*/'         {Skip();}
  ;

 Space
  :  (' ' | '\t' | '\r' | '\n' | '\u000C') {Skip();}
  ;

fragment Int  
  :  '1'..'9' Digit*  
  |  '0'  
  ;  

fragment Digit   
  :  '0'..'9'  
  ;

我收到的错误消息是

决策可以使用多个替代项来匹配“CParen”等输入:1, 2:第 79:20 行

决策可以使用多个替代项来匹配“CBracket”等输入:1, 2:第 176:10 行

错误与函数调用和列表规则有关。我检查了 ANTLRWorks 1.5 中的解析器文件并确认了那里存在相同的错误。这两个规则的语法图如下所示;

functionCall rule showing parsing error

还有这个;

list rule showing parsing error

我尝试了一些更改来尝试解决问题,但我似乎无法获得正确的语法。如果你们能提供任何帮助,我将不胜感激,如果有帮助的话,我可以通过电子邮件发送图像。

提前致谢 伊恩·卡森

最佳答案

condExp 规则中的 OR 运算符过多,导致语法不明确。

你有:

condExp  
  :  ( orExp               -> orExp)   
  |  ( '?' a=exp ':' b=exp -> ^(TERNARY orExp $a $b)
     |  In exp             -> ^(In orExp exp)
     )?  
  ;  

对应于:

enter image description here

但应该是:

condExp  
  :  ( orExp               -> orExp)
     ( '?' a=exp ':' b=exp -> ^(TERNARY orExp $a $b)
     |  In exp             -> ^(In orExp exp)
     )?  
  ;  

对应于:

enter image description here

关于antlr - 如何解决 "The following alternatives can never be matched",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15150098/

相关文章:

escaping - 如何使用 ANTLR 4 转义转义字符?

parsing - LL(*) 与 PEG 解析器 : what is the difference?

c# - 为所有可能的增量表达式创建相同的标记

antlr 词法分析器规则与另一个规则的前缀匹配

antlr - 如何使用 ANTLRWorks 创建/指定用于测试树语法的 AST 输入?

java - Antlr 输入字符串时出错

return-value - 如何处理ANTLR中的列表返回值

python - Antlr4 在 RaspberryPi 上运行缓慢

parsing - 为什么 ANTLR 不解析整个输入?

c - 如何让 ANTLR3.5 在 C 中生成的解析器在 MVS EBCDIC 环境中工作?