如何通过Listener方法获取规则中的所有逻辑运算符Token?
解决ANTLR Listener提取逻辑运算符Token的问题
嘿,我来帮你搞定这个提取and/or运算符Token的问题!其实核心就是利用ANTLR的Listener机制,结合Parser上下文来获取这些关键字对应的Token,下面分步骤给你讲清楚:
第一步:确保Lexer正确定义关键字规则
首先得保证你的TransitionLexer里明确把and和or定义为独立的Token,而且要放在标识符(IDENTIFIER)规则的前面,避免被当成普通标识符匹配。比如:
lexer grammar TransitionLexer; // 先定义关键字,优先级更高 AND: 'and'; OR: 'or'; // 其他语法规则 EQUAL: '='; LPAREN: '('; RPAREN: ')'; BOOLEAN: 'true' | 'false'; IDENTIFIER: [a-zA-Z_][a-zA-Z0-9_]*; WS: [ \t\n\r]+ -> skip;
第二步:优化Parser规则(可选但推荐)
为了更方便在Listener里定位运算符,建议给Parser的表达式规则分支命名,这样Listener会自动生成对应的进入/退出方法。比如:
parser grammar TransitionParser; options { tokenVocab = TransitionLexer; } expr : expr AND expr #AndExpr | expr OR expr #OrExpr | LPAREN expr RPAREN #ParenExpr | IDENTIFIER EQUAL BOOLEAN #EqExpr;
第三步:通过Listener提取Token
接下来就可以编写自定义Listener,重写对应的方法来获取运算符Token了:
方法一:利用命名分支的Listener方法
如果上面给Parser规则分支命了名,ANTLR生成的Listener会包含enterAndExpr和enterOrExpr方法,直接在这些方法里获取Token即可:
public class OperatorExtractorListener extends TransitionParserBaseListener { @Override public void enterAndExpr(TransitionParser.AndExprContext ctx) { // 获取and对应的Token Token andToken = ctx.AND(); System.out.println("提取到运算符: " + andToken.getText()); } @Override public void enterOrExpr(TransitionParser.OrExprContext ctx) { // 获取or对应的Token Token orToken = ctx.OR(); System.out.println("提取到运算符: " + orToken.getText()); } }
方法二:遍历上下文获取Token(适用于未命名分支)
如果没给Parser规则分支命名,也可以在enterExpr方法里遍历上下文的Token,筛选出AND和OR类型的Token:
public class OperatorExtractorListener extends TransitionParserBaseListener { @Override public void enterExpr(TransitionParser.ExprContext ctx) { // 提取所有AND类型的Token for (Token token : ctx.getTokens(TransitionLexer.AND)) { System.out.println("提取到运算符: " + token.getText()); } // 提取所有OR类型的Token for (Token token : ctx.getTokens(TransitionLexer.OR)) { System.out.println("提取到运算符: " + token.getText()); } } }
最后:运行Listener的示例代码
你可以像下面这样使用这个Listener来解析输入并提取运算符:
public class Main { public static void main(String[] args) throws IOException { String input = "(states = failed) and (states1 = nominal) or (states2 = nominal)"; TransitionLexer lexer = new TransitionLexer(CharStreams.fromString(input)); CommonTokenStream tokens = new CommonTokenStream(lexer); TransitionParser parser = new TransitionParser(tokens); ParseTree tree = parser.expr(); ParseTreeWalker walker = new ParseTreeWalker(); walker.walk(new OperatorExtractorListener(), tree); } }
这样运行后,就能输出你想要的and和or啦!
内容的提问来源于stack exchange,提问作者lution
相关产品推荐
相关产品推荐

