我正在尝试运行此.y文件
%{
#include <stdlib.h>
#include <stdio.h>
int yylex();
int yyerror();
%}
%start BEGIN
%%
BEGIN: 'a' | BEGIN 'a'
%%
int yylex(){
return getchar();
}
int yyerror(char* s){
fprintf(stderr, "*** ERROR: %s\n", s);
return 0;
}
int main(int argn, char **argv){
yyparse();
return 0;
}
这是一个简单的野牛程序,语法在我看来是正确的,但总是得到语法错误问题... 谢谢你的帮助。
答案 0 :(得分:1)
词法分析器函数yylex
需要返回0以指示输入的结束。但是,您的实现只会传递getchar
返回的值,该值将为EOF
(通常为-1)。
此外,您的输入几乎肯定会包含换行符,也会传递给解析器。
由于解析器既不识别\n
也不识别EOF
,因此在收到其中一个时会产生错误。
至少,您需要修改yylex
以正确响应输入结束:
int yylex(void) {
int ch = getchar();
return (ch == EOF) ? 0 : ch;
}
但你仍然需要处理换行符,要么通过在词法分析器中处理它们(可能忽略它们或者可能返回输入imdication的结尾),要么用你的语法处理它们。
请注意,bison / yacc生成的解析器始终解析整个输入流,而不仅仅是解析满足语法的最长序列。这可以通过一些工作来调整 - 请参阅YYACCEPT
特殊操作的文档 - 但标准行为通常是解析时所需的。
顺便说一句,请在您的bison / yacc语法中使用标准样式约定,以避免出现问题并避免让读者感到困惑。通常我们为终端符号保留UPPER_CASE
,因为它们也在词法分析器中用作编译时常量。非终端通常用lower_case
编写,但有些人更喜欢使用CamelCase
。对于终端,您需要避免使用标准库保留的名称(例如EOF
)或(f)lex(BEGIN
)或bison / yacc(END
) 。手册中有保留名称列表。