2010-03-19 18 views
3

Je veux générer deux fonctions d'analyse séparées à partir de lex/yacc. Normalement yacc vous donne une fonction yyparse() que vous pouvez appeler quand vous avez besoin de faire de l'analyse, mais j'ai besoin de plusieurs yypars différents, chacun associé à des lexers et des grammaires différents. La page man semble suggérer le drapeau -p (préfixe), mais cela n'a pas fonctionné pour moi. J'ai obtenu des erreurs de la part de gcc qui indiquait que yylval n'était pas correctement rebaptisé (c'est-à-dire qu'il prétend que plusieurs jetons différents ne sont pas définis). Est-ce que quelqu'un connaît la procédure générale pour générer ces fonctions séparées?Comment générer différentes fonctions yyparse à partir de lex/yacc pour les utiliser dans le même programme?

grâce

+0

(a) Quelles versions des outils utilisez-vous? (b) Avez-vous cherché des occurrences inattendues de 'yy' dans les grammaires/lexers censés utiliser un autre préfixe? Nous avons utilisé des scripts 'sed' pour les aeons (ce qui signifie plus de 20 ans) pour le faire - parce que les options de préfixes n'étaient pas toujours disponibles il y a longtemps - avec beaucoup de succès. ... Je devrais qualifier le truc 'grep yy'; 'flex -P zz lex.l' laisse beaucoup d'occurrences 'yy' dans la source C, lex.zz.c, mais aucune n'est visible en dehors du fichier objet (' nm -g lex.zz.o'). –

Répondre

1

Que diriez-vous d'un pointeur de fonction dans le code environnant qui échange sur parseurs, en supposant que vous ne voulez pas changer le contexte de l'analyse syntaxique au milieu de yylex() sur le même tampon.

Le pointeur de fonction peut être défini en incluant des analyseurs avec l'option de préfixe, ou ceux chargés à partir de DSO lors de l'exécution, a-la une configuration de plugin. Cela a l'avantage, qui peut ou peut ne pas vous être utile, que votre code qui gère l'AST peut être aveugle quant à la combinaison parser/lexer utilisée pour le produire.

1

Si vous utilisez flex/bison, vous pouvez utiliser les options «réentrantes», qui permettent d'avoir plusieurs instances du même scanner (ou également différentes). Cette option est présente sur la version récente de Flex. À mon humble avis, c'est la façon la plus propre d'avoir plusieurs scanners/parseurs dans le même programme. This article explique en profondeur le problème.

Une autre méthode consiste à utiliser la capacité de flex de générer une classe C++ au lieu d'un analyseur statique, mais cela force le programmeur C à écrire certaines fonctions wrapper.

Cordialement

2

J'ai eu un même problème il y a quelque temps et j'ai fini d'écriture du fichier d'en-tête suivant:

#ifndef RENAME_FLEX_H 
#define RENAME_FLEX_H 

#define yy_create_buffer scan__create_buffer 
#define yy_delete_buffer scan__delete_buffer 
#define yy_init_buffer scan_init_buffer 
#define yy_load_buffer_state scan_load_buffer_state 
#define yy_switch_to_buffer scan_switch_to_buffer 
#define yyin scan_in 
#define yyleng scan_leng 
#define yylex scan_lex 
#define yyout scan_out 
#define yyrestart scan_restart 
#define yytext scan_text 
#define yy_flex_debug scab_flex_debug 
#define yywrap scan_wrap 
#define yyrealloc scan_realloc 
#define yyfree scan_free 
#define yy_flush_buffer scan_flush_buffer 
#define yypush_buffer_state scan_push_buffer_state 
#define yypop_buffer_state scan_pop_buffer_state 
#define yy_scan_buffer scan_scan_buffer 
#define yy_scan_string scan_scan_string 
#define yy_scan_bytes scan_scan_bytes 
#define yyget_in scan_get_in 
#define yyget_out scan_get_out 
#define yyget_leng scan_get_leng 
#define yyset_text scan_set_text 
#define yyset_in scan_set_in 
#define yyset_out scan_set_out 
#define yyget_debug scan_get_debug 
#define yyset_debug scan_set_debug 
#define yylex_destroy scan_lex_destroy 
#define yyalloc scan_alloc 
#define yyget_text scan_get_text 

#endif 

et l'inclure dans .l, donc de mon dossier .c je peux utiliser scan_ symboles préfixés pour le second scanneur, plutôt que yy -prefixé