Parsing 使用antlr解析酷语言,无法打印所需输出

Parsing 使用antlr解析酷语言,无法打印所需输出,parsing,compiler-construction,antlr,left-recursion,ambiguous-grammar,Parsing,Compiler Construction,Antlr,Left Recursion,Ambiguous Grammar,我是为COOL(课堂面向对象语言)编写语法分析器/词法分析器的专家。你可以在下面的链接中看到语法:(手册的最后一页) 我正在使用ANTLR编写此程序,通过以下输入,我希望得到以下输出: 输入: class Main inherits IO { main(): Object {{ x <- 2 + 3 *4; }}; }; 但我得到的结果是: 1 2 3 11 6 27 16 27 18 27 这是我的解析器/词法分析器代码: // parser grammar CA2

我是为COOL(课堂面向对象语言)编写语法分析器/词法分析器的专家。你可以在下面的链接中看到语法:(手册的最后一页)

我正在使用ANTLR编写此程序,通过以下输入,我希望得到以下输出:

输入:

class Main inherits IO {
  main(): Object {{
    x <- 2 + 3 *4;
  }};
};
但我得到的结果是:

1
2
3
11
6
27
16
27
18
27
这是我的解析器/词法分析器代码:

// parser
grammar CA2;

program : {System.out.println("1");} (classdef';')+ ;
classdef : {System.out.println("2");} CLASS ID (INHERITS ID)? '{' (feature';')* '}' ;
feature : {System.out.println("3");} ID OPENP (formal (','formal)*)? CLOSEP ':' ID '{' expr '}' 
        | {System.out.println("4");} ID ':' ID ( POINTTOLEFT expr )? ;
formal : {System.out.println("5");} ID ':' ID ;
expr : {System.out.println("6");} ID POINTTOLEFT expr exprprime
     | {System.out.println("8");} ID OPENP ( expr (','expr)* )? CLOSEP exprprime
     | {System.out.println("9");} IF expr THEN expr ELSE expr FI exprprime
     | {System.out.println("10");} WHILE expr LOOP expr POOL exprprime 
     | {System.out.println("11");} '{' (expr';')+ '}' exprprime 
     | {System.out.println("12");} LET ID ':' ID (POINTTOLEFT expr)? (','ID ':' ID (POINTTOLEFT expr)?)* IN expr exprprime
     | {System.out.println("13");} CASE expr OF (ID POINTTORIGHT expr ';')+ ESAC exprprime
     | {System.out.println("14");} NEW ID exprprime
     | {System.out.println("15");} ISVOID expr exprprime
     /*| {System.out.println("16");} expr ADD expr
     | {System.out.println("17");} expr SUB expr
     | {System.out.println("18");} expr MULTIPLY expr
     | {System.out.println("19");} expr DIV expr
     | {System.out.println("20");} TILDA expr
     | {System.out.println("21");} expr LARGERTHAN expr
     | {System.out.println("22");} expr LARGEREQ expr
     | {System.out.println("23");} expr EQUALS expr
     | {System.out.println("24");} NOT expr
     | {System.out.println("25");} OPENP expr CLOSEP
     | {System.out.println("26");} ID
     | {System.out.println("27");} INTEGER*/
     | {System.out.println("28");} STRING exprprime | mathex exprprime ;
     /*| {System.out.println("29");} TRUE
     | {System.out.println("30");} FALSE ;*/
exprprime : {System.out.println("7");} (('@'ID)?)'.'ID OPENP (expr (','expr)*)? CLOSEP exprprime | ;
mathex : b ;
b : {System.out.println("24");} NOT b | c ;
cprime : {System.out.println("21");} LARGERTHAN d cprime 
       | {System.out.println("22");} LARGEREQ d cprime 
       | {System.out.println("23");} EQUALS d cprime | ;
c : d cprime ;
dprime : {System.out.println("16");} ADD e dprime 
       | {System.out.println("17");} SUB e dprime | ;
d : e dprime ;
eprime : {System.out.println("18");} MULTIPLY f eprime 
       | {System.out.println("19");} DIV f eprime | ;
e : f eprime ;
f : {System.out.println("20");} TILDA f | g ;
g : {System.out.println("25");} OPENP mathex CLOSEP 
  | {System.out.println("26");} ID 
  | {System.out.println("27");} INTEGER 
  | {System.out.println("29");} TRUE 
  | {System.out.println("30");} FALSE ;

