野牛yacc yyerror不起作用

问题描述 投票:0回答:2

我很喜欢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

bison yacc
2个回答
1
投票

你需要提供一个main()函数(至少)调用yyparse()。否则,将使用来自mainlibfl。那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文件的两个注释:

  1. 括号的模式可以写成: [()] { return yytext[0]; } 在字符类中不需要反斜杠转义括号,因为除了]-\之外的其他字符在字符类中没有特殊含义。
  2. 模式.与换行符不匹配,这就是输入中的换行符不会产生错误消息的原因。实际上,没有一个模式与换行符匹配,因此当您键入换行符时,将调用默认规则。默认规则等同于ECHO,bison定义为: fputs(yytext, yyout); (或fprintf(yyout, "%s", yytext);) 这就是您输入换行符时输出额外换行符的原因。

-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"
© www.soinside.com 2019 - 2024. All rights reserved.