我更喜欢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
答案 0 :(得分:1)
您需要提供一个main()
函数(至少)调用yyparse()
。否则,将使用main
中的libfl
。 main
不会调用yyparse()
;相反,它会反复调用yylex
,直到发出EOF信号。 (libfl
是Flex的一部分,而不是野牛,所以它不能依赖于yyparse
甚至是现有的。)
确实无需与-lfl
关联。 main()
定义对您没有用,库中唯一的其他内容是yywrap()
的虚拟定义。您没有定义yywrap()
,因此将调用库函数;但是,您可以简单地添加
%option noyywrap
到您的Flex代码(就在%%
之前),然后生成的扫描程序将不会调用yywrap()
。
调用野牛时也无需使用-y
标志。使用-y
的唯一原因是能够使用bison处理传统的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);
)
这就是当您输入换行符时输出额外换行符的原因。
答案 1 :(得分:-1)
所以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"