Question

Pardonnez-moi, je suis complètement nouveau dans l'analyse syntaxique et lex / yacc, et je suis probablement au-dessus de ma tête, mais néanmoins:

J'écris une calculatrice assez basique avec PLY, mais son entrée n'est peut-être pas toujours une équation, et je dois déterminer si c'est le cas ou non lors de l'analyse. Les extrêmes de l’entrée seraient quelque chose qui correspond parfaitement à une équation, qu’elle analyse parfaitement et calcule, ou quelque chose qui ne ressemble en rien à une équation, qui échoue lors de l’analyse et qui convient également.

La zone grise est une entrée qui comporte des parties de type équation, que l'analyseur va saisir et résoudre. Ce n’est pas ce que je veux. Je dois pouvoir savoir si des parties de la chaîne n’ont pas été ramassées et marquées afin que je puisse renvoyer une erreur, mais je ne sais pas comment faire.

Est-ce que quelqu'un sait comment je peux définir, en gros, un jeton "attraper tout ce qui reste"? Ou y a-t-il une meilleure façon de gérer cela?

Était-ce utile?

La solution

Il y a un jeton d'erreur intégré dans yacc. Vous feriez normalement quelque chose comme:

ligne: goodline | badline;

badline: error '\ n' / * Action de gestion des erreurs, si nécessaire * /

goodline: équation '\ n';

Toute ligne qui ne correspond pas à équation sera traitée par badline .

Vous pouvez utiliser yyerrok dans l'action de traitement des erreurs pour vous assurer que le traitement de l'erreur est réinitialisé pour la ligne suivante.

Autres conseils

Définissez un jeton (fin d’entrée) et faites-le sortir par votre lexer à la fin de l’entrée.

Donc avant, si vous aviez ces jetons:

'1' 'PLUS' '1'

Vous aurez maintenant:

'1' 'PLUS' '1' 'END_OF_INPUT'

Vous pouvez maintenant définir votre règle de niveau supérieur dans votre analyseur. Au lieu de (par exemple):

Equation ::= EXPRESSION

Vous aurez

Equation ::= EXPRESSION END_OF_INPUT

Évidemment, vous devrez les réécrire avec la syntaxe PLY, mais cela devrait vous rendre la majeure partie du chemin.

J'utilise généralement un "lecteur de commandes" séparé pour obtenir une commande complète - probablement une ligne dans votre cas - dans une chaîne de variable hôte, puis je fais en sorte que l'analyseur lexical analyse la chaîne, notamment en m'indiquant quand il ne l'a pas été ". t atteindre la fin. Ceci est difficile à configurer, mais facilite certaines classes de rapports d’erreurs. L’un des endroits où j’ai utilisé cette technique a régulièrement des commandes multi-lignes avec 3 conventions de commentaire, deux ensembles de chaînes citées, et quelques autres méchants pour me mordre à fond (tokenization sensible au contexte - beurk!).

Sinon, le conseil de Don avec le jeton "erreur" de Yacc est bon.

Il semble que vous ayez déjà trouvé une solution, mais je vais ajouter une autre suggestion si vous ou d'autres personnes êtes intéressés par une autre approche.

Vous dites que vous utilisez PLY mais est-ce parce que vous voulez que le compilateur s'exécute dans un environnement Python? Si c'est le cas, vous pourriez également envisager d'autres outils. Pour ces tâches, j’utilise souvent ANTLR ( http://www.antlr.org ) qui dispose d’un générateur de code Python. . ANTLR a beaucoup de trucs pour faire des choses comme manger beaucoup d’entrées au niveau du lexer pour que l’analyseur ne le voie jamais (par exemple des commentaires), la possibilité d’appeler une sous-règle (par exemple une équation) dans une grammaire plus grande (qui devrait se terminer une fois la la règle a été mise en correspondance sans traiter plus d’entrée ... semble un peu comme ce que vous voulez faire) et un très bel algorithme de factorisation à gauche.

Capacité d'analyse ANTLR associée à l'utilisation de StringTemplate ( http://www.stringtemplate.org ) moteur fait une belle combinaison et les deux supportent Python (parmi beaucoup d'autres).

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