首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >正整数文字上SML卡顿的ANTLR4语法

正整数文字上SML卡顿的ANTLR4语法
EN

Stack Overflow用户
提问于 2020-08-25 07:32:58
回答 1查看 60关注 0票数 0

我正在使用ANTLR 4.8为SML构建一个解析器,由于某种原因,生成的解析器会因为整型字面值而卡住:

代码语言:javascript
复制
# 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 ):

代码语言:javascript
复制
grammar SML_Small;

Whitespace : [ \t\r\n]+ -> skip ;

expression : CONSTANT ;

LABEL : [1-9] NUM* ;

CONSTANT : INT ;
INT : '~'? NUM ;
NUM : DIGIT+ ;
DIGIT : [0-9] ;

另一方面,删除LABEL会使正数再次工作:

代码语言:javascript
复制
grammar SML_Small;

Whitespace : [ \t\r\n]+ -> skip ;

expression : CONSTANT ;

CONSTANT : INT ;
INT : '~'? NUM ;
NUM : DIGIT+ ;
DIGIT : [0-9] ;

我曾尝试用DIGIT?和类似的变体替换NUM*,但这并没有解决我的问题。

我真的不确定发生了什么,所以我怀疑这是比我使用的语法更深层次的东西。

EN

回答 1

Stack Overflow用户

发布于 2020-08-25 15:27:53

正如Rici在评论中提到的: lexer尝试匹配尽可能多的字符,当2个或更多规则匹配相同的字符时,首先定义的规则“获胜”。因此,有了这样的规则:

代码语言:javascript
复制
LABEL    : [1-9] NUM* ;
CONSTANT : INT ;
INT      : '~'? NUM ;
NUM      : DIGIT+ ;
DIGIT    : [0-9] ;

输入1将始终成为LABEL。而像0这样的输入永远是一个CONSTANT。仅当遇到后跟某些数字的~时,才会创建INT令牌。NUMDIGIT永远不会生成令牌,因为它之前的规则将是匹配的。NUMDIGIT本身永远不能成为令牌,这一事实使它们成为fragment tokens的候选对象

代码语言:javascript
复制
fragment NUM   : DIGIT+ ;
fragment DIGIT : [0-9] ;

这样,您就不会意外地在解析器规则中使用这些标记。

此外,让~成为令牌的一部分通常不是可行的方法。您可能还希望~(1 + 2)是一个有效的表达式。因此,在解析器规则expression : '~' expression | ... ;中通常更好地使用像~这样的一元运算符。

最后,如果你想区分一个非零整数值作为标签,你可以这样做:

代码语言:javascript
复制
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] ;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63570019

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档