Antlr用 Visitor 模式实现对 AST 的访问
2020-08-04 14:02:18 0 举报
Anltr用访问者模式实现对语法树的访问
作者其他创作
大纲/内容
RuleContext
+ attribute1:type = defaultValue+ attribute2:type- attribute3:type
+ operation1(params):returnType- operation2(params)- operation3()
ParseTree
ASTEvaluator.visitLiteral(LiteralContext)
1
ASTEvaluator
+ visitAdditiveExpression(AdditiveExpressionContext ctx):Integer+ visitMultiplicativeExpression(MultiplicativeExpressionContext ctx):Integer+ visitPrimaryExpression(PrimaryExpressionContext ctx):Integer+ visitLiteral(LiteralContext ctx) :Integer
abstract class Parser
8
@Override public T visit(ParseTree tree) { return tree.accept(this); }
tree.accept(ASTEvaluator )
RuleNode
7
SyntaxTree
PlayScriptVisitor<T>visitLiteral(PlayScriptParser.LiteralContext ctx):TvisitPrimitiveType(PlayScriptParser.PrimitiveTypeContext ctx):TvisitStatement(PlayScriptParser.StatementContext ctx):TvisitExpressionStatement(PlayScriptParser.ExpressionStatementContext ctx):TvisitDeclaration(PlayScriptParser.DeclarationContext ctx):TvisitInitializer(PlayScriptParser.InitializerContext ctx):TvisitAdditiveExpression(PlayScriptParser.AdditiveExpressionContext ctx):TvisitMultiplicativeExpression(PlayScriptParser.MultiplicativeExpressionContext ctx):TvisitExpression(PlayScriptParser.ExpressionContext ctx):T
extends
TerminalNode
4
@Overridepublic <T> T accept(ParseTreeVisitor<? extends T> visitor) { if (visitor instanceof PlayScriptVisitor) return ((PlayScriptVisitor<? extends T>) visitor).visitExpression(this); else return visitor.visitChildren(this);}
PlayScriptParser
implements
ASTEvaluator.visitExpression(ExpressionContext)
ParserRuleContext
2
@Overridepublic T visitExpression(PlayScriptParser.ExpressionContext ctx) { return visitChildren(ctx);}
PlayScriptParser parser = new PlayScriptParser(tokens);ParseTree tree = parser.expression();//解释执行ASTEvaluator visitor = new ASTEvaluator();Integer result = visitor.visit(tree);
Inner LiteralContext
+ accept(ParseTreeVisitor<? extends T> visitor):T
Inner ExpressionContext
extends PlayScriptBaseVisitor
5
6
我们在纯手工编写的脚本语言解释器里,用了一个 evaluate() 方法自上而下地遍历了整棵树。随着要处理的语法越来越多,这个方法的代码量会越来越大,不便于维护。而 Visitor 设计模式针对每一种 AST 节点,都会有一个单独的方法来负责处理,能够让代码更清晰,也更便于维护。
abstract class AbstractParseTreeVisitor<T>
+ visit(ParseTree tree):T+ visitChildren(RuleNode node):T+ visitTerminal(TerminalNode node):T+ visitErrorNode(ErrorNode node):T
ParseTreeVisitor<T>visit(ParseTree tree):TvisitChildren(RuleNode node):TvisitTerminal(TerminalNode node):TvisitErrorNode(ErrorNode node):T
@Overridepublic <T> T accept(ParseTreeVisitor<? extends T> visitor) { if (visitor instanceof PlayScriptVisitor) return ((PlayScriptVisitor<? extends T>) visitor).visitLiteral(this); else return visitor.visitChildren(this);}
@Overridepublic Integer visitLiteral(LiteralContext ctx) { if (ctx.IntegerLiteral() !=null){ return Integer.valueOf(ctx.IntegerLiteral().getText()); } return 0;}
ExpressionContext.accept(ASTEvaluator ){ ((PlayScriptVisitor<? extends T>) visitor).visitExpression(this)}
3
9
PlayScriptBaseVisitor<T>
+ visitLiteral(PlayScriptParser.LiteralContext ctx):T+ visitPrimitiveType(PlayScriptParser.PrimitiveTypeContext ctx):T+ visitStatement(PlayScriptParser.StatementContext ctx):T+ visitExpressionStatement(PlayScriptParser.ExpressionStatementContext ctx):T+ visitDeclaration(PlayScriptParser.DeclarationContext ctx):T+ visitAdditiveExpression(PlayScriptParser.AdditiveExpressionContext ctx):T+ visitMultiplicativeExpression(PlayScriptParser.MultiplicativeExpressionContext ctx):T+ visitExpression(PlayScriptParser.ExpressionContext ctx):T...
0 条评论
下一页