2010-12-10 4 views
8

Je migre un compilateur de langage de programmation basé sur C# d'un lexeur/analyseur manuel vers Antlr. Antlr m'a donné des maux de tête sévères parce que généralement travaille, mais il ya aussi les petites parties qui ne sont pas et sont incroyablement douloureuses à résoudre.Analyseur ANTLR avec lexeur manuel

J'ai découvert que la plupart de mes maux de tête sont causés par les parties lexer d'Antlr, plutôt que par l'analyseur. Puis j'ai remarqué parser grammar X; et j'ai réalisé que peut-être je pourrais avoir mon lexer écrit manuellement et ensuite un analyseur généré par Antlr. Donc, je suis à la recherche de plus de documentation sur ce sujet. Je suppose qu'un ITokenStream personnalisé pourrait fonctionner, mais il semble y avoir pratiquement aucune documentation en ligne sur ce sujet ...

+0

Ma recommandation est que vous pouvez apprendre de ceux qui existent déjà. Cependant, je ne peux trouver que NHibernate qui utilise Antlr, et l'utilisation est plutôt limitée. : " –

+0

*" mais il y a aussi les petites parties qui ne sont pas et qui sont incroyablement douloureuses à résoudre "* - Odd La partie laxative d'une langue est généralement plus facile à implémenter Peut-être pourriez-vous expliquer ce que les" petites parties "vous donnent Problèmes? –

+0

@Bart Kiers Je rencontre des problèmes avec l'implémentation de plages et d'autres fonctionnalités (telles que 3.toString() et 3.0.toString()) d'une manière différente de celle indiquée dans leur FAQ. Incroyablement simple à résoudre dans un lexer créé manuellement – luiscubal

Répondre

7

J'ai découvert comment. Ce n'est peut-être pas la meilleure approche, mais cela semble fonctionner.

  1. parseurs Antlr reçoivent un paramètre ITokenStream
  2. lexers Antlr sont eux-mêmes ITokenSource s
  3. ITokenSource est une interface nettement plus simple que ITokenStream
  4. La façon la plus simple de convertir un ITokenSource à un ITokenStream est d'utiliser un CommonSourceStream , qui reçoit un paramètre ITokenSource

Alors maintenant, nous ne devons faire 2 choses:

  1. Adjust la grammaire à être analyseur seulement
  2. Mettre en oeuvre ITokenSource

Réglage de la grammaire est très simple. Supprimez simplement toutes les déclarations lexer et assurez-vous de déclarer la grammaire comme parser grammar. Un exemple simple est affiché ici pour convinience:

parser grammar mygrammar; 

options 
{ 
    language=CSharp2; 
} 

@parser::namespace { MyNamespace } 

document: (WORD {Console.WriteLine($WORD.text);} | 
     NUMBER {Console.WriteLine($NUMBER.text);})*; 

Notez que le fichier suivant affichera class mygrammar au lieu de class mygrammarParser. Alors, nous voulons maintenant implémenter une fausse "lexer". J'ai personnellement utilisé le pseudo-code suivant:

TokenQueue q = new TokenQueue(); 
//Do normal lexer stuff and output to q 
CommonTokenStream cts = new CommonTokenStream(q); 
mygrammar g = new mygrammar(cts); 
g.document(); 

Enfin, nous devons définir TokenQueue. TokenQueue n'est pas strictement nécessaire mais je l'ai utilisé pour plus de commodité. Il devrait avoir des méthodes pour recevoir les jetons lexer, et des méthodes pour sortir les jetons Antlr. Donc, si vous n'utilisez pas les jetons natifs Antlr, vous devez implémenter une méthode convert-to-Antlr-token. En outre, TokenQueue doit implémenter ITokenSource. Sachez qu'il est très important de définir correctement les variables de jeton. Au départ, j'ai eu quelques problèmes parce que j'avais mal calculé CharPositionInLine. Si ces variables sont incorrectement définies, l'analyseur peut échouer. En outre, le canal normal (non masqué) est 0.

Cela semble fonctionner pour moi jusqu'à présent. J'espère que les autres le trouveront utile aussi. Je suis ouvert aux commentaires. En particulier, si vous trouvez une meilleure façon de résoudre ce problème, n'hésitez pas à poster une réponse séparée.

+0

bon travail, comment avez-vous géré le fichier .tokens? J'essaie de faire quelque chose de similaire sauf utiliser les pygment lexers – Naveen

+0

@Naveen Je ne me souviens pas avoir fait quoi que ce soit dans le fichier .tokens. – luiscubal

+0

J'ai aussi votre méthode pour travailler avec python. D'autres ont utilisé avec jflex et stax. J'ai posté un exemple simple sur github: https://github.com/tinku99/antlr-pygments – Naveen