//lexer
TRUE : 'true' ;
FALSE : 'false' ;
INHERITS : 'inherits' ;
CLASS : 'class' ;
IF : 'if' ;
THEN : 'then' ;
ELSE : 'else' ;
FI : 'fi' ;
WHILE : 'while' ;
LOOP : 'loop' ;
POOL : 'pool' ;
LET : 'let' ;
IN : 'in' ;
CASE : 'case' ;
OF : 'of' ;
ESAC : 'esac' ;
NEW : 'new' ;
ISVOID : 'isvoid' ;
NOT : 'not' ;
TILDA : '~' ;
WHITESPACE : [ ' '|'\r'|'\n'|'\t']+ ->skip ;
INTEGER : [0-9]+ ;
ID : ['_'a-zA-Z][a-zA-Z0-9'_']* ;
ADD : '+' ;
MULTIPLY : '*' ;
SUB : '-' ;
DIV : '/' ;
OPENP : '(' ;
CLOSEP : ')' ;
EQUALS : '=' ;
LARGERTHAN : '<' ;
LARGEREQ : '<=' ;
POINTTOLEFT : '<-' ;
POINTTORIGHT : '=>' ;
STRING : '"'(~[\r\n])*'"' ;
//语法分析器
语法CA2;
程序:{System.out.println(“1”);}(classdef';')+;
classdef:{System.out.println(“2”);}类ID(继承ID)?'{'(特征';')*'}';
特性:{System.out.println(“3”);}ID OPENP(formal(','formal)*)?CLOSEP':'ID'{'expr'}'
|{System.out.println(“4”);}ID':'ID(POINTTOLEFT expr);
形式:{System.out.println(“5”);}ID':'ID;
expr:{System.out.println(“6”);}ID POINTTOLEFT expr exprprome
|{System.out.println(“8”);}ID OPENP(expr(','expr)*)?关闭表达式
|{System.out.println(“9”);}如果是expr,那么expr ELSE expr FI exprprome
|{System.out.println(“10”);}WHILE expr循环expr池exprprome
|{System.out.println(“11”);}'{'(expr';')+'}'exprprome
|{System.out.println(“12”);}LET ID':'ID(POINTTOLEFT expr)?(','ID':'ID(POINTTOLEFT expr)?)*在expr exprprime中
|{System.out.println(“13”);}(ID POINTTORIGHT expr';')+ESAC exprprime的CASE expr
|{System.out.println(“14”);}新ID exprprome
|{System.out.println(“15”);}ISVOID expr exprprome
/*|{System.out.println(“16”);}expr ADD expr
|{System.out.println(“17”);}expr子expr
|{System.out.println(“18”);}expr乘法expr
|{System.out.println(“19”);}expr DIV expr
|{System.out.println(“20”);}TILDA expr
|{System.out.println(“21”);}expr大于expr
|{System.out.println(“22”);}expr LARGEREQ expr
|{System.out.println(“23”);}expr等于expr
|{System.out.println(“24”);}不是expr
|{System.out.println(“25”);}OPENP expr CLOSEP
|{System.out.println(“26”);}ID
|{System.out.println(“27”);}整数*/
|{System.out.println(“28”)}字符串exprprome | mathex exprprome;
/*|{System.out.println(“29”);}TRUE
|{System.out.println(“30”);}FALSE*/
exprprome:{System.out.println(“7”);}(“@”ID)?”.“ID OPENP(expr(“,”expr)*”)?CLOSEP exprprome |;
mathex:b;
b:{System.out.println(“24”)}不是b|c;
cprime:{System.out.println(“21”);}大于d cprime
|{System.out.println(“22”);}LARGEREQ d cprime
|{System.out.println(“23”)}等于d cprime |;
c:d cprime;
dprome:{System.out.println(“16”);}添加e dprome
|{System.out.println(“17”)}SUB e dprome |;
d:e-dprome;
eprome:{System.out.println(“18”);}乘以eprome
|{System.out.println(“19”)}DIV f eprome |;
e:f eprome;
f:{System.out.println(“20”)}TILDA f|g;
g:{System.out.println(“25”);}OPENP-mathex-CLOSEP
|{System.out.println(“26”);}ID
|{System.out.println(“27”);}整数
|{System.out.println(“29”);}TRUE
|{System.out.println(“30”);}FALSE;
//雷克瑟
真:‘真’;
假:‘假’;
继承:“继承”;
阶级:"阶级";;
如果:‘如果’;
然后:"然后",;
ELSE:‘ELSE’;
FI:‘FI’;
WHILE:‘WHILE’;
循环:‘循环’;
游泳池:“游泳池”;
LET:‘LET’;
IN:'IN';
案例:“案例”;
OF‘OF’;
以撒:“以撒”;
新:"新";;
ISVOID:‘ISVOID’;
不是‘不是’;
蒂尔达:“~”;
空格:[''|'\r'|'\n'|'\t']+->跳过;
整数:[0-9]+;
编号:[“a-zA-Z][a-zA-Z0-9”];
加:“+”;
乘:'*';
SUB:“-”;
分区:“/”;
OPENP:'(';
关闭:')';
等于:'=';

大于:“除了
程序
中的操作之外,每个
println
调用都出现在语法中的标记引用之前。很明显,这意味着它们将按照令牌在文件中出现的相同顺序执行

预期输出和实际输出之间的第一个不匹配是行
16
27
的颠倒。只有当输入中的
+
标记出现在输入中的
2
标记之前时,才会出现预期的输出,但您可以清楚地看到情况并非如此。第二次失配发生的原因相同;具体来说,这是因为预期输出假定
*
标记在语法中出现的时间比
3
标记早


我注意到您最初编写了一个左递归
expr
规则,并在其中包含了嵌入式操作。以下信息与解决您的特定问题无关,但如果您决定取消对该代码的注释并使用左递归形式
expr
,请务必理解

考虑下面的左递归规则,允许简单地添加标识符,并添加两个嵌入式操作

expr
  : {a();} ID
  | {b();} expr '+' ID
  ;
正如您可能发现的那样,此语法不会使用ANTLR编译。我们发现在我在这里展示的位置对表达式
{b();}
求值会对生成的代码产生巨大(负面)性能影响,因此我们选择不允许它。当解析器实际尝试使用对输入进行操作时,输出将是表达式的最终结果。解决方案是使用中缀符号:

expr
  : {a();} ID
  | expr {b();} '+' ID
  ;
通过收集调用
a
b
的结果,您可以在编写结果之前将结果转换为任何您喜欢的符号。另一个选项是将嵌入的操作移动到一个访问者,该访问者在解析完成后执行,在这个访问者中,按照您喜欢的任何顺序执行这些操作都很简单


进一步阅读:

我想你的答案实际上不是答案,而是一个我们想要改变输出的技巧,对吗?你还暗示期望的输出是不正确的,而我的输出实际上是正常的?@AshkanKzme我回答的第一部分(在人力资源上方)准确地解释了你得到的是什么/为什么
expr
  : {a();} ID
  | expr {b();} '+' ID
  ;