2013-12-12 34 views
5

Antlr 4とStringTemplate 4を使用してPL/SQLコードをJavaに変換できるトランスレータを構築しようとしています。PL/SQlの文法を持ち、 PL/SQL用のパーサをすでに作成していますが、問題にさらに近づける方法はわかりません。 antlrとstringtemplateを使って多くの言語翻訳記事を見つけましたが、すべてANTLR 3またはANTLR 2を使用しています。 Antlr 4を使用してPL/SQLのパーサとしてAntlr 4を使用すると、Antlr 4を使用して翻訳する際に違いがあります。Antlr 4とstringtemplate 4を使用したPL/SQLコードのJavaへの変換

問題にアプローチするより良い方法。

+0

antlr2/3では動作しますがantlr4では動作しない文法/テンプレートスニペットなどの例を挙げてください。 porcelliパーサーを使用していますか、独自に作成しましたか? –

+0

ANTLR3とANTLR 4 'の文法の主な違いは、構文述語の削除です:http://stackoverflow.com/questions/18431158/syntactic-predicates-upgrading-from-antlr-3-to-antlr-4 いいえ、私自身のパーサを書きました。Ref:https://github.com/developeron29/Antlr-4-PLSQL-Parser---AST-Generator/ –

+0

v4と互換性のある既存の文法ファイルを使用しましたか?可能であれば、リンクを共有することができます –

答えて

10

v4より前のANTLRは、StringTemplateの本来のサポートを持っていました(文法の出力をSTと指定できます)。 v4以降、このサポートは中止されたようです。

リスナーインターフェイスまたはビジターインターフェイスを使用して手動でテンプレートを構築することもできます。訪問者は、この文脈においてより有用である可能性が高い。

私が現在調査しているもう1つのオプションは、ParseTree(解析結果)をパラメータとしてテンプレートに割り当てることです。 ParserRuleContextのカスタムModelAdapterを使用するので、テンプレートからサブコンテキストにアクセスできます。

例: 私はPL/SQLの文法を使用していると仮定しています。今、あなた

@Override 
public Object getProperty(Interpreter interpreter, ST seld, Object o, Object property, String propertyName) throws STNoSuchPropertyException 
{ 
    Method m = null; 
    try { 
     String mn = "get" + Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1); 
     m = o.getClass().getMethod(mn); 
    } catch (Exception e) { 
    } 
    if (m == null) 
     try { 
      m = o.getClass().getDeclaredMethod(propertyName); 
     } catch (Exception e) { 
     } 

    if (m != null) try { 
     return m.invoke(o); 
    } catch (Exception e) { 
     throw new STNoSuchPropertyException(e, property, propertyName); 
    } 
    else 
     throw new STNoSuchPropertyException(null, property, propertyName); 
} 

plsql_block(block) ::= <<{ 
    <declarations(block.declare_section)> 
    <body(block.body)> 
}>> 

declarations(ds)  ::= "<ds.item_declaration:itemDecl()>" 
itemDecl(id)   ::= "<id.variable_declaration:varDecl()>" 
varDecl(vd)   ::= "<vd.datatype.text> <vd.ID>;" 

body(b)    ::= "<b.text>" 

あなたはまたParserRuleContextためModelAdapterを(これはこれで唯一の方法のほんの一例である)必要があるでしょう:次に、あなたのようなテンプレートグループを持つことができます次の操作を行うことができます:

ANTLRInputStream input = new ANTLRInputStream(new FileInputStream("block_test.sql")); 
PLSQLLexer lexer = new PLSQLLexer(input); 
CommonTokenStream tokens = new CommonTokenStream(lexer); 
PLSQLParser parser = new PLSQLParser(tokens); 
parser.setBuildParseTree(true); 
ParseTree tree = parser.plsql_block(); 

STGroupFile stg = new STGroupFile("test.stg"); 
stg.registerModelAdaptor(ParserRuleContext.class, new ContextModelAdapter()); 
ST t = stg.getInstanceOf("plsql_block"); 
t.add("block", tree); 
System.out.println(t.render()); 

+0

リスナまたは訪問者インターフェイスを使用する例、またはParseTree ? –

+0

ありがとう!あなたは素晴らしいです! –

+1

どのような素晴らしい答え!十分にupvoteできません。私は自分の仕事のためにリスナーの使用をやめ、これに切り替えました。とにかく、リスナーのメソッドがSTに代わってプロキシとして終わったことに気付きました。このアプローチについてあなたが提供できるその他のヒントMarin?再度、感謝します。 – Core