Antlr &引用;跳过“;更改解析器行为
向规则中添加Antlr &引用;跳过“;更改解析器行为,antlr,antlr4,Antlr,Antlr4,向规则中添加skip并不能达到我的预期效果。下面是一个语法,表示由逗号和空格分隔的一对标记。我制作了一个逗号标记为skip的版本,还有一个没有: grammar Commas; COMMA: ', '; COMMASKIP: ', ' -> skip; DATA: ~[, \n]+; withoutSkip: data COMMA data '\n'; withSkip: data COMMASKIP data '\n'
skip
并不能达到我的预期效果。下面是一个语法,表示由逗号和空格分隔的一对标记。我制作了一个逗号标记为skip
的版本,还有一个没有:
grammar Commas;
COMMA: ', ';
COMMASKIP: ', ' -> skip;
DATA: ~[, \n]+;
withoutSkip: data COMMA data '\n';
withSkip: data COMMASKIP data '\n';
data: DATA;
在不跳过的情况下测试规则可以正常工作:
$ echo 'a, b' | grun Commas withoutSkip -tree
(withoutSkip (data a) , (data b) \n)
使用skip
时出现错误:
$ echo 'a, b' | grun Commas withSkip -tree
line 1:1 mismatched input ', ' expecting COMMASKIP
(withSkip (data a) , b \n)
如果我注释掉逗号
和而不注释skip
规则,我会得到以下结果:
$ echo 'a, b' | grun Commas withSkip -tree
line 1:3 missing ', ' at 'b'
(withSkip (data a) <missing ', '> (data b) \n)
我做错了什么?skip
导致lexer丢弃令牌。因此,skip
ped lexer规则不能在解析器规则中使用
另外,如果两个或多个规则匹配相同的输入,则首先定义的规则将从语法中稍后定义的规则中“赢”,无论解析器是否尝试匹配语法中稍后定义的规则,第一个规则都将始终“赢”。在您的情况下,将永远不会创建规则COMMASKIP
,因为COMMA
匹配相同的输入
试着这样做:
(withSkip (data a) (data b) \n)
grammar X;
COMMA : ',';
SPACE : (' '|'\n') -> skip;
DATA : ~[, \n]+;
data : DATA (COMMA DATA)*;
public class MyListener extends XBaseListener {
@Override
public void enterData(XParser.DataContext ctx) {
List dataList = ctx.DATA(); // not sure what type of list it returns...
// do something with `dataList`
}
}
语法逗号
COMMA : ',' -> skip;
SPACE : (' '|'\n') -> skip;
DATA : ~[, \n]+;
data : DATA+;
编辑
那么,在不将逗号包含在解析树中的情况下,如何指定逗号的位置呢?您的代码将与a、b匹配
不需要,因此如果逗号有效(即,a,b
)无效,则不能从lexer中跳过它
我认为在antlr3中应该使用感叹号
在Antlr4中,您不能从解析创建AST。在新版本中,所有终端/规则都位于一个解析树中。您可以使用自定义访问者和/或侦听器迭代此树。如何做到这一点的演示可以在以下问答中找到:
在您的情况下,语法如下所示:
(withSkip (data a) (data b) \n)
grammar X;
COMMA : ',';
SPACE : (' '|'\n') -> skip;
DATA : ~[, \n]+;
data : DATA (COMMA DATA)*;
public class MyListener extends XBaseListener {
@Override
public void enterData(XParser.DataContext ctx) {
List dataList = ctx.DATA(); // not sure what type of list it returns...
// do something with `dataList`
}
}
然后创建一个如下所示的侦听器:
(withSkip (data a) (data b) \n)
grammar X;
COMMA : ',';
SPACE : (' '|'\n') -> skip;
DATA : ~[, \n]+;
data : DATA (COMMA DATA)*;
public class MyListener extends XBaseListener {
@Override
public void enterData(XParser.DataContext ctx) {
List dataList = ctx.DATA(); // not sure what type of list it returns...
// do something with `dataList`
}
}
如您所见,逗号
没有被删除,但在enterData(…)
中,您只使用数据
标记。那么,如何指定逗号的位置而不将其包含在解析树中?您的代码将匹配a、b
。我认为在antlr3中应该使用感叹号。@DanLipsitt,检查我的编辑。