Lex-yacc程序显示语法错误 [英] Lex - yacc program showing syntax error
问题描述
为了对输入执行算术运算,已编写了以下两个代码,但是它始终使我出现语法错误 这是lex程序
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];}
%%
这是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
可能是什么问题?
推荐答案
存在三个问题.
第一个问题是您的语法只能识别一个表达式:
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.
第二个问题是您的扫描仪实际上无法将换行符识别为END
令牌:
The second problem is that your scanner does not actually recognize a newline character as an END
token:
'\n' {return END;}
'不是(f)lex的特殊字符. (有关可接受的模式字符的完整列表,请参见 Flex手册. ),因此该规则正在查找三个字符:撇号,换行符和另一个撇号.如果提供该输入,则将获得预期"输出:
' 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
$
你想写的是
\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:
%{
#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();
}
更改:
- 我从flex输入中删除了所有单字符模式,因为它们都具有相同的效果:返回读取的单个字符.由于以下更改,其中包括换行符.
- 我更改了语法的开始形式,以便它显式查找换行符(而不是
END
)并接受任意数量的输入行. - 我从野牛输入中删除了
#include "y.tab.h"
,因为没有必要在解析器文件中包含解析器标头. - 我将
expr
的空生产移到了S
生产中,这样它就不会尝试打印空表达式的值. - 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.
Changes:
最后,您尝试在开始生产时明确识别END
令牌.这可能有效,但不建议这样做.
Finally, you attempt to explicitly recognize an END
token in your start production. That may work but it is not recommended.
Yacc/野牛通过添加看起来与您的规则S
完全一样的外部规则来自动扩充语法:它可以识别开始的非终结符,后跟END
.因此,无需添加自己的作品.
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.
这篇关于Lex-yacc程序显示语法错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!