来自Bison手册:
在一个简单的交互式命令解析器中 每个输入是一行,它可以 足以让yyparse到 错误时返回1并拥有调用者 忽略输入行的其余部分 发生了(然后调用yyparse 再次)。
这几乎是我想要的,但我无法上班。基本上,我想在flex中检测和出错,如果检测到错误,让Bison丢弃整行。我现在所拥有的,是不正常的,因为我的命令仍然执行:
kbsh: ls '/home
Error: Unterminated Single Quote
admin kbrandt tempuser
syntax error
kbsh:
在我的Bison文件中:
commands:
/*Empty*/ { prompt(); } |
command { prompt(); }
;
command:
error {return 1; } |
chdir_command |
pwd_command |
exit_command |
WORD arg_list {
execute_command($1, $2);
//printf("%s, %s\n", $1, $2);
} |
WORD { execute_command($1, NULL); }
;
在我的Flex中:
' {BEGIN inQuote; }
<inQuote>\n {printf("Error: Unterminated Single Quote\n"); BEGIN(0); return(ERROR);}
答案 0 :(得分:6)
我认为你找不到一个简单的解决方案来处理词法分析器中的这些类型的解析错误。
我会保持lexer(flex / lex)尽可能笨,它应该只提供一个基本标记流(标识符,关键字等等)并让解析器(yacc / bison)进行错误检测。实际上,只需对您的方法进行一些重组,它就可以根据您的需要进行设置......
在lexer(parser.l)中,保持简单(没有eol / newline处理),类似(不是完整的东西):
}%
/* I don't recall if the backslashify is required below */
SINGLE_QUOTE_STRING \'.*\'
DOUBLE_QUOTE_STRING \".*\"
%%
{SINGLE_QUOTE_STRING} {
yylval.charstr = copy_to_tmp_buffer(yytext); // implies a %union
return STRING;
}
{DOUBLE_QUOTE_STRING} {
yylval.charstr = copy_to_tmp_buffer(yytext); // implies a %union
return STRING;
}
\n return NEWLINE;
然后在你的parser.y文件中做所有真正的处理(不是完整的东西):
command:
error NEWLINE
{ yyclearin; yyerrorok; print_the_next_command_prompt(); }
| chdir_command STRING NEWLINE
{ do_the_chdir($<charstr>2); print_the_next_command_prompt(); }
| ... and so on ...
这里有两点需要注意:
int yywrap() {return 1;}
”)。如果你试图在flex中过早发现它,你何时知道引发错误?这样你应该得到类似的东西(猜测chdir可能是什么样子):
cd'some_directory
语法错误
cd'some_directory'
你在some_directory dude!
它全部由yacc语法处理,而不是由标记器处理。
我发现尽可能简单地保持弯曲会给你最大的灵活性。 :)