如何解决用于正整数文字的SML扼制的ANTLR4语法
我正在使用ANTLR 4.8构建用于SML的解析器,由于某种原因,生成的解析器使整数字面值感到窒息:
# CLASSPATH=bin ./scripts/grun SML expression -tree <<<'1'
line 1:0 mismatched input '1' expecting {'(','let','op','{','()','[','#','raise','if','while','case','fn',LONGID,CONSTANT}
(expression 1)
我从语法上进行了尽可能多的修剪,以显示此问题,这看起来很奇怪。此语法显示了问题(尽管LABEL
甚至没有被使用):
grammar SML_Small;
Whitespace : [ \t\r\n]+ -> skip ;
expression : CONSTANT ;
LABEL : [1-9] NUM* ;
CONSTANT : INT ;
INT : '~'? NUM ;
NUM : DIGIT+ ;
DIGIT : [0-9] ;
另一方面,删除LABEL
可使正数再次起作用:
grammar SML_Small;
Whitespace : [ \t\r\n]+ -> skip ;
expression : CONSTANT ;
CONSTANT : INT ;
INT : '~'? NUM ;
NUM : DIGIT+ ;
DIGIT : [0-9] ;
我尝试用NUM*
和类似的变体替换DIGIT?
,但这并不能解决我的问题。
我真的不确定发生了什么,因此我怀疑它比我使用的语法更深。
解决方法
正如Rici的评论中已经提到的:词法分析器尝试匹配尽可能多的字符,并且当2个或更多规则与相同字符匹配时,一个规则将首先定义“获胜”。因此,使用以下规则:
LABEL : [1-9] NUM* ;
CONSTANT : INT ;
INT : '~'? NUM ;
NUM : DIGIT+ ;
DIGIT : [0-9] ;
输入1
将始终成为LABEL
。并且像0
这样的输入将始终是CONSTANT
。仅当遇到INT
后跟一些数字时,才会创建~
令牌。 NUM
和DIGIT
将永远不会产生令牌,因为之前的规则将被匹配。 NUM
和DIGIT
永远不能自己成为令牌的事实,使它们成为fragment
tokens的候选者:
fragment NUM : DIGIT+ ;
fragment DIGIT : [0-9] ;
这样,您就不会在解析器规则中意外使用这些令牌。
此外,将~
用作令牌的一部分通常也不可行。您可能还希望~(1 + 2)
是一个有效的表达式。因此,通常最好在解析器规则:~
中使用像expression : '~' expression | ... ;
这样的一元运算符。
最后,如果您想区分非零整数值作为标签,可以这样做:
grammar SML_Small;
expression
: '(' expression ')'
| '~' expression
| integer
;
integer
: INT
| INT_NON_ZERO
;
label
: INT_NON_ZERO
;
INT_NON_ZERO : [1-9] DIGIT* ;
INT : DIGIT+ ;
SPACES : [ \t\r\n]+ -> skip ;
fragment DIGIT : [0-9] ;
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。