Question

// Create a scanner that reads from the input stream passed to us
 CSLexer lexer = new CSLexer(new ANTLRFileStream(f));
tokens.TokenSource = lexer;

// 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;

Que puis-je faire avec le x qui est de type compilation_unit_return, pour extraire la racine, ses classes, ses méthodes, etc? Dois-je extraire son adaptateur sur? Comment je fais ça? Notez que le compilation_unit_return est défini en tant que tel dans mon CSParser (qui est généré automatiquement par ANTLR):

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

Cependant, l'arbre que je reçois est de l'objet de type. J'exécution à l'aide du débogueur et semblait voir qu'il est de BaseTree de type. Mais BaseTree est une interface! Je ne sais pas comment il se rapporte à BaseTree et ne savent pas comment extraire les détails à partir de cet arbre.

Je dois écrire un visiteur qui a visite à sa classe, la méthode, les variables, etc. La classe ParserRuleReturn va de RuleReturnScope et a un début et d'arrêt objet, que je ne sais pas ce qu'elle est.

De plus, il y a cette classe TreeVisitor fournie par ANTLR qui semble prêter à confusion. Il nécessite un adaptateur à passer comme paramètre à son constructeur (sinon il utilisera le CommonTreeAdaptor par défaut), tt est pourquoi j'ai demandé au sujet de la façon d'obtenir l'adaptateur sur eariler. Et d'autres questions aussi. Pour l'API, vous pouvez consulter http://www.antlr.org/api/ CSharp / annotated.html

Était-ce utile?

La solution

Je n'ai jamais travaillé avec ANTLR de C #, mais après votre lien vers API, BaseTree est manifestement pas une interface - c'est un

Autres conseils

Vous pouvez définir le type d'arbre AST dans les options de grammaire en haut du fichier comme ceci:

tree grammar CSharpTree;
options { 
    ASTLabelType = CommonTree
}

Je construirais une 3ème grammaire ou de travailler dans votre grammaire de l'analyseur existant qui transforme l'arbre en classes que vous créez. Par exemple supposons que vous avez une règle qui correspond à l'opérateur plus et il est 2 arguments. Vous pouvez définir une règle correspondant à cet arbre qui crée une classe que vous avez écrit, nous allons l'appeler PlusExpression comme ceci:

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

expr serait une autre règle dans vos expressions de correspondance de grammaire. gauche et à droite sont des alias vient de donner aux valeurs d'arbres. La partie entre les {} s 'est à peu près transformé en code C # textuellement à l'exception de remplacer les références variables. La propriété .value hors de $ gauche et vient droit $ du rendement indiqué hors des règles qui ont été créés à partir.

Si je devais faire un compilateur C # aujourd'hui, voici ce que je faire essayer comme une première tentative:

  1. Commencez par le ANTLR C # 3 cible (bien sûr, je suis partial ici - vous pouvez sérieusement utiliser soit la cible CSharp2 ou CSharp3)
  2. .
  3. Get Visual Studio 2010 avec le .NET Framework 4. La clé ici est .NET 4 et il est des arbres nouveaux d'expression douce.
  4. Construire un analyseur combiné de base. Mettez aussi peu logique dans l'analyseur comme tout à fait possible. Il devrait avoir peu (le cas échéant) des actions, et la sortie devrait être un undecorated AST qui peut être parcouru avec déambulateur LL (1).
  5. Construire une grammaire d'arbres pour parcourir l'arborescence et d'identifier tous les types déclarés. Il convient également de garder les sous-arbres member_declaration pour une utilisation ultérieure.
  6. Construire un marcheur arbre qui marche un seul member_declaration et ajoute le membre à la balise TypeBuilder . Gardez une trace des corps de méthode, mais ne les à pied profond encore.
  7. Construire un marcheur arbre qui marche le corps d'une méthode. Générer un Expression<TDelegate> correspondant à la méthode, et utiliser CompileToMethod mon propre API (voir de Pavel et mes commentaires) pour générer le code IL.

Si vous faites les choses dans cet ordre, lorsque vous êtes enfin l'analyse syntaxique des expressions (corps de méthode, Initialiseur sur le terrain), vous pouvez utiliser les méthodes paramétrées de string comme celui-ci dans Expression classe pour sauver les membres résoudre le travail.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top