3

LANG1 と LANG2 の 2 つの言語間のコンピューター言語翻訳プログラムを作成したいと考えています。具体的には、LANG1で書かれたコードをLANG2のソースコードに翻訳したいです。

LANG1 と LANG2 の両方に BNF Grammar があります。

LANG1 は私が自分で書いた小さな DSL であり、本質的には LANG2 の「より簡単な」バージョンです。

LANG1で書かれた入力文から、LANG2で文を生成できるようにしたいです。

LANG1 用のコンパイラーをコンパイル中ですが、次に何をすればよいかわかりません (LANG1 ステートメントを LANG2 ステートメントに変換するため)。

関連する手順についての私の理解は次のとおりです。

1. BNF for my DSL (LANG1)                                  DONE
2. Reverse engineered the BNF for LANG2                    DONE
3. Learning how to generate a compiler for LANG1           TODO
4. Translate LANG1 statements to LANG2 statements          ???

LANG1 ステートメントから LANG2 ステートメントを生成するために必要な手順は何ですか?

私のコード ベースは C++ であるため、C または C++ で生成されたパーサーを使用できます。

PS: ANTLR3 を使用して、LANG1 のコンパイラを生成します。

4

1 に答える 1

4

最も一般的なケースでは、文法の可能な各セクションをLANG1からLANG2に適したものに変換する必要があります。または、アセンブリやコンビネータなど、両方の言語の可能な限り単純なプリミティブにダムダウンする必要があります。これは少し時間がかかり、あまり楽しくありません。

ただし、文法が同等であるか、多くの共通点を共有している場合は、両方の文法について同じツリーを解析し、標準化されたツリーを取得してLANG1またはLANG2ソース(これは一般的なケースとほとんど同じですが、より多くのショートカットが必要です)。

編集:私はあなたの質問を読み直したところ、あなたは一方向にしか翻訳したくないことに気づいたので、ツリーの形をLANG1に適合させ、LANG2の翻訳機能を持たせることだけを心配する必要があります。しかし、私の例がとにかく役立つことを願っています。

ツリー構築の例:

同じ非常に単純なASTを生成する2つの異なるANTLR文法を次に示します。

文法1

1つ目は、加算を表現する標準的な方法です。

grammar simpleAdd;

options {output=AST;}

tokens {
    PLUS = '+';
}

expression : addition EOF!;
addition   : NUMBER (PLUS NUMBER)+ -> ^(PLUS NUMBER*);

NUMBER     :'0'..'9'+;
WHITESPACE : ( '\t' | ' ' | '\r' | '\n')+    { $channel = HIDDEN; } ;

これにより、2つ以上の整数が受け入れられ、PLUSノードとリスト内のすべての数値が一緒に追加されるツリーが生成されます。例えば、

1 + 1 + 2 + 3 + 5

文法2

2番目の文法は、あまりエレガントではありません。

grammar horribleAdd;

options {output=AST;}

tokens {
    PLUS = '+';
    PLUS_FUNC = 'plus';
    COMMA = ',';
    LEFT_PARENS ='(';
    RIGHT_PARENS=')';
} 

expression : addition EOF!;
addition   : PLUS_FUNC LEFT_PARENS NUMBER (COMMA NUMBER)+ RIGHT_PARENS -> ^(PLUS NUMBER*);

NUMBER     :'0'..'9'+;
WHITESPACE : ( '\t' | ' ' | '\r' | '\n')+    { $channel = HIDDEN; } ;

この文法は、関数に与えられた数値を想定しています(はい、関数が実際にはこのように機能しないことはわかっています。例をできるだけ明確に保つようにしています)。例えば、

plus(1, 1, 2, 3, 5)

最初の文法とまったく同じツリー(子として数字を持つPLUSノード)を生成します。

これで、指示がどの言語からのものであるかを心配する必要がなくなり、好きな形式で出力できます。あなたがする必要があるのは、このASTをあなたの選んだ言語に戻すことができる関数を書くことです。

于 2012-12-29T11:26:39.500 に答える