Antlr4左递归规则包含一个左递归替代项,后面可以跟一个空字符串

Antlr4左递归规则包含一个左递归替代项,后面可以跟一个空字符串,antlr4,left-recursion,Antlr4,Left Recursion,所以我定义了一个语法来解析C风格的语法语言: grammar mygrammar; program : (declaration)* (statement)* EOF ; declaration : INT ID '=' expression ';' ; assignment : ID '=' expression ';' ; expression : expression (op=('*'|'/') expression)* | expression (op=('+'|'-')

所以我定义了一个语法来解析C风格的语法语言:

grammar mygrammar;

program
: (declaration)*
  (statement)*
  EOF
;

declaration
: INT ID '=' expression ';'
;

assignment
: ID '=' expression ';'
;

expression
: expression (op=('*'|'/') expression)*
| expression (op=('+'|'-') expression)*
| relation
| INT
| ID
| '(' expression ')'
;

relation
: expression (op=('<'|'>') expression)*
;

statement
: expression ';'
| ifstatement
| loopstatement
| printstatement
| assignment
;

ifstatement
: IF '(' expression ')' (statement)* FI ';'
;

loopstatement
: LOOP '(' expression ')' (statement)* POOL ';'
;

printstatement
: PRINT '(' expression ')' ';'
;

IF : 'if';
FI : 'fi';
LOOP : 'loop';
POOL : 'pool';
INT : 'int';
PRINT : 'print';
ID : [a-zA-Z][a-zA-Z0-9]*;
INTEGER : [0-9]+;
WS : [ \r\n\t] -> skip;
语法我的语法;
程序
:(声明)*
(声明)*
EOF
;
宣言
:INT ID'='表达式';'
;
分配
:ID'='表达式';'
;
表达
:表达式(op=(“*”|“/”)表达式)*
|表达式(op=(“+”|“-”)表达式)*
|关系
|INT
|身份证
|“(“表达式”)”
;
关系
:表达式(op=(“”)表达式)*
;
陈述
:表达式“;”
|国际单项体育联合会声明
|循环语句
|打印语句
|分配
;
国际单项体育联合会声明
:如果“(“表达式”)”(语句)*FI“;”
;
循环语句
:循环“(“表达式”)”(语句)*池“;”
;
打印语句
:打印“(“表达式”)”;'
;
如果:‘如果’;
FI:‘FI’;
循环:‘循环’;
游泳池:“游泳池”;
INT:‘INT’;
打印:“打印”;
ID:[a-zA-Z][a-zA-Z0-9]*;
整数:[0-9]+;
WS:[\r\n\t]->跳过;
我可以这样分析一个简单的测试:

int i = (2+3)*3/2*(3+36);
int j = i;
int k = 2*1+i*3;
if (k > 2)
  k = k + 1;
  i = i / 3;
  j = j / 3;
fi;
loop (i < 10)
  i = i + 1 * (i+k);
  j = (j + 1) * (j-k);
  k = i + j;
  print(k);
pool;
inti=(2+3)*3/2*(3+36);
int j=i;
int k=2*1+i*3;
如果(k>2)
k=k+1;
i=i/3;
j=j/3;
fi;
环路(i<10)
i=i+1*(i+k);
j=(j+1)*(j-k);
k=i+j;
印刷品(k);
水塘
但是,当我想在intelliJ中生成ANTLR重定位程序时,我遇到了以下错误:

sCalc.g4:19:0:左递归规则表达式包含一个左递归替代项,该替代项后面可以跟空字符串


我想知道这是否是由我的
ID
可能是空字符串引起的?

这是关于你的
表达式和
关系的
规则。表达式规则可以在一个alt中匹配
关系
,而该alt又返回到
表达式。
规则
关系
由于
(op=('')表达式)*


更好的方法可能是使用
关系
调用
表达式
并从
表达式
中删除
关系
alt。然后使用
关系
现在使用
表达式
的所有地方。这是表达式中的典型场景,从低优先级操作开始作为顶级规则,向下钻取到更高优先级的规则,最终以简单的表达式规则(或类似规则)结束。

您的语法有几个问题:

  • expression
    中有
    INT
    作为替代,而您可能需要
    INTEGER
  • 无需执行
    表达式(op=(“+”|“-”)表达式)*
    :这将执行:
    表达式op=(“+”|“-”)表达式
  • ANTLR4不支持间接左递归规则:必须在
    表达式中包含
    关系
像这样的事情应该可以做到:

grammar mygrammar;

program
: (declaration)*
  (statement)*
  EOF
;

declaration
: INT ID '=' expression ';'
;

assignment
: ID '=' expression ';'
;

expression
: expression op=('*'|'/') expression
| expression op=('+'|'-') expression
| expression op=('<'|'>') expression
| INTEGER
| ID
| '(' expression ')'
;

statement
: expression ';'
| ifstatement
| loopstatement
| printstatement
| assignment
;

ifstatement
: IF '(' expression ')' (statement)* FI ';'
;

loopstatement
: LOOP '(' expression ')' (statement)* POOL ';'
;

printstatement
: PRINT '(' expression ')' ';'
;

IF : 'if';
FI : 'fi';
LOOP : 'loop';
POOL : 'pool';
INT : 'int';
PRINT : 'print';
ID : [a-zA-Z][a-zA-Z0-9]*;
INTEGER : [0-9]+;
WS : [ \r\n\t] -> skip;
语法我的语法;
程序
:(声明)*
(声明)*
EOF
;
宣言
:INT ID'='表达式';'
;
分配
:ID'='表达式';'
;
表达
:表达式op=(“*”|“/”)表达式
|表达式op=(“+”|“-”)表达式
|表达式op=(“”)表达式
|整数
|身份证
|“(“表达式”)”
;
陈述
:表达式“;”
|国际单项体育联合会声明
|循环语句
|打印语句
|分配
;
国际单项体育联合会声明
:如果“(“表达式”)”(语句)*FI“;”
;
循环语句
:循环“(“表达式”)”(语句)*池“;”
;
打印语句
:打印“(“表达式”)”;'
;
如果:‘如果’;
FI:‘FI’;
循环:‘循环’;
游泳池:“游泳池”;
INT:‘INT’;
打印:“打印”;
ID:[a-zA-Z][a-zA-Z0-9]*;
整数:[0-9]+;
WS:[\r\n\t]->跳过;

也不是说这个
(语句)*
可以简单地写成
语句*

谢谢,这很有效。但我也想知道,antlr4如何简单地将0与多个语句匹配,而不使用
“()”
捕获一组语句。呃,我不明白
(a)*
a*
完全相同。如果你有不止一件事情要重复,那么你需要在它们周围加上括号:
(ab)*
(与
ab*
不同)