[英]Confusion about a Bison/YACC Grammar
使用以下語法,使用這種輸入會出現語法錯誤:
ls /home > foo #Runs and works okay, but raises error token
ls /home /foo /bar /etc #works okay
我認為這可能與前瞻的工作方式有關,但這是我的第一個語法,我對為什么它不能這樣工作感到有些困惑:external_cmd GT WORD是重定向,redirect是命令,command是命令,因此輸入命令NEWLINE應該可以使用。
語法最高規則:
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);
}
;
引發錯誤令牌時的調試/詳細輸入:
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
更新:
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;
}
語法錯誤來自您對yyparse的第二次調用。 進行重定向后,語法將執行YYACCEPT,這將導致解析器立即返回而無需讀取更多內容。 在第二次調用中,讀取的第一個令牌是一個NEWLINE,它可以防止出現錯誤(您的語法不允許空行。)
沒有重定向,就沒有YYACCEPT,因此語法會繼續運行,讀取換行符並返回到輸入的末尾。
你真的真的應該使用左遞歸與LALR(1)語法分析器發電機。 正確的遞歸要求所有元素都必須轉移到解析器狀態堆棧上,甚至可以進行一次歸約。 您可以想象這對錯誤恢復有什么作用。
external_cmd
到底是什么? 看起來好像它在早期減少,但是很難說出來,因為您沒有包括它。
為什么重定向后會調用YYACCEPT
? 如果打算在每行上重新啟動解析器,則不應具有遞歸輸入收集器。 只要您有,就不要做YYACCEPT。
找到它后,在我的重定向規則中有一個缺失的管道,因此有兩個組件而不是兩個組件,其中一個具有中規則操作,這不是我想要的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.