Pergunta

da Wikipedia interpolação Definição Estou começando a aprender / bisonte flex e estou escrevendo minha própria shell com ele. Eu estou tentando descobrir uma boa maneira de fazer interpolação variável. Minha abordagem inicial a este era ter varredura flexível para algo como ~ para o meu diretório home, ou US $ myVar, em seguida, definir o que o yyval.stringto o que é retornado usando um olhar de função. Meu problema é que isso não me ajudar quando o texto aparece um token:

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

A definição lex que tenho por variáveis:

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

Então, em minha gramática, eu tenho coisas como:

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

Alguém sabe de uma boa maneira de lidar com esse tipo de coisa? Eu vou sobre esta tudo errado?

Foi útil?

Solução

A maneira conchas 'tradicionais' lidar com coisas como a substituição de variáveis ??é difícil de lidar com lex / yacc. O que eles fazem é mais parecido com expansão de macro, onde depois de expandir uma variável, que, em seguida, re-tokenizar a entrada, sem expandir novas variáveis. Assim, por exemplo, uma entrada como "$ xx {$ foo}" onde 'foo' é definido como 'bar' e 'bar' é definido como '$ y' vai se expandir para 'xx $ y', que será tratado como um única palavra (e $ Y não será ampliada).

Você pode lidar com isso em flex, mas você precisa de um monte de apoio código. Você precisa usar o material yy_buffer_state de flex para, por vezes, redirecionar a saída para um buffer que você vai, em seguida, nova verificação de e estados uso de início com cuidado para o controle quando as variáveis ??pode e não pode ser expandido.

É provavelmente mais fácil usar um lexer muito simples que retorna fichas como ALPHA (um ou caracteres mais alfabéticos), numérico (um ou mais dígitos), ou espaços em branco (um ou mais espaço ou tabulação), e têm o analisador montá-los apropriadamente, e você acaba com regras como:

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: '$' name { $$ = lookup($2); }
        | '$' '{' word '}' { $$ = lookup($3); }
        | '$' '{' word ':' ....

Como você pode ver, este ficar complexo muito rápido.

Outras dicas

Looks geralmente OK


Eu não tenho certeza o que return_value está fazendo, espero que strdup(3) o nome da variável, porque yytext é apenas um buffer.

Se você está perguntando sobre a divisão do trabalho entre lex e de análise, eu tenho certeza que é perfeitamente razoável para empurrar o processamento de macro e substituição de parâmetros no scanner e apenas ter seu negócio gramática com WORDs, listas, comandos, oleodutos, redirecionamentos, etc. Afinal, seria o suficiente razoável, embora tipo de fora do estilo e possivelmente derrotar a ponto do seu exercício, para fazer tudo com o código.

Eu acho que a tomada de cd ou chdir um símbolo terminal e usar isso em uma produção gramática é ... não a melhor decisão design. Só porque um comando é um built-in não significa que ele deve aparecer como uma regra. Vá em frente e cd análise e chdir como qualquer outro comando. Verifique se há built-in semântica como uma ação, não uma produção.

Afinal, o que se é redefinida como um processo shell?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top