0
votes

I'm begginer to Yacc programming and I have an easy task to write a program, which checks whether an input text file contains a sequence of correctly paired parentheses. Any incorrect sequence should be signaled as "Syntax error!". I use bison and flex.

Example correct data: (()()((())())()) but (() is incorrect.

My problem is that I think it should work, but it seems like yyerror is not working. Maybe I'm doing something wrong, please correct me. Here's my code Yacc code:

 %{
int yylex();
void yyerror(char* x);
%}
%%
S: S A
 |A
 ;
A: '('S')'
  |'(' ')'
  ;

And the lex code:

%{
#include "y.tab.h"
%}
%%
[\(\)] return(yytext[0]);
. {printf("%c - error!\n",yytext[0]);}

%%
void yyerror(char* x)
{
    printf("syntax error");
    exit(1);
}

So the problem is that it doesn't fire a syntax error, it doesn't matter how much parentheses I write. edit: Here's how I compile it: screen

2
Don't print "syntax error". Print the error you are provided with.user207421
It is not the problem, because the exit(1) also doesn't work. It doesn't enter the yyerror methodFilip Matuszczak
That's why I posted it as a comment, not an answer. It remains wrong.user207421

2 Answers

1
votes

You need to provide a main() function which (at the minimum) calls yyparse(). Otherwise, the main from libfl will be used. That main does not call yyparse(); rather, it repeatedly calls yylex until an EOF is signalled. (libfl is part of Flex, not bison, so it cannot rely on yyparse even existing.)

There is really no need to link with -lfl. The main() definition there is not useful to you and the only other thing in the library is a dummy definition of yywrap(). You don't define yywrap(), so the library function will be called; however, rather than depending on the library, you could simply add

%option noyywrap

to your flex code (just before the %%), and then the generated scanner will not call yywrap().

There is also no need to use the -y flag when you invoke bison. The only reason to use -y is to be able to process legacy yacc files with bison. I suppose you are using the flag so that that generated parser is called y.tab.c; without the flag, it would be called z5.tab.c (and the header file will be z5.tab.h); you could just use those names. (Or you could tell bison the precise filename you would like it to use, by using the -o flag.)

Finally, two notes about your lex file:

  1. The pattern for parentheses could just be written:

    [()]  { return yytext[0]; }
    

    There is no need to backslash-escape parentheses inside a character class, because no characters other than ], - and \ have special meaning inside a character class.

  2. The pattern . does not match a newline character, which is why the newline characters in your input are not producing error messages. In fact, none of your patterns match the newline character, so when you type a newline, the default rule is invoked. The default rule is equivalent to ECHO, which bison defines to be something like:

    fputs(yytext, yyout);
    

    (or fprintf(yyout, "%s", yytext);)

    That's why an extra newline is output when you type a newline.

-1
votes

So the proper code for lex is:

%{
#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);
}

and the proper way to compile it is:

flex s5.l 
bison -d z5.y 
gcc lex.yy.c z5.tab.c -L"C:\GnuWin32\lib"