2013-12-12 9 views
5

Ich versuche einen Übersetzer zu konstruieren, der PL/SQL-Code mit Antlr 4 und StringTemplate 4 in Java konvertieren kann. Ich habe die Grammatik von PL/SQl und habe baue bereits einen Parser für PL/SQL, aber ich habe keine Ahnung, wie ich das Problem weiter angehen soll. Ich fand viele Artikel der Sprachübersetzung mit Antlr und StringTemplate, aber sie alle verwenden ANTLR 3 oder ANTLR 2. Also gibt es einen Unterschied, wenn ich Antlr 4 zusammen mit Stringtemplate verwende, da der Parser für PL/SQL mit Antlr 4 einige Unterschiede hatte besserer Weg, um das Problem anzugehen.Übersetzung von PL/SQL-Code nach Java mit Antlr 4 und StringTemplate 4

+0

Können Sie ein Beispiel angeben, zum Beispiel ein Grammatik-/Template-Snippet, das mit antlr2/3 funktioniert, aber nicht mit antlr4? Verwenden Sie den Porzelli-Parser oder haben Sie Ihren eigenen geschrieben? –

+0

Der Hauptunterschied zwischen ANTLR3 und ANTLR 4 'Grammatik ist Entfernung von syntaktischen Prädikaten Siehe: http://stackoverflow.com/questions/18431158/syntactic-predicates-upgrading-from-antlr-3-to-antlr-4. Nein, ich habe meinen eigenen Parser geschrieben, Ref: https://github.com/developeron29/Antlr-4-PLSQL-Parser---AST-Generator/ –

+0

Haben Sie eine vorhandene Grammatikdatei verwendet, die mit v4 kompatibel ist? Wenn ja, können Sie den Link teilen –

Antwort

10

ANTLR vor v4 hatte intrinsische Unterstützung für StringTemplate (Sie könnten angeben, dass Ihre Grammatikausgabe ST ist). Ab Version 4 scheint diese Unterstützung entfallen zu sein.

Eine Option besteht darin, Listener- oder Besucherschnittstellen zu verwenden, um Ihre Vorlagen manuell zu erstellen. Der Besucher ist in diesem Zusammenhang wahrscheinlich nützlicher.

Die andere Option, die ich derzeit untersuche, ist die Zuweisung von ParseTree (Ergebnis der Analyse) als Parameter für die Vorlage. Ich benutze Custom ModelAdapter für ParserRuleContext, damit ich aus den Vorlagen auf Unterkontexte zugreifen kann.

Beispiel: Ich nehme an, Sie verwenden Grammatik für PL/SQL. Dann könnten Sie eine Vorlagengruppe wie haben:

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>" 

Sie müssen auch ModelAdapter für ParserRuleContext (dies ist nur ein Beispiel für die einzige Methode darin):

@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); 
} 

Jetzt Sie kann folgendes tun:

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()); 

Hoffe das hilft!

+0

Können Sie bitte ein Beispiel für die Verwendung von Listener oder Besucher-Schnittstelle oder mit ParseTree verwenden ? –

+0

Danke! Du bist toll! –

+1

Was für eine tolle Antwort! Kann nicht genug aufladen. Ich habe aufgehört, einen Listener für meine Aufgabe zu verwenden, und ich bin dazu gewechselt. Mir ist aufgefallen, dass die Listener-Methoden sowieso zu Proxies für ST gehörten. Irgendwelche anderen Tipps, die Sie über diesen Ansatz geben können Marin? Danke noch einmal. – Core