J'ai une grammaire YACC (Bison), un tokenizer Lex (Flex) et un programme C parmi lesquels j'ai besoin de partager un struct
(ou vraiment n'importe quelle variable). Actuellement, je déclare l'objet réel dans le fichier de grammaire et extern
là où j'en ai besoin (c'est-à-dire, mon fichier source C), en utilisant généralement un pointeur pour le manipuler. J'ai un fichier en-tête (et implémentation) partagé entre le fichier C et le fichier de grammaire avec des fonctions utiles pour manipuler ma structure de données. Cela fonctionne, mais il se sent un peu mal à l'aise. Existe-t-il un meilleur moyen de partager la mémoire entre la grammaire et le programme?Partage de la mémoire entre les fichiers YACC, Lex et C
Répondre
Un fichier d'en-tête pour partager la déclaration externe entre les fichiers source qui en ont besoin est la meilleure solution. L'alternative majeure est de lui fournir un «accès fonctionnel», c'est-à-dire une sorte de fonction «get value» et «set value» (ou un ensemble de fonctions). Ceci est généralement exagéré. Assurez-vous d'inclure l'en-tête dans la grammaire (où vous définissez la variable) ainsi que dans le lexeur et l'autre code afin que les incohérences soient repérées dès que possible.
Si vous voulez vous en tenir au standard (POSIX) lex/yacc, alors votre seule option est d'opter pour des variables/fonctions globales. Si vous utilisez les extensions Bison et Flex, il existe plusieurs façons de passer des variables, qui impliquent principalement l'ajout de paramètres supplémentaires à yyparse() et yylex().
Dans Bison, ceci est accompli par% lex-param et% parse-param.
%parse-param { struct somestruct *mystruct }
%lex-param { struct somestruct *mystruct }
Dans Flex, il existe deux mécanismes différents, selon que vous voulez ou non une lexer réentrante. En supposant que vous allez avec l'option par défaut (non rentrante), vous aurez envie de redéfinir YY_DECL:
%{
#define YY_DECL int yylex(struct somestruct *mystruct)
%}
Dans un rentrante Flex lexer, des arguments supplémentaires peuvent être ajoutés par la struct du scanner qui porte Flex autour de garder son Etat. Vous voudrez définir YY_EXTRA_TYPE; les données supplémentaires peuvent être accessibles via yyget/set_extra().