我已经在ANTLR中为(a + b) * c
之类的非常简单的表达式定义了语法:
grammar SimpleCalc;
options {
language=CSharp2;
output=AST;
}
tokens {
PLUS = '+' ;
MINUS = '-' ;
MULT = '*' ;
DIV = '/' ;
}
/*------------------------------------------------------------------
* LEXER RULES
*------------------------------------------------------------------*/
ID : ('a'..'z' | 'A' .. 'Z' | '0' .. '9')+ ;
WHITESPACE : ( '\t' | ' ' | '\r' | '\n'| '\u000C' )+ { Skip(); } ;
/*------------------------------------------------------------------
* PARSER RULES
*------------------------------------------------------------------*/
expr : multExpr ((PLUS | MINUS)^ multExpr)*;
multExpr : atom ((MULT | DIV)^ atom )*;
atom : ID
| '(' expr ')' -> expr;
现在我有一些用于创建树结构的预定义类型:
public class Expr { }
public class SimpleExpr : Expr
{
public SimpleExpr(string name) { ... }
}
public enum BinaryExprType
{
Plus,
Minus,
Multiply,
Divide
}
public class BinaryExpr : Expr
{
public BinaryExpr(Expr left, BinaryExprType op, Expr right) { ... }
}
我知道我们可以编写一些代码来将CommonTree
转换为Expr
树,但我想直接重写为自定义类型,如:
atom returns [Expr e]
: ID { $e = new SimpleExpr($ID.text); }
| '(' expr ')' { $e = $expr.e; };
expr returns [Expr e]
: /* ??? */;
multExpr returns [Expr e]
: /* ??? */;
但我该如何为expr
和multExpr
创建BinaryExpr
BinaryExprType
?
答案 0 :(得分:1)
尝试这样的事情(未经测试!):
expr returns [Expr e]
: m1=multExpr {$e = $m1.e;}
( PLUS m2=multExpr {$e = new BinaryExpr($expr.e, BinaryExprType.Plus, $m2.e);}
| MINUS m2=multExpr {$e = new BinaryExpr($expr.e, BinaryExprType.Minus, $m2.e);}
)*
;
multExpr returns [Expr e]
: a1=atom {$e = $a1.e;}
( MULT a2=atom {$e = new BinaryExpr($multExpr.e, BinaryExprType.Multiply, $a2.e);}
| DIV a2=atom {$e = new BinaryExpr($multExpr.e, BinaryExprType.Divide, $a2.e);}
)*
;
atom returns [Expr e]
: ID {$e = new SimpleExpr($ID.text);}
| '(' expr ')' {$e = $expr.e;}
;
诀窍是在二进制表达式中递归使用规则本身:$expr.e
中的$multExpr.e
和new BinaryExpr(...)
。