2009-11-11 5 views
1

À l'école, on nous a demandé de concevoir un langage puis de le mettre en œuvre (je m'amuse tellement à le mettre en œuvre =)). Mon professeur nous a dit d'utiliser yacc/lex, mais je décide d'aller avec Java + API regex, voici comment la langue que je conçu ressemble:Question de l'analyse de la syntaxe

Program "my program" 
var yourName = read() 
if { equals("guy1" to yourName) } 
    print("hello my friend") 
else 
print("hello extranger") 
end 
Program End 

Eh bien, comme vous pouvez le voir, son une langue assez basique =).

Je pensais que je pouvais le mettre en œuvre de façon très POO, comme faire une classe abstraite Sentence et ensuite les sous-classes comme VariableAssignment, IfSentence etc, et ont une classe Program qui est seulement un tas de phrases à droite? Et puis appeler une méthode abstraite eval sur tous les Sentence s, donc ma première approche complie la langue ne se composait que de deux phases:

  1. IDENTIFY Syntaxe de la ligne de seach
  2. Créer la classe correspondig pour chaque ligne

bien sûr, si quelque chose se passe mal sur une phase Ii pourrait générer une erreur. Ma question est: est-ce que je me trompe? Dois-je passer en revue toutes les phases comme le dit la théorie (lexicale, syntaxique, sémantique)? Devrais-je continuer avec mon compilateur naïf à deux phases?

+7

Grosse erreur. Vous devriez apprendre à analyser et au lieu de cela vous vous amusez avec des expressions régulières. Vous devriez passer à l'utilisation d'un système d'analyse Java tel que Jack ou, mieux encore, utiliser BYACC/J http://byaccj.sourceforge.net/ afin que vous soyez plus en phase avec la classe. –

Répondre

5

Je ne vais pas vous poser la question évidente de savoir pourquoi vous ne suivez pas les conseils de votre instructeur et utilisez yacc/lex parce que je connais la réponse. Tu voulais partir et faire quelque chose que tu trouvais cool et qui t'aiderait à apprendre. Malheureusement, cette approche a été recommandée par votre professeur car, comme l'a déclaré un autre post, beaucoup de gens très intelligents avant d'avoir exploré plusieurs approches et passé beaucoup de temps à essayer de trouver une bonne solution.

Vous pouvez faire fonctionner un compilateur à deux phases, mais vous devrez accepter qu'il ne sera jamais aussi efficace que de passer par le processus complet, car il est plus difficile de détecter les erreurs. Beaucoup plus difficile en fait. Dans certains cas, vous ne serez même pas en mesure de dire qu'il y a une erreur jusqu'à ce qu'il soit trop tard. ie: déjà compilé et essayant de fonctionner.

Si vous voulez en apprendre beaucoup plus à ce sujet, optez pour l'approche en deux phases et vous rencontrerez les mêmes problèmes que ceux que vous rencontriez avant. Assurez-vous simplement de comprendre qu'il vous faudra beaucoup plus de temps pour arriver à une solution finale, vous pourriez être amarré des points sur votre projet, et cela pourrait ne pas fonctionner correctement.

Cela dit, vous en apprendrez plus à ce sujet que quiconque dans la classe. Si vous avez le temps, je le ferais comme vous êtes maintenant. La connaissance pourrait être utile sur la route. Je voudrais aussi parler à votre professeur et lui dire que vous allez le faire d'une autre manière contre ses recommandations parce que vous voulez avoir une compréhension plus approfondie. Peut-être ne va-t-il pas enlever des points à votre projet pour être ambitieux, même si cela ne va pas.

Après tout, le point de faire des projets à l'université est d'apprendre.

5

Beaucoup de gens intelligents y ont réfléchi, et d'après votre message, ils sont arrivés à la conclusion que toutes les phases étaient nécessaires. Par conséquent, si vous voulez que votre compilateur fonctionne, suivez les règles de la théorie.

Si vous voulez comprendre, pourquoi dicte les phases, essayez le raccourci. Cela prendra probablement beaucoup plus de temps.


Disclaimer: Je n'ai aucune idée sur la théorie du compilateur


Une autre note: Vous avez un problème; Vous décidez de le résoudre en utilisant des expressions rationnelles; Maintenant vous avez deux problèmes

+0

@Jens Schauder, +1 pour la citation "Maintenant vous avez deux problèmes". –

1

Si vous utilisez des expressions régulières à parse chaque ligne votre langue aurait une syntaxe très limitée.

Vous ne seriez pas capable d'analyser chaque ligne en utilisant simplement une API d'expression régulière si votre syntaxe devenait plus complexe. Même le if { equals("guy1" to yourName) } deviendrait impossible à analyser avec regex si vous commencez à ajouter et et ou opérateurs, et que se passerait-il si vous commencez à supporter les caractères d'échappement comme \n dans vos littéraux de chaîne? L'API Java Regex serait capable de vous aider avec l'analyseur lexical, mais vous devriez écrire l'analyseur à partir de là. Vous pouvez prendre l'une de plusieurs approches:

  • Si vous utilisez Java, vous pouvez regarder Antlr (qui nie la nécessité d'écrire un analyseur de lexicall avec la bibliothèque regex de Java), ou
  • Vous pouvez écrire un analyseur de descente récursive main

entre autres

(également, « déclaration » est synonyme de « peine » qui est plus fréquent dans les textes du compilateur)

0

Si vous voulez vraiment vous salir les mains, codez un analyseur de descente récursif. Si vous voulez comprendre la théorie du compilateur, utilisez antlr et concentrez-vous sur les principes en laissant l'implémentation pour le générateur d'analyseur. BTW, pourquoi wnat compliquer votre vie avec regex?!

1

Si vous souhaitez utiliser uniquement des expressions régulières pour analyser votre langue, votre langue ne peut être que régulière. C'est une grosse constriction, par exemple, une imbrication arbitrairement profonde serait impossible, car vous devrez apprendre à votre analyseur chaque combinaison de nidification séparément. Je ne suis pas sûr si la construction d'un langage régulier de Turing est même possible.