我有一个Lexer规则如下:
PREFIX : [abcd]'_';
EXTRA : ('xyz' | 'XYZ' );
SUFFIX : [ab];
TCHAN : PREFIX EXTRA? DIGIT+ SUFFIX?;
和解析器规则:
tpin : TCHAN
;
在exit_tpin()Listiner方法中,是否有一种语法可以提取令牌的DIGIT组件?现在我可以得到ctx.TCHAN()元素,但这是一个字符串。我只想要TCHAN的数字部分。
或者我应该删除TCHAN作为TOKEN并将该规则移至tpin(即)
tpin : PREFIX EXTRA? DIGIT+ SUFFIX?
我知道如何从听众中提取DIGIT。
我的猜测是,当TOKEN被呈现给解析器时,解构它已经太晚了......但我想知道是否有一些ANTLR专家知道一种技术。
如果我重写我的TOKENIZER,那么INT / ID令牌可能会错过TCHAN令牌(我想这就是为什么我最终解析了)。
我总是可以在监听器方法中做一些正则表达式的工作......但这看起来很糟糕......因为我之前有各个组件。我只是懒惰,并且想知道除了重构解析语法之外是否还有其他技术。
答案 0 :(得分:1)
在The Definitive ANTLR Reference中,您可以找到复杂词法分析器的示例,其中大部分工作已完成。但是在学习ANTLR时,我建议将词法分析器主要用于将输入流的分裂函数转换为小标记。然后在解析器中做大工作。在目前的情况下,我会这样做:
grammar Question;
/* extract digit */
question
: tpin EOF
;
tpin
// : PREFIX EXTRA? DIGIT+ SUFFIX?
// {System.out.println("The only useful information is " + $DIGIT.text);}
: PREFIX EXTRA? number SUFFIX?
{System.out.println("The only useful information is " + $number.text);}
;
number
: DIGIT+
;
PREFIX : [abcd]'_';
EXTRA : ('xyz' | 'XYZ' );
DIGIT : [0-9] ;
SUFFIX : [ab];
WS : [ \t\r\n]+ -> skip ;
输入为d_xyz123456b
。随着第一个版本
: PREFIX EXTRA? DIGIT+ SUFFIX?
你得到了
$ grun Question question -tokens data.txt
[@0,0:1='d_',<PREFIX>,1:0]
[@1,2:4='xyz',<EXTRA>,1:2]
[@2,5:5='1',<DIGIT>,1:5]
[@3,6:6='2',<DIGIT>,1:6]
[@4,7:7='3',<DIGIT>,1:7]
[@5,8:8='4',<DIGIT>,1:8]
[@6,9:9='5',<DIGIT>,1:9]
[@7,10:10='6',<DIGIT>,1:10]
[@8,11:11='b',<SUFFIX>,1:11]
[@9,13:12='<EOF>',<EOF>,2:0]
The only useful information is 6
因为DIGIT+
的解析转换为重用DIGIT的循环
setState(12);
_errHandler.sync(this);
_la = _input.LA(1);
do {
{
{
setState(11);
((TpinContext)_localctx).DIGIT = match(DIGIT);
}
}
setState(14);
_errHandler.sync(this);
_la = _input.LA(1);
} while ( _la==DIGIT );
和$DIGIT.text
转换为((TpinContext)_localctx).DIGIT.getText()
,只保留最后一位数字。这就是我定义一个子规则number
: PREFIX EXTRA? number SUFFIX?
可以轻松捕获值:
[@0,0:1='d_',<PREFIX>,1:0]
[@1,2:4='xyz',<EXTRA>,1:2]
[@2,5:5='1',<DIGIT>,1:5]
[@3,6:6='2',<DIGIT>,1:6]
[@4,7:7='3',<DIGIT>,1:7]
[@5,8:8='4',<DIGIT>,1:8]
[@6,9:9='5',<DIGIT>,1:9]
[@7,10:10='6',<DIGIT>,1:10]
[@8,11:11='b',<SUFFIX>,1:11]
[@9,13:12='<EOF>',<EOF>,2:0]
The only useful information is 123456
你甚至可以简化:
tpin
: PREFIX EXTRA? INT SUFFIX?
{System.out.println("The only useful information is " + $INT.text);}
;
PREFIX : [abcd]'_';
EXTRA : ('xyz' | 'XYZ' );
INT : [0-9]+ ;
SUFFIX : [ab];
WS : [ \t\r\n]+ -> skip ;
$ grun Question question -tokens data.txt
[@0,0:1='d_',<PREFIX>,1:0]
[@1,2:4='xyz',<EXTRA>,1:2]
[@2,5:10='123456',<INT>,1:5]
[@3,11:11='b',<SUFFIX>,1:11]
[@4,13:12='<EOF>',<EOF>,2:0]
The only useful information is 123456
在侦听器中,您可以通过规则上下文TpinContext
直接访问这些值:
public static class TpinContext extends ParserRuleContext {
public Token INT;
public TerminalNode PREFIX() { return getToken(QuestionParser.PREFIX, 0); }
public TerminalNode INT() { return getToken(QuestionParser.INT, 0); }
public TerminalNode EXTRA() { return getToken(QuestionParser.EXTRA, 0); }
public TerminalNode SUFFIX() { return getToken(QuestionParser.SUFFIX, 0); }