好的,让我们建立一个简单的数学示例。 对于这样的任务,构建AST完全是矫kill过正,但这是展示原理的好方法。
我将使用C#进行操作,但Java版本将非常相似。
语法
首先,让我们编写一个非常基本的数学语法来使用:
grammar Math;
compileUnit
: expr EOF
;
expr
: '(' expr ')' # parensExpr
| op=('+'|'-') expr # unaryExpr
| left=expr op=('*'|'/') right=expr # infixExpr
| left=expr op=('+'|'-') right=expr # infixExpr
| func=ID '(' expr ')' # funcExpr
| value=NUM # numberExpr
;
OP_ADD: '+';
OP_SUB: '-';
OP_MUL: '*';
OP_DIV: '/';
NUM : [0-9]+ ('.' [0-9]+)? ([eE] [+-]? [0-9]+)?;
ID : [a-zA-Z]+;
WS : [ \t\r\n] -> channel(HIDDEN);
很基本的东西,我们有一个处理所有内容的dynamic规则(优先级规则等)。
AST节点
然后,让我们定义一些我们将使用的AST节点。 这些都是完全自定义的,您可以按照自己的方式定义它们。
这是我们用于此示例的节点:
internal abstract class ExpressionNode
{
}
internal abstract class InfixExpressionNode : ExpressionNode
{
public ExpressionNode Left { get; set; }
public ExpressionNode Right { get; set; }
}
internal class AdditionNode : InfixExpressionNode
{
}
internal class SubtractionNode : InfixExpressionNode
{
}
internal class MultiplicationNode : InfixExpressionNode
{
}
internal class DivisionNode : InfixExp