ANTLR:使用自定义类型而不是CommonTree生成树图

时间:2012-12-11 09:37:07

标签: c# antlr antlr3

我已经在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]
    : /* ??? */;

但我该如何为exprmultExpr创建BinaryExpr BinaryExprType

1 个答案:

答案 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.enew BinaryExpr(...)