为了对输入执行算术运算,已经编写了以下两个代码,但它始终给出了语法错误 这是lex程序
%{
#include "y.tab.h"
#include <stdlib.h>
%}
%%
[0-9]+ {yylval = atoi(yytext);return ID;}
[*-+/()] {return yytext[0];}
'\n' {return END;}
. {return yytext[0];}
%%
这是yacc计划:
%{
#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();
}
输出:
2+3
2+3
Syntax error
问题是什么?
答案 0 :(得分:0)
有三个问题。
第一个问题是你的语法只能识别一个表达式:
S: expr END { printf("Answer is : %d\n",$$); exit(1); }
因此,如果输入两个表达式,则会出现语法错误。
第二个问题是您的扫描程序实际上并未将换行符识别为END
令牌:
'\n' {return END;}
&#39; 不是(f)lex的特殊字符。 (有关已接受模式字符的完整列表,请参阅Flex manual。)因此该规则正在查找三个字符:撇号,换行符和另一个撇号。如果您提供该输入,您将得到&#34;期望&#34;输出:
$ ./badexpr
2+3'
'
Answer is : 5
$
你打算写的是
\n { return END; }
但这可能也不理想。这将在单个表达式后立即返回。一个更有趣的语法将允许任意数量的表达式:
%{
#include <stdlib.h>
#include "y.tab.h"
%}
%%
[0-9]+ {yylval = atoi(yytext);return ID;}
.|\n {return yytext[0];}
%{
#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();
}
END
)并接受任意数量的输入行。#include "y.tab.h"
,因为没有必要在解析器文件中包含解析器头。expr
的空制作品移到S
制作中,以便它不会尝试打印空表达式的值。最后,您尝试在初始制作中明确识别END
令牌。这可能有效,但不建议这样做。
Yacc / bison通过添加外观规则自动增加您的语法,该规则看起来与您的规则S
完全相同:它识别起始非终端,后跟END
。因此,添加自己的作品是不必要的。