我正在尝试将 AST 与 ANTLR4 一起使用,并使用以下文件:
生成器.java
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.TokenStream;
public class Builder
{
public static void main(String[] args)
{
CharStream input = new ANTLRInputStream("ON M1==2 && M3 == 5 && (M2 > 1 || M5 <= 5.0) "
+ "DO P5:42 P4:10");
ExprLexer lexer = new ExprLexer(input);
TokenStream tokens = new CommonTokenStream(lexer);
ExprParser parser = new ExprParser(tokens);
parser.addParseListener(new ExprTestListener());
ExprParser.ExpressionContext uu = parser.expression();
}
}
Expr测试监听器:
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.tree.TerminalNode;
import org.antlr.v4.runtime.tree.ErrorNode;
public class ExprTestListener extends ExprBaseListener {
@Override public void enterExpression(ExprParser.ExpressionContext ctx)
{
System.out.println(ctx);
}
@Override public void exitExpression(ExprParser.ExpressionContext ctx)
{
System.out.println(ctx);
}
@Override public void enterActionexpr(ExprParser.ActionexprContext ctx)
{
System.out.println(ctx);
}
@Override public void exitActionexpr(ExprParser.ActionexprContext ctx)
{
System.out.println(ctx);
}
@Override public void enterCondexpr(ExprParser.CondexprContext ctx)
{
System.out.println(ctx);
}
@Override public void exitCondexpr(ExprParser.CondexprContext ctx)
{
System.out.println(ctx);
}
@Override public void enterCond(ExprParser.CondContext ctx)
{
System.out.println(ctx);
}
@Override public void exitCond(ExprParser.CondContext ctx)
{
System.out.println(ctx);
}
@Override public void enterEveryRule(ParserRuleContext ctx)
{
System.out.println(ctx);
}
@Override public void exitEveryRule(ParserRuleContext ctx)
{
System.out.println(ctx);
}
@Override public void visitTerminal(TerminalNode node)
{
}
@Override public void visitErrorNode(ErrorNode node)
{
}
}
Expr.g:
grammar Expr;
options
{
// antlr will generate java lexer and parser
language = Java;
}
WS : [ \t\r\n]+ -> skip ;
OP : '&&' | '||';
COMP : '==' | '<' | '>' | '<=' | '>=' | '!=';
fragment INT : [0-9]+;
REAL : INT '.' INT | INT;
ACTION : 'P' INT ':' INT;
MEASURE : 'M' INT;
// ***************** parser rules:
cond : MEASURE COMP REAL;
condexpr : '(' condexpr ')' | cond OP condexpr | cond;
actionexpr : ACTION actionexpr | ACTION;
expression : 'ON' condexpr 'DO' actionexpr;
我有这个输出:
[]
[]
[29]
[29]
[16 29]
[16 29]
[16 29]
[16 29]
[18 29]
[18 29]
[16 18 29]
[16 18 29]
[16 18 29]
[16 18 29]
[18 18 29]
[18 18 29]
[13 18 18 29]
[13 18 18 29]
[16 13 18 18 29]
[16 13 18 18 29]
[16 13 18 18 29]
[16 13 18 18 29]
[18 13 18 18 29]
[18 13 18 18 29]
[20 18 13 18 18 29]
[20 18 13 18 18 29]
[20 18 13 18 18 29]
[20 18 13 18 18 29]
[18 13 18 18 29]
[18 13 18 18 29]
[13 18 18 29]
[13 18 18 29]
[18 18 29]
[18 18 29]
[18 29]
[18 29]
[29]
[29]
[31]
[31]
[24 31]
[24 31]
[24 31]
[24 31]
[31]
[31]
[]
[]
我发现使用 ANTLR4 很难理解访客。
我有树目标:
- 获取 MEASURE 和 ACTION 的集合 INT(在两个不同的集合中)
- 替换一些 OP(例如 != 替换为 )
- 获取 condexpr (顶部项目)字符串并替换 OP(请参阅我的上一点)
首先我将解释一下您在上面观察到的内容:
首先也是最重要的,请阅读您调用的方法的文档。这Parser.addParseListener http://antlr.org/api/Java/org/antlr/v4/runtime/Parser.html#addParseListener%28org.antlr.v4.runtime.tree.ParseTreeListener%29文档包括以下注释:
这仅适用于高级用户。请将您的 ParseTreeListener 交给 ParseTreeWalker,而不是交给解析器!!!!
实施toString()
为了ParserRuleContext
类只是在创建上下文时打印规则调用堆栈。当侦听器进入规则时,您将打印一次,当侦听器退出时,您将打印一次。为了actionexpr
, cond
, and condexpr
您再次打印它,每个上下文总共会产生 4 个相同的输出行。
现在关于您的目标的一些注意事项:
- 代替
enterCond
and exitCond
, the MEASURE
可通过致电获取文本ctx.MEASURE().getText()
.
- 代替
enterActionexpr
and exitActionexpr
, the ACTION
可通过致电获取文本ctx.ACTION().getText()
.
- 您可以更改
COND
通过创建一个新的令牌TerminalNodeImpl
and CommonToken
获取更新后的令牌,并将其分配给字段中的正确索引CondContext.children
使用访问者或听众。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)