Question

Définition de l'interpolation de Wikipedia J'apprends juste flex / bison et j'écris ma propre coquille avec. J'essaie de trouver un bon moyen d'interpolation variable. Mon approche initiale à cet égard consistait à effectuer une analyse flexible de quelque chose comme ~ pour mon répertoire personnel, ou $ myVar, puis à définir le yyval.stringto ce qui est renvoyé à l'aide d'une fonction de recherche. Mon problème est que cela ne m'aide pas lorsque du texte apparaît sur un jeton:

kbsh:/home/kbrandt% echo ~
/home/kbrandt
kbsh:/home/kbrandt% echo ~/foo
/home/kbrandt /foo
kbsh:/home/kbrandt%

La définition de la lex que j'ai pour les variables:

\$[a-zA-Z/0-9_]+    {
    yylval.string=return_value(&variables, (yytext + sizeof(char)));;
    return(WORD);
}

Puis, dans ma grammaire, j'ai des choses comme:

chdir_command:
    CD WORD { change_dir($2); }
    ;

Quelqu'un connaît-il un bon moyen de gérer ce genre de chose? Est-ce que je vais à ce sujet tout faux?

Était-ce utile?

La solution

La manière dont les coques 'traditionnelles' traitent des choses comme la substitution variable est difficile à gérer avec lex / yacc. Ce qu’ils font ressemble plus à une expansion macro, où APRÈS l’extension d’une variable, ils re-segmentent l’entrée, sans développer d’autres variables. Ainsi, par exemple, une entrée du type " xx $ {$ foo} " où "foo" est défini comme "bar" et "bar" est défini comme "$ y" sera étendu à "xx $ y" qui sera traité comme un seul mot (et que y ne sera PAS développé).

Vous POUVEZ régler ce problème en flex, mais vous avez besoin de beaucoup de code de support. Vous devez utiliser les éléments yy_buffer_state de flex pour parfois rediriger la sortie dans une mémoire tampon à partir de laquelle vous devez ensuite effectuer une nouvelle analyse, et utiliser les états de démarrage avec précaution pour contrôler le moment où les variables peuvent et ne peuvent pas être développées.

Il est probablement plus facile d’utiliser un lexer très simple qui renvoie des jetons tels que ALPHA (un ou plusieurs caractères alphabétiques), NUMERIC (un ou plusieurs chiffres) ou WHITESPACE (un ou plusieurs espaces ou tabulations) et que l’analyseur les assemble. de manière appropriée, et vous vous retrouvez avec des règles telles que:

simple_command: wordlist NEWLINE ;

wordlist: word | wordlist WHITESPACE word ;

word: word_frag
    | word word_frag { $ = concat_string($1, $2); }
;

word_frag: single_quote_string
         | double_quote_string
         | variable
         | ALPHA
         | NUMERIC
        ...more options...
;

variable: '

comme vous pouvez le voir, cela devient assez rapidement complexe.

name { $ = lookup($2); } | '

comme vous pouvez le voir, cela devient assez rapidement complexe.

'{' word '}' { $ = lookup($3); } | '

comme vous pouvez le voir, cela devient assez rapidement complexe.

'{' word ':' ....

comme vous pouvez le voir, cela devient assez rapidement complexe.

Autres conseils

On dirait généralement que c'est OK

Je ne sais pas ce que return_value est en train de faire. J'espère que ce sera strdup (3) le nom de la variable, car yytext est simplement un tampon.

Si vous vous interrogez sur la division du travail entre lex et parse, je suis sûr qu'il est parfaitement raisonnable de transférer le traitement des macros et la substitution de paramètres dans le scanner et de laisser votre grammaire régler le problème avec WORD . s, des listes, des commandes, des pipelines, des redirections, etc. Après tout, il serait raisonnable de faire tout avec du code, même si cela n’est pas à la mode et peut-être même fausser le sens de votre exercice.

Je pense vraiment que faire de cd ou chdir un symbole de terminal et que l’utiliser dans une production grammaticale ne soit ... pas la meilleure décision de conception. Ce n’est pas parce qu’une commande est intégrée qu’elle doit apparaître en règle générale. Allez-y et analysez cd et chdir comme toute autre commande. Recherchez la sémantique intégrée en tant qu'action et non en tant que production.

Après tout, que se passe-t-il s'il est redéfini en tant que procédure shell?

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