野牛 yacc yyerror 不起作用
bison yacc yyerror doesn't work
我是 Yacc 编程的初学者,我有一个简单的任务来编写一个程序,它检查输入的文本文件是否
包含一系列正确配对的括号。任何不正确的顺序
应该被标记为 "Syntax error!"。我用bison和flex。
示例正确数据:
(()()((())())())
但
(()
不正确。
我的问题是我认为它应该有效,但 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()
。否则,将使用 libfl
中的 main
。那main
不叫yyparse()
;相反,它会重复调用 yylex
直到发出 EOF 信号。 (libfl
是 Flex 的一部分,而不是 bison,因此它不能依赖 yyparse
甚至存在。)
真的没必要link和-lfl
。 main()
定义对你没有用,库中唯一的其他东西是 yywrap()
的虚拟定义。你没有定义yywrap()
,所以会调用库函数;但是,您可以简单地添加
而不是依赖于库
%option noyywrap
到您的 flex 代码(就在 %%
之前),然后生成的扫描器将不会调用 yywrap()
。
调用 bison 时也无需使用 -y
标志。使用 -y
的唯一原因是能够使用 bison 处理遗留的 yacc 文件。我想你正在使用标志,以便生成的解析器被称为 y.tab.c
;如果没有标志,它将被称为 z5.tab.c
(头文件将是 z5.tab.h
);您可以只使用这些名称。 (或者您可以使用 -o
标志告诉 bison 您希望它使用的准确文件名。)
最后,关于您的 lex 文件的两点说明:
括号的格式可以这样写:
[()] { return yytext[0]; }
不需要在字符 class 内对括号进行反斜杠转义,因为除 ]
、-
和 \
外,其他字符在字符内没有特殊含义字符 class.
模式 .
与换行符不匹配,这就是您输入的换行符未产生错误消息的原因。事实上,none 的模式匹配换行符,因此当您键入换行符时,将调用默认规则。默认规则等同于 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"
我是 Yacc 编程的初学者,我有一个简单的任务来编写一个程序,它检查输入的文本文件是否 包含一系列正确配对的括号。任何不正确的顺序 应该被标记为 "Syntax error!"。我用bison和flex。
示例正确数据: (()()((())())()) 但 (() 不正确。
我的问题是我认为它应该有效,但 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()
。否则,将使用 libfl
中的 main
。那main
不叫yyparse()
;相反,它会重复调用 yylex
直到发出 EOF 信号。 (libfl
是 Flex 的一部分,而不是 bison,因此它不能依赖 yyparse
甚至存在。)
真的没必要link和-lfl
。 main()
定义对你没有用,库中唯一的其他东西是 yywrap()
的虚拟定义。你没有定义yywrap()
,所以会调用库函数;但是,您可以简单地添加
%option noyywrap
到您的 flex 代码(就在 %%
之前),然后生成的扫描器将不会调用 yywrap()
。
调用 bison 时也无需使用 -y
标志。使用 -y
的唯一原因是能够使用 bison 处理遗留的 yacc 文件。我想你正在使用标志,以便生成的解析器被称为 y.tab.c
;如果没有标志,它将被称为 z5.tab.c
(头文件将是 z5.tab.h
);您可以只使用这些名称。 (或者您可以使用 -o
标志告诉 bison 您希望它使用的准确文件名。)
最后,关于您的 lex 文件的两点说明:
括号的格式可以这样写:
[()] { return yytext[0]; }
不需要在字符 class 内对括号进行反斜杠转义,因为除
]
、-
和\
外,其他字符在字符内没有特殊含义字符 class.模式
.
与换行符不匹配,这就是您输入的换行符未产生错误消息的原因。事实上,none 的模式匹配换行符,因此当您键入换行符时,将调用默认规则。默认规则等同于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"