2

C#を使用してPLC言語インタープリターを作成しています。私のインタープリターには、要素型(整数、ブール、..)と派生型(構造体、配列など)という独自の型階層があります。ANTLR文法から多次元配列を作成するときに問題が発生します。

これは私の言語が多次元配列(3x2 int配列)を宣言する方法です:

TYPE 
    MY_ARRAY : ARRAY [0..2, 1..2] OF INT; 
END_TYPE

一次元配列宣言を解析するための私のantlr文法は次のとおりです。

decl_derivated
    : 'TYPE' NEWLINE* ID ':' NEWLINE* type_decl ';' NEWLINE* 'END_TYPE' NEWLINE* -> ^(TYPEDEF<TypeDefinition>[$ID.text, $type_decl.type])
    ;

type_decl returns [Type type]
    : 'STRUCT' NEWLINE* decl_fields 'END_STRUCT' { $type = new STRUCT($decl_fields.fieldList); }
    | 'ARRAY' '[' range ']' 'OF' type_var { $type = new ARRAY($type_var.type, $range.init, $range.end); }   
    ;

range returns [int init, int end]
    : ini=CTE_INT '..' en=CTE_INT { $init = int.Parse($ini.text); $end = int.Parse($en.text); }
    ;

type_var returns [Type type]
    : 'BOOL'  { $type = new BOOL(); }
    | 'INT'   { $type = new INT(); }
    | 'REAL'  { $type = new REAL(); }
    ;

/* lexer */

ID  :   (LETTER | '_') (LETTER | DIGIT | '_')*
    ;

fragment
DIGIT : '0'..'9'
      ;

fragment
INTEGER : DIGIT ('_'|DIGIT)*
    ;

fragment
EXPONENT : ('e'|'E') ('+'|'-')? INTEGER ;

fragment
CTE_INT
    : ('+'|'-'| ) INTEGER
    ;

fragment
CTE_REAL
    : ('+'|'-'| /*vacio*/ ) INTEGER '.' INTEGER EXPONENT?
    ;

RANGE   : '..' ;

RANGE_OR_INT 
    : ( CTE_INT RANGE ) => CTE_INT  { $type=CTE_INT; }
        | ( CTE_REAL )  => CTE_REAL     { $type=CTE_REAL; }
        | CTE_INT                   { $type=CTE_INT; }
    ;

NEWLINE : '\r'? '\n'
    | '\r'
    ;

多次元配列をパーサーして、配列宣言の文法を次のように変更しても問題ありません。

type_decl returns [Type type]
        : 'ARRAY' '[' range (',' range)* ']' 'OF' type_var

この多次元配列のコンストラクターを作成する方法がわかりません。誰でも私を助けることができますか?ありがとうございました。

4

1 に答える 1

1

解決

最後に、私はより優れた、よりエレガントなソリューションを実現しました。ARRAYデータ型クラスに2つの新しいメソッドを追加しました。1つは新しいディメンションを追加するためのもので、もう1つは基本型を設定するためのものです。

public class ARRAY : ANY_DERIVED
    {
        public Type de; // ARRAY type
        public int size;
        public int initIndex;
        public int finalIndex;

    public ARRAY(int initIndex, int finalIndex)
    {   
        this.initIndex = initIndex;
        this.finalIndex = finalIndex;
        size = finalIndex - initIndex + 1;
    }

    public void NewDim(int initIndex, int finalIndex)
    {
        if (de == null)
            de = new ARRAY(initIndex, finalIndex);
        else
            ((ARRAY)de).NewDim(initIndex, finalIndex);
    }

    public void SetBaseType(Type t)
    {
        if (de == null)
            de = t;
        else
            ((ARRAY)de).SetBaseType(t);
    }
   }

ANTLR文法:

decl_type returns [Type type]
    : 'ARRAY' '[' r1=range {$type = new ARRAY($r1.init, $r1.end);} (',' r2=range {((ARRAY)$type).NewDim($r2.init, $r2.end);})* ']' 'OF' type_var { ((ARRAY)$type).SetBaseType($type_var.type); }    
    ;

とにかく、お時間をいただきありがとうございます;)

于 2012-04-05T08:05:22.247 に答える