YACC 无法解析 SIMPE shell 语法



我正在使用 yacc/lex 为 shell 编写一个简单的语法。我希望我的语法能够识别管道,这些管道具有以下形式:command1 | command2 | ... | commandn.我能够重新定义单个命令,the simple_command规则作为下面的代码中的启动非终端。但是,当我添加其他规则(simple_command_listpipeline(来解析管道时,事情不起作用。为了测试语法,我让 yacc 从以下字符串读取输入:char *input = "command1 | command2 | command3 | command4n",在主函数中定义。当被要求解析此字符串时,yacc 只解析第一个命令,打印"parse error",然后停止,如下所示:

command "command1"
simple command 
1B
parse error

莱克斯代码:

%{ 
#include <string.h> 
#include "y.tab.h" 
%} 
%%

n      { 
return NEWLINE; 
} 
[ t]   { 
/* Discard spaces and tabs */ 
} 
">"     { 
return GREAT; 
} 
"<"     { 
return LESS; 
} 

“|”    { 
return PIPE; 
} 
“&”    { 
return AMPERSAND; 
} 

[a-zA-Z][a-zA-Z0-9]*  { 
/* Assume that file names have only alpha chars */ 
yylval.str = strdup(yytext); 
return WORD; 
} 

.       { 
/* Invalid character in input */ 
return BAD_TOKEN;
}
%%
int yywrap(void) {
return 1;
}

雅克代码:

%{
#include <string.h>
#include <stdio.h>
int yylex(void);
void yyerror(char *);

%}
%union
{
char *str;
int i;
}
%token <i> AMPERSAND GREAT LESS PIPE NEWLINE BAD_TOKEN
%token <str> WORD
%start pipeline
%expect 1

%%
cmd:
WORD
{
printf("command "%s"n", $1);
}
;
arg:
WORD
{
printf("argument "%s"n", $1);
}
;
arg_list:
arg_list arg
{
//printf(" argument list: n");
}
| // empty

;
simple_command:
cmd arg_list
{
printf("simple command n");
}
;
simple_command_list:
simple_command_list PIPE simple_command
{
printf("1An");
}
| simple_command
{
printf("1Bn");
}
;
pipeline:
simple_command_list NEWLINE
{
printf("p-An");
}
| NEWLINE
{
printf("p-Bn");
}
;

%%

void yyerror(char *s) {
fprintf(stderr, "%sn", s);
}

int main(void) {
// read input from a string
//YY_BUFFER_STATE *bp;
struct yy_buffer_state *bp;
char *input = "command1 | command2 | command3 | command4n";
//  connect input buffer to specified string
bp = yy_scan_string(input);
// read from the buffer
yy_switch_to_buffer(bp);

// parse 
yyparse();
// delete the buffer
yy_delete_buffer(bp);
// delete the string (or not)

return 0;
}

您的 lex 源文件包含 unicode 字符,如(U-201C 左双引号(和(U-201D 右双引号(,lex 不会将其重新识别为引号,因此正在寻找包含该 7 字节 UTF-8 序列而不是单字节|的输入序列。

用 Ascii"字符替换它们,它应该可以工作。

如果使用 bison 的--debug选项启用调试,您应该看到它正在获取哪些令牌以及它正在移动和减少哪些规则。 在您的情况下,为|获得BAD_TOKEN...

最新更新