【问题标题】:How to resolve "The following alternatives can never be matched"如何解决“以下备选方案永远无法匹配”
【发布时间】:2013-03-01 03:39:26
【问题描述】:

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

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

但是当我添加缺失部分的代码以完成教程时,我在“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'  
  ;

我得到的错误信息是

Decision 可以使用多种选择来匹配诸如“CParen”之类的输入:1、2 : Line 79:20

Decision 可以使用多种选择来匹配诸如“CBracket”之类的输入:1、2:第 176:10 行

错误与 functionCall 和 list 规则有关。我检查了 ANTLRWorks 1.5 中的解析器文件,并在那里确认了相同的错误。两条规则的语法图如下所示;

还有这个;

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

提前致谢 伊恩·卡森

【问题讨论】:

  • 我不知道您尝试发布的图像中的内容,但您的规则似乎有点模棱两可,这就是问题所在。例如,Identifier ( explist? ) 案例与 Array ( exp ) 案例没有什么区别...
  • @Stobor 感谢您的指点,我坐在这里查看 ANTLRWorks 语法图(可悲的是,我认为它们很酷 :-))并尝试了一些东西。到目前为止没有运气,但夜晚还很年轻!

标签: antlr antlr3 antlrworks


【解决方案1】:

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

你有:

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

对应:

但应该是:

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

对应:

【讨论】:

  • 嗨,巴特,非常感谢您帮我看看这个小家伙。这样就解决了!我想经验带来的许多技巧之一是超越直接问题规则,因为整个结构作为一个系统工作。下次我会记住的。我添加了缺失的图片来完成我的问题,我试图给你投票,但需要 15 分 - 我稍后会回来
猜你喜欢
  • 1970-01-01
  • 2011-09-12
  • 1970-01-01
  • 2023-03-09
  • 2020-06-06
  • 2018-02-23
  • 2018-08-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多