Antlr4:无法理解为什么将某些东西分解成子规则不起作用
Antlr4: Can't understand why breaking something out into a subrule doesn't work
我还是 Antlr4 的新手,我遇到了一个可能非常愚蠢的问题。
这是我的 .g4 文件中的一个片段:
assignStatement
: VariableName '=' expression ';'
;
expression
: (value | VariableName)
| bin_op='(' expression ')'
| expression UNARY_PRE_OR_POST
| (UNARY_PRE_OR_POST | '+' | '-' | '!' | '~' | type_cast) expression
| expression MUL_DIV_MOD expression
| expression ADD_SUB expression
;
VariableName
: ( [a-z] [A-Za-z0-9_]* )
;
// Pre or post increment/decrement
UNARY_PRE_OR_POST
: '++' | '--'
;
// multiply, divide, modulus
MUL_DIV_MOD
: '*' | '/' | '%'
;
// Add, subtract
ADD_SUB
: '+' | '-'
;
我的示例输入:
myInt = 10 + 5;
myInt = 10 - 5;
myInt = 1 + 2 + 3;
myInt = 1 + (2 + 3);
myInt = 1 + 2 * 3;
myInt = ++yourInt;
yourInt = (10 - 5)--;
第一个示例行 myInt = 10 + 5;
行产生此错误:
line 22:11 mismatched input '+' expecting ';'
line 22:14 extraneous input ';' expecting {<EOF>, 'class', '{', 'interface', 'import', 'print', '[', '_', ClassName, VariableName, LITERAL, STRING, NUMBER, NUMERIC_LITERAL, SYMBOL}
我在每一行中都遇到了类似的问题。
如果我做一个更改,一大堆错误就会消失:
| expression ADD_SUB expression
改成这样:
| expression ('+' | '-') expression
我已经尝试了很多东西。我试过同时使用词法分析器和解析器规则(即,将其称为 add_sub
或 ADD_SUB
)。我尝试了各种括号组合。
我试过了:
ADD_SUB: [+-];
令人恼火的是,只要我没有因 +-* 产生的错误,前增量行和 post 增量行就不会产生任何错误。然而他们依赖 UNARY_PRE_OR_POST。当然,也许它并没有真正使用它,而是使用了我不清楚的其他东西。
目前,我只是删除了子规则语法,并将所有内容嵌入到主规则中。但我想了解发生了什么。
所以...正确的方法是什么:
不要在解析器规则中使用文字标记(除非您知道自己在做什么)。
对于语法:
expression
: '+' expression
| ...
;
ADD_SUB
: '+' | '-'
;
ANTLR 将为文字 '+'
创建词法分析器规则,使语法看起来像这样:
expression
: T__0 expression
| ...
;
T__0 : '+';
ADD_SUB
: '+' | '-'
;
导致输入 +
永远不会成为 ADD_SUB
标记,因为 T__0
总是首先匹配它。这就是词法分析器的简单操作方式:尝试为每个词法分析器规则匹配尽可能多的字符,并且当 2 个(或更多)匹配相同数量的字符时,让第一个定义的“赢”。
改为执行以下操作:
expression
: value
| '(' expression ')'
| expression UNARY_PRE_OR_POST
| (UNARY_PRE_OR_POST | ADD | SUB | EXCL | TILDE | type_cast) expression
| expression (MUL | DIV | MOD) expression
| expression (ADD | SUB) expression
;
value
: ...
| VariableName
;
VariableName
: [a-z] [A-Za-z0-9_]*
;
UNARY_PRE_OR_POST
: '++' | '--'
;
MUL : '*';
DIV : '/';
MOD : '%';
ADD : '+';
SUB : '-';
EXCL : '!';
TILDE : '~';
我还是 Antlr4 的新手,我遇到了一个可能非常愚蠢的问题。
这是我的 .g4 文件中的一个片段:
assignStatement
: VariableName '=' expression ';'
;
expression
: (value | VariableName)
| bin_op='(' expression ')'
| expression UNARY_PRE_OR_POST
| (UNARY_PRE_OR_POST | '+' | '-' | '!' | '~' | type_cast) expression
| expression MUL_DIV_MOD expression
| expression ADD_SUB expression
;
VariableName
: ( [a-z] [A-Za-z0-9_]* )
;
// Pre or post increment/decrement
UNARY_PRE_OR_POST
: '++' | '--'
;
// multiply, divide, modulus
MUL_DIV_MOD
: '*' | '/' | '%'
;
// Add, subtract
ADD_SUB
: '+' | '-'
;
我的示例输入:
myInt = 10 + 5;
myInt = 10 - 5;
myInt = 1 + 2 + 3;
myInt = 1 + (2 + 3);
myInt = 1 + 2 * 3;
myInt = ++yourInt;
yourInt = (10 - 5)--;
第一个示例行 myInt = 10 + 5;
行产生此错误:
line 22:11 mismatched input '+' expecting ';'
line 22:14 extraneous input ';' expecting {<EOF>, 'class', '{', 'interface', 'import', 'print', '[', '_', ClassName, VariableName, LITERAL, STRING, NUMBER, NUMERIC_LITERAL, SYMBOL}
我在每一行中都遇到了类似的问题。
如果我做一个更改,一大堆错误就会消失:
| expression ADD_SUB expression
改成这样:
| expression ('+' | '-') expression
我已经尝试了很多东西。我试过同时使用词法分析器和解析器规则(即,将其称为 add_sub
或 ADD_SUB
)。我尝试了各种括号组合。
我试过了:
ADD_SUB: [+-];
令人恼火的是,只要我没有因 +-* 产生的错误,前增量行和 post 增量行就不会产生任何错误。然而他们依赖 UNARY_PRE_OR_POST。当然,也许它并没有真正使用它,而是使用了我不清楚的其他东西。
目前,我只是删除了子规则语法,并将所有内容嵌入到主规则中。但我想了解发生了什么。
所以...正确的方法是什么:
不要在解析器规则中使用文字标记(除非您知道自己在做什么)。
对于语法:
expression
: '+' expression
| ...
;
ADD_SUB
: '+' | '-'
;
ANTLR 将为文字 '+'
创建词法分析器规则,使语法看起来像这样:
expression
: T__0 expression
| ...
;
T__0 : '+';
ADD_SUB
: '+' | '-'
;
导致输入 +
永远不会成为 ADD_SUB
标记,因为 T__0
总是首先匹配它。这就是词法分析器的简单操作方式:尝试为每个词法分析器规则匹配尽可能多的字符,并且当 2 个(或更多)匹配相同数量的字符时,让第一个定义的“赢”。
改为执行以下操作:
expression
: value
| '(' expression ')'
| expression UNARY_PRE_OR_POST
| (UNARY_PRE_OR_POST | ADD | SUB | EXCL | TILDE | type_cast) expression
| expression (MUL | DIV | MOD) expression
| expression (ADD | SUB) expression
;
value
: ...
| VariableName
;
VariableName
: [a-z] [A-Za-z0-9_]*
;
UNARY_PRE_OR_POST
: '++' | '--'
;
MUL : '*';
DIV : '/';
MOD : '%';
ADD : '+';
SUB : '-';
EXCL : '!';
TILDE : '~';