9

// Creare uno scanner che legge dallo stream di input passato a noi CSLexer lexer = nuovo CSLexer (nuovo ANTLRFileStream (f)); tokens.TokenSource = lexer;Compilare il proprio compilatore C# utilizzando ANTLR: Compilation Unit

// Create a parser that reads from the scanner 
CSParser parser = new CSParser(tokens); 

// start parsing at the compilationUnit rule 
CSParser.compilation_unit_return x = parser.compilation_unit(); 
object ast = x.Tree; 

Che cosa posso fare con la x che è di tipo compilation_unit_return, per estrarre la sua radice, le classi, i suoi metodi, ecc? Devo estrarre la sua scheda? Come lo faccio? Si noti che il compilation_unit_return è definito come tale nel mio CSParser (che viene generato automaticamente da ANTLR):

public class compilation_unit_return : ParserRuleReturnScope 
    { 
     private object tree; 
     override public object Tree 
     { 
      get { return tree; } 
      set { tree = (object) value; } 
     } 
    }; 

Tuttavia l'albero sto ottenendo è del tipo di oggetto. Corro usando il debugger e sembra vedere che è del tipo BaseTree. Ma BaseTree è un'interfaccia! Non so come si riferisce a BaseTree e non so come estrarre i dettagli da questo albero. Ho bisogno di scrivere un visitatore che visita la sua classe, metodo, variabili .... La classe ParserRuleReturn si estende da RuleReturnScope e ha un oggetto start e stop, che non so cosa sia ... Inoltre , c'è questa classe TreeVisitor fornita da ANTLR che sembra poco chiara. Richiede che un adapter passi come parametro al suo costruttore (se non userà il CommonTreeAdaptor predefinito), per questo ho chiesto ad abt come ottenere il paraorecchie dell'adapter. E anche altri problemi ... Per l'API, puoi fare riferimento a http://www.antlr.org/api/CSharp/annotated.html

Ora sono colpito qui ... Se sai qualcosa, aiutami. Grazie mille.

risposta

3

non ho mai lavorato con ANTLR da C#, ma seguendo il tuo link di API, BaseTree è chiaramente non è un'interfaccia - è un class, e ha proprietà pubbliche: Type per ottenere il tipo di nodo, Text per ottenere (Presumo) testo di origine corrispondente ad esso, e Children per ottenere i nodi figlio. Cos'altro hai bisogno di camminare?

+0

È una classe astratta ... classe astratta pubblica BaseTree: ITree – yeeen

+1

Ebbene sì, e perché dovrebbe fermarti? Hai il nodo radice dell'albero, che sai essere di un tipo che ha tutti i metodi necessari per recuperare i suoi figli (e quindi camminare l'albero a qualsiasi profondità). –

-2

Se dovessi fare un compilatore C# oggi, ecco quello che vorrei fare provare come un primo tentativo:

  1. Inizia con l'ANTLR C# 3 di destinazione (ovviamente io sono di parte qui - seriamente puoi usare il bersaglio CSharp2 o CSharp3).
  2. Ottieni Visual Studio 2010 con .NET Framework 4. La chiave qui è .NET 4 ed è dolce nuova espressione alberi.
  3. Creare un parser combinato di base. Metti la logica nel parser come assolutamente possibile. Dovrebbe avere poche azioni (se ce ne sono) e l'output dovrebbe essere un AST non decorato che può essere percorso con LL (1) walker.
  4. Costruisci una grammatica dell'albero per camminare sull'albero e identificare tutti i tipi dichiarati. Dovrebbe anche mantenere i sottoalberi member_declaration per un uso successivo.
  5. Costruisci un tree walker che cammina un singolo member_declaration e aggiunge il membro allo TypeBuilder. Tieni traccia dei corpi del metodo, ma non approfondiscili ancora.
  6. Costruisci un albero che cammina il corpo di un metodo. Genera un Expression<TDelegate> corrispondente al metodo e usa il metodo CompileToMethod mia API (vedi Pavel e i miei commenti) per generare il codice IL.

Se fai le cose in questo ordine, poi, quando si è finalmente l'analisi del espressioni (corpi dei metodi, inizializzatori campo), è possibile utilizzare i metodi string parametrizzati like this one nella classe Expression per salvare i membri di lavoro risolvere.

+0

Sfortunatamente, 'CompileToMethod' non può essere veramente usato in questo scenario a causa dei suoi limiti intrinseci - non c'è modo di compilare in un codice un altro metodo che stai generando a fianco, e il metodo di destinazione' MethodBuilder' deve essere per un metodo statico solo. Vedere https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=473128 per ulteriori dettagli. –

+0

Bello. Bene, allora inizierei con la costruzione di un compilatore 'Expression' che funziona in quei casi, e poi lo uso. :) Terrò il compilatore 'Expression' come un modulo indipendente in modo che possa essere usato con altri progetti (e forse lo farò comunque per divertimento). –

+0

Forse solo per deviare un po 'dal mio qn sopra: I hv il codice sorgente per antlr-3.1.3. N sotto la cartella di runtime, ci sono 2 cartelle - CSharp n CSharp3. Visto che hai citato CSharp3, sai perché ci sono 2 cartelle? Tuttavia l'API fornita online sembrava essere solo per CSharp CSharp3, anche la dll compilata. Se qualcuno vuole usare CSharp3, deve compilare i codici lì da solo? A me sembra che CSharp3 abbia caratteristiche più avanzate, ma non molto rilevanti nel mio contesto. – yeeen

6

È possibile impostare il tipo di albero AST nelle opzioni grammaticali nella parte superiore del file in questo modo:

tree grammar CSharpTree; 
options { 
    ASTLabelType = CommonTree 
} 

vorrei costruire un terzo di grammatica o di lavoro nella tua grammatica parser esistente che trasforma l'albero in classi che crei. Ad esempio, supponi di avere una regola che corrisponda all'operatore più e che sia 2 argomenti. È possibile definire una regola di corrispondenza che albero che crea una classe che hai scritto, chiamiamolo PlusExpression in questo modo:

plusExpr returns [PlusExpression value] 
    : ^(PLUS left=expr right=expr) { $value = new PlusExpression($left.value, $right.value); } 

expr sarebbe un altro regni nei vostri grammatica espressioni corrispondenti. sinistra e destra sono solo alias dati sui valori dell'albero. La parte tra {} è praticamente convertita in codice C#, ad eccezione della sostituzione dei riferimenti alle variabili. La proprietà .value off di $ left e $ right deriva dal valore restituito specificato dalle regole da cui sono stati creati.

Problemi correlati