我很喜欢Yacc编程,我有一个简单的任务来编写一个程序,它检查输入文本文件是否包含一系列正确配对的括号。任何不正确的序列都应标记为“语法错误!”。我用野牛和弯曲。
示例正确数据:(()()((())())())但(()不正确。
我的问题是,我认为它应该工作,但似乎yyerror无法正常工作。也许我做错了什么,请纠正我。这是我的代码Yacc代码:
%{
int yylex();
void yyerror(char* x);
%}
%%
S: S A
|A
;
A: '('S')'
|'(' ')'
;
和lex代码:
%{
#include "y.tab.h"
%}
%%
[\(\)] return(yytext[0]);
. {printf("%c - error!\n",yytext[0]);}
%%
void yyerror(char* x)
{
printf("syntax error");
exit(1);
}
所以问题是它不会触发语法错误,我写的括号有多大并不重要。编辑:这是我编译它的方式:screen
你需要提供一个main()
函数(至少)调用yyparse()
。否则,将使用来自main
的libfl
。那main
不叫yyparse()
;相反,它反复调用yylex
直到发出EOF信号。 (libfl
是Flex的一部分,而不是野牛,所以它不能依赖yyparse
甚至存在。)
真的没有必要与-lfl
联系。 main()
定义对你没有用,库中唯一的其他东西是yywrap()
的虚拟定义。你没有定义yywrap()
,所以将调用库函数;但是,您可以简单地添加,而不是依赖于库
%option noyywrap
你的flex代码(就在%%
之前),然后生成的扫描程序将不会调用yywrap()
。
当你调用野牛时,也没有必要使用-y
标志。使用-y
的唯一原因是能够使用野牛处理传统的yacc文件。我想你正在使用该标志,以便生成的解析器被称为y.tab.c
;没有标志,它将被称为z5.tab.c
(头文件将是z5.tab.h
);你可以使用这些名字。 (或者你可以通过使用-o
标志告诉bison你希望它使用的确切文件名。)
最后,关于你的lex文件的两个注释:
[()] { return yytext[0]; }
在字符类中不需要反斜杠转义括号,因为除了]
,-
和\
之外的其他字符在字符类中没有特殊含义。.
与换行符不匹配,这就是输入中的换行符不会产生错误消息的原因。实际上,没有一个模式与换行符匹配,因此当您键入换行符时,将调用默认规则。默认规则等同于ECHO
,bison定义为:
fputs(yytext, yyout);
(或fprintf(yyout, "%s", yytext);
)
这就是您输入换行符时输出额外换行符的原因。所以lex的正确代码是:
%{
#include "z5.tab.h"
%}
%%
[\(\)] return(yytext[0]);
. {printf("%c - error!\n",yytext[0]);}
\n ;
%%
int main(void)
{
yyparse();
return 0;
}
int yywrap(void)
{
return 0;
}
void yyerror(char* x)
{
printf("syntax error");
exit(1);
}
以及编译它的正确方法是:
flex s5.l
bison -d z5.y
gcc lex.yy.c z5.tab.c -L"C:\GnuWin32\lib"