问题
The following two codes have been written in order to perform arithmetic operations on input , but it gives me syntax error all the time Here is the lex program
%{
#include "y.tab.h"
#include <stdlib.h>
%}
%%
[0-9]+ {yylval = atoi(yytext);return ID;}
[*-+/()] {return yytext[0];}
'\n' {return END;}
. {return yytext[0];}
%%
Here is the yacc program :
%{
#include <stdio.h>
#include <stdlib.h>
#include "y.tab.h"
%}
%token ID END
%%
S: expr END { printf("Answer is : %d\n",$$); exit(1); }
expr: ID
|
| expr '+' expr { $$ = $1+$3;}
| expr '-' expr { $$ = $1-$3;}
| expr '*' expr { $$ = $1*$3;}
| expr '/' expr { $$ = $1/$3;}
| '(' expr ')' {$$ = $2;}
;
%%
int main()
{
yyparse();
}
Output:
2+3
2+3
Syntax error
What could the problem be ?
回答1:
There are three problems.
The first problem is that your grammar only recognizes a single expression:
S: expr END { printf("Answer is : %d\n",$$); exit(1); }
So if you enter two expressions, there is a syntax error.
The second problem is that your scanner does not actually recognize a newline character as an END
token:
'\n' {return END;}
' is not a special character for (f)lex. (See the Flex manual for a complete list of accepted pattern characters.) So that rule is looking for three characters: an apostrophe, a newline, and another apostrophe. If you provide that input, you will get the "expected" output:
$ ./badexpr
2+3'
'
Answer is : 5
$
What you meant to write was
\n { return END; }
But that's probably not ideal either. That will return immediately after a single expression. A more interesting grammar would allow for any number of expressions:
file.l
%{
#include <stdlib.h>
#include "y.tab.h"
%}
%%
[0-9]+ {yylval = atoi(yytext);return ID;}
.|\n {return yytext[0];}
file.y
%{
#include <stdio.h>
#include <stdlib.h>
%}
%token ID
%%
S: /* %empty */
| S expr '\n' { printf("Answer is : %d\n",$2); }
| S '\n'
expr: ID
| expr '+' expr { $$ = $1+$3;}
| expr '-' expr { $$ = $1-$3;}
| expr '*' expr { $$ = $1*$3;}
| expr '/' expr { $$ = $1/$3;}
| '(' expr ')' {$$ = $2;}
;
%%
int main()
{
yyparse();
}
Changes:
- I removed all of the single-character patterns from the flex input because they all have the same effect: return the single character read. That includes the newline character, because of the following change.
- I changed the start production for the grammar so that it looks for a newline character explicitly (rather than
END
) and accepts any number of input lines. - I removed the
#include "y.tab.h"
from the bison input because it is not necessary to include the parser header in the parser file. - I moved the empty production for
expr
into theS
production so that it does not attempt to print the value of an empty expression.
Finally, you attempt to explicitly recognize an END
token in your start production. That may work but it is not recommended.
Yacc/bison automatically augment your grammar by adding an outer rule which looks precisely like your rule S
: it recognizes the start non-terminal followed by END
. So adding your own production is unnecessary.
来源:https://stackoverflow.com/questions/42089664/lex-yacc-program-showing-syntax-error