Confusão sobre um Bison / YACC Grammar
Pergunta
Com o seguinte gramática, eu recebo um erro de sintaxe com este tipo de entrada:
ls /home > foo #Runs and works okay, but raises error token
ls /home /foo /bar /etc #works okay
Eu acho que pode ter algo a ver com a forma como lookahead obras, mas esta é a minha primeira gramática e estou um pouco confuso sobre o porquê de ele não funciona desta maneira: external_cmd GT WORD é um redirecionamento, redirecionamento é um comando, comando é um comando, de modo que a entrada comandos NEWLINE deve funcionar.
Regras Top da gramática:
input:
error NEWLINE {
printf("Error Triggered\n");
yyclearin;
yyerrok;
prompt();
} |
input NEWLINE {
prompt();
} |
input commands NEWLINE {
prompt ();
} |
/* empty */
;
commands:
command |
command SEMI |
command SEMI commands
;
command:
builtin_cmd |
redirect |
external_cmd {
execute_command($1, 0, NULL);
}
;
redirect:
external_cmd GT WORD {
printf("Redirecting stdout of %s to %s\n", $1->cmd, $3);
//printf("DEBUG: GT\n");
execute_command($1, STDOUT_FILENO, $3);
}
external_cmd LT WORD {
printf("Redirecting stin of %s to %s\n", $1->cmd, $3);
//printf("DEBUG: GT\n");
execute_command($1, STDIN_FILENO, $3);
}
;
O debug / detalhado de entrada quando o token erro é gerado:
Next token is token WORD ()
Shifting token WORD ()
Entering state 6
Reading a token: Next token is token WORD ()
Shifting token WORD ()
Entering state 24
Reading a token: Next token is token GT ()
Reducing stack by rule 22 (line 115):
$1 = token WORD ()
-> $$ = nterm arg_list ()
Stack now 0 2 6
Entering state 26
Reducing stack by rule 19 (line 91):
$1 = token WORD ()
$2 = nterm arg_list ()
-> $$ = nterm external_cmd ()
Stack now 0 2
Entering state 16
Next token is token GT ()
Shifting token GT ()
Entering state 29
Reading a token: Next token is token WORD ()
Shifting token WORD ()
Entering state 33
Reducing stack by rule 11 (line 68):
Redirecting stdout of ls to foo
DEBUG: redirect mode is 1
DEBUG: Command to run is ls
DEBUG: Adding Argument /home
admin kbrandt tempuser
-> $$ = nterm @1 ()
Stack now 0 2 16 29 33
Entering state 34
Reading a token: Next token is token NEWLINE ()
syntax error
Error: popping nterm @1 ()
Stack now 0 2 16 29 33
Error: popping token WORD ()
Stack now 0 2 16 29
Error: popping token GT ()
Stack now 0 2 16
Error: popping nterm external_cmd ()
Stack now 0 2
Error: popping nterm input ()
Stack now 0
Shifting token error ()
Entering state 1
Next token is token NEWLINE ()
Shifting token NEWLINE ()
Entering state 3
Reducing stack by rule 1 (line 38):
$1 = token error ()
$2 = token NEWLINE ()
Error Triggered
-> $$ = nterm input ()
Stack now 0
Entering state 2
Update:
external_cmd é:
external_cmd:
WORD arg_list {
$$ = malloc( sizeof(struct ext_cmd) );
if ( $$ == NULL)
printf("Memory Allocation Error\n");
$$->cmd = $1;
$$->args_pp = $2;
} |
WORD {
$$ = malloc( sizeof(struct ext_cmd) );
if ( $$ == NULL)
printf("Memory Allocation Error\n");
$$->cmd = $<string>1;
$$->args_pp = NULL;
}
Solução 3
encontrou, na minha regra de redirecionamento não é um cachimbo faltando, então ao invés de dois componentes, há um com uma ação de meados de regra, o que não é o que eu quero.
Outras dicas
O erro de sintaxe é proveniente de sua chamada segundo para yyparse. Quando você tem o redirecionamento, você gramática faz um YYACCEPT, o que faz com que o analisador para retornar imediatamente sem ler mais nada. Na segunda chamada, a primeira leitura token é uma nova linha, que casos o erro (a sua gramática não permite linhas em branco.)
Sem redirecionamento, não há YYACCEPT, de modo a gramática continuar a funcionar, a leitura da nova linha e retornando ao chegar ao fim da entrada.
-
Você realmente realmente deve usar recursão esquerdo com LALR (1) geradores de analisador. recursão direito exige que todos os elementos ser deslocado para a pilha estado analisador antes mesmo de uma única redução pode ocorrer. Você pode imaginar o que isso faz para recuperação de erros.
-
O que é exatamente
external_cmd
? É o tipo de parece que ele está sendo reduzido no início, mas é difícil dizer, porque você não incluí-lo. -
Por que é
YYACCEPT
invocado depois de qualquer redirecionamento? Se você está pretendendo para reiniciar o analisador em cada linha, então você não deve ter o coletor de entrada recursiva. Contanto que você tem isso, não faça um YYACCEPT.