Question

Je crée un compilateur avec Lex et YACC (en fait Flex et Bison). La langue permet des références à terme illimitées à un symbole (comme C #). Le problème est qu'il est impossible d'analyser la langue sans savoir ce qu'est un identifiant est.

La seule solution que je connaisse est la lex toute source, puis faire une « largeur d'abord » analyser, les choses de niveau si élevés comme les déclarations de classe et les déclarations de fonction se parsés avant que les fonctions qui les utilisent. Cependant, cela prendrait une grande quantité de mémoire pour les gros fichiers, et il serait difficile de traiter avec YACC (je dois créer grammaires distincts pour chaque type de déclaration / corps). Je dois aussi écrire à la main le lexer (qui est pas un gros problème).

Je ne me soucie pas beaucoup sur l'efficacité (bien qu'il soit encore important), parce que je vais réécrire le compilateur en lui-même une fois que je l'ai fini, mais je veux que la version soit rapide (donc s'il y a toutes les techniques générales rapide qui ne peut pas être fait dans Lex / YACC mais peut être fait à la main, s'il vous plaît les suggèrent aussi). Donc, en ce moment, la facilité de développement est le facteur le plus important.

Y a-t-il des bonnes solutions à ce problème? Comment cela se fait habituellement dans les compilateurs pour les langages comme C # ou Java?

Était-ce utile?

La solution

Il est tout à fait possible de l'analyser. Bien qu'il y ait une ambiguïté entre les identifiants et mots-clés, lex heureusement face à cela en donnant la priorité des mots-clés.

Je ne vois pas ce que d'autres problèmes, il y a. Vous n'avez pas besoin de déterminer si les identificateurs sont valables pendant la phase d'analyse syntaxique. Vous construisez soit un arbre d'analyse syntaxique ou un arbre de syntaxe abstraite (la différence est subtile, mais non pertinente aux fins de cette discussion) que vous analysez. Après que vous construisez vos structures de table de symboles imbriqués en effectuant une passe au-dessus de l'AST que vous avez généré au cours de l'analyse syntaxique. Ensuite, vous faites une autre passe au-dessus de l'AST pour vérifier que les identifiants utilisés sont valides. Suivez ce avec un ou plusieurs Parsis supplémentaires sur l'AST pour générer le code de sortie, ou d'un autre intermédiaire et vous structure de données est fait!

EDIT: Si vous voulez voir comment il est fait, vérifiez le code source du compilateur Mono C #. Ceci est en fait écrit en C # plutôt que C ou C ++, mais il utilise le port .NET de Jay qui est très similaire à yacc.

Autres conseils

Une option consiste à traiter les renvois en avant par seulement des jetons de numérisation et de mise en cache jusqu'à ce que vous touchez quelque chose que vous savez comment réel (un peu comme la récupération d'erreur « panique en mode »). Une fois que vous avez exécuté pensé que le dossier complet, revenir en arrière et essayer de nouveau analyser les bits qui ne compilent avant.

Pour ce qui est d'avoir à écrire à la main le lexer; ne pas utiliser lex pour générer un analyseur normal et il suffit de lire à partir via une cale écrite à la main qui vous permet de revenir en arrière et alimenter l'analyseur à partir d'un cache ainsi que ce que fait lex.

Quant à faire plusieurs grammaires, un peu de plaisir avec un préprocesseur sur le fichier yacc et vous devriez être en mesure de les faire tous de la même source d'origine

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