2

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

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

基于 Bart Kiers 工作的简单数学解析器

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

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

functionCall 规则显示解析错误

还有这个;

显示解析错误的列表规则

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

在此先感谢伊恩·卡森

4

1 回答 1

2

规则中有太多的 OR 运算符,condExp使语法模棱两可。

你有:

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)
     )?  
  ;  

对应于:

在此处输入图像描述

于 2013-03-01T08:59:29.573 回答