1

次のような非常に単純な式の文法定義は、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て作成するにはどうすればよいですか?BinaryExprBinaryExprType

4

1 に答える 1

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.ein new BinaryExpr(...).

于 2012-12-11T09:56:42.180 に答える