Yacc计算器括号和指数问题
Yacc Calculator Parenthesis and Exponent problems
几个小时以来,我一直在努力解决这个问题,最后我决定看看是否有人可以就我的这个问题提供一些意见。
我正在尝试扩展可以执行各种任务的 Yacc 计算器。剩下的两个正在识别括号并返回指数。我承认我对这个过程还很陌生,但据我所知,与我发现的许多例子相比,我没有做任何可怕的错误,所以我希望这是一个相当简单的问题。
%{
#include <stdio.h>
#include <ctype.h>
%}
%token NUMBER
%%
command : expr {printf("Answer is: %d\n",);}
;
expr : expr '-' term {$$=-;}
| expr '+' term {$$=+;}
| expr '*' term {$$=*;}
| expr '/' term {$$=/;}
| expr '%' term {$$=%;}
| expr '^' term {$$=,;}
| '(' term ')' term {$$=;}
| term {$$=;}
;
term : factor {$$=;}
;
factor : NUMBER {$$=;}
%%
main(){
return yyparse();
}
int yylex(void){
int character;
while((character=getchar())==' ');
if(isdigit(character)){
ungetc(character,stdin);
scanf("%d",&yylval);
return(NUMBER);
}
if(character=='\n'){
return(0);
}
return(character);
}
int yyerror(char * s){
fprintf(stderr,"%s\n",s);
return 0;
}
计算器相当简单,但我没有发现我的问题。代码编译没有问题,其他函数工作得很好。
如果有任何帮助,我将不胜感激!
EDIT/Addition
我不小心使用了错误的代码,我修复了它,并根据@rici 提供的建议添加了更新的代码。
此代码是新的且功能正常的代码。
%{
int yylex (void);
#include <stdio.h>
#include <ctype.h>
#include <math.h>
%}
%token NUMBER
%left '+' '-'
%left '*' '/'
%precedence NEG
%right '^'
%%
command : expr {printf("Answer is: %d\n",);}
;
expr : expr '-' term {$$=-;}
| expr '+' term {$$=+;}
| expr '*' term {$$=*;}
| expr '/' term {$$=/;}
| expr '%' term {$$=%;}
| '-' term %prec NEG {$$=-;}
| expr '^' term {$$=pow(,);}
| '(' expr ')' {$$=;}
| term {$$=;}
;
term : factor {$$=;}
;
factor : NUMBER {$$=;}
%%
main(){
return yyparse();
}
int yylex(void){
int character;
while((character=getchar())==' ');
if(isdigit(character)){
ungetc(character,stdin);
scanf("%d",&yylval);
return(NUMBER);
}
if(character=='\n'){
return(0);
}
return(character);
}
int yyerror(char * s){
fprintf(stderr,"%s\n",s);
return 0;
}
我不知道你的求幂问题是什么(而且你根本没有描述问题)除了你需要
#include <math.h>
如果您要使用 pow
。您还需要将 -lm
添加到编译命令中。由于您不包括数学 header,编译器将假设 pow
采用 int
参数并产生 int
结果,当然不是这种情况。除非您的编译器执行类似自动包含数学函数的操作(这对我来说似乎不太可能),否则将导致 pow
中的 return 值变得毫无意义。所以这可能是 pow
.
的问题
括号的问题似乎更清楚一些。你的语法是:
expr: ... | '(' term ')' term | ...
这意味着“写 expr
的一种可能方法是写一个左括号,然后是 term
,然后是右括号,然后是另一个 term
.(换句话说,语法就是它们看起来的样子。没有魔法或微妙之处。)
因为 term
只是 factor
而 factor
只是 NUMBER
,term
只能是一个数字,你的括号规则允许 expr
例如,
( 42 ) 63
但它不允许 (42)
,更不用说 (42+63)
。所以这不太可能是你想要的。
您的计算器似乎也没有任何运算符优先级,因此它会将 2+4*3 计算为 18,而不是 14。也许您不介意,但这有点不合常规。
Bison manual 中有一系列示例计算器。示例代码本身是 bison 分布的一部分,手册文本试图解释如何解释 bison 输入。第二个示例是带有括号和求幂的标准计算器——基本上就是您要实现的。
几个小时以来,我一直在努力解决这个问题,最后我决定看看是否有人可以就我的这个问题提供一些意见。
我正在尝试扩展可以执行各种任务的 Yacc 计算器。剩下的两个正在识别括号并返回指数。我承认我对这个过程还很陌生,但据我所知,与我发现的许多例子相比,我没有做任何可怕的错误,所以我希望这是一个相当简单的问题。
%{
#include <stdio.h>
#include <ctype.h>
%}
%token NUMBER
%%
command : expr {printf("Answer is: %d\n",);}
;
expr : expr '-' term {$$=-;}
| expr '+' term {$$=+;}
| expr '*' term {$$=*;}
| expr '/' term {$$=/;}
| expr '%' term {$$=%;}
| expr '^' term {$$=,;}
| '(' term ')' term {$$=;}
| term {$$=;}
;
term : factor {$$=;}
;
factor : NUMBER {$$=;}
%%
main(){
return yyparse();
}
int yylex(void){
int character;
while((character=getchar())==' ');
if(isdigit(character)){
ungetc(character,stdin);
scanf("%d",&yylval);
return(NUMBER);
}
if(character=='\n'){
return(0);
}
return(character);
}
int yyerror(char * s){
fprintf(stderr,"%s\n",s);
return 0;
}
计算器相当简单,但我没有发现我的问题。代码编译没有问题,其他函数工作得很好。
如果有任何帮助,我将不胜感激!
EDIT/Addition
我不小心使用了错误的代码,我修复了它,并根据@rici 提供的建议添加了更新的代码。
此代码是新的且功能正常的代码。
%{
int yylex (void);
#include <stdio.h>
#include <ctype.h>
#include <math.h>
%}
%token NUMBER
%left '+' '-'
%left '*' '/'
%precedence NEG
%right '^'
%%
command : expr {printf("Answer is: %d\n",);}
;
expr : expr '-' term {$$=-;}
| expr '+' term {$$=+;}
| expr '*' term {$$=*;}
| expr '/' term {$$=/;}
| expr '%' term {$$=%;}
| '-' term %prec NEG {$$=-;}
| expr '^' term {$$=pow(,);}
| '(' expr ')' {$$=;}
| term {$$=;}
;
term : factor {$$=;}
;
factor : NUMBER {$$=;}
%%
main(){
return yyparse();
}
int yylex(void){
int character;
while((character=getchar())==' ');
if(isdigit(character)){
ungetc(character,stdin);
scanf("%d",&yylval);
return(NUMBER);
}
if(character=='\n'){
return(0);
}
return(character);
}
int yyerror(char * s){
fprintf(stderr,"%s\n",s);
return 0;
}
我不知道你的求幂问题是什么(而且你根本没有描述问题)除了你需要
#include <math.h>
如果您要使用 pow
。您还需要将 -lm
添加到编译命令中。由于您不包括数学 header,编译器将假设 pow
采用 int
参数并产生 int
结果,当然不是这种情况。除非您的编译器执行类似自动包含数学函数的操作(这对我来说似乎不太可能),否则将导致 pow
中的 return 值变得毫无意义。所以这可能是 pow
.
括号的问题似乎更清楚一些。你的语法是:
expr: ... | '(' term ')' term | ...
这意味着“写 expr
的一种可能方法是写一个左括号,然后是 term
,然后是右括号,然后是另一个 term
.(换句话说,语法就是它们看起来的样子。没有魔法或微妙之处。)
因为 term
只是 factor
而 factor
只是 NUMBER
,term
只能是一个数字,你的括号规则允许 expr
例如,
( 42 ) 63
但它不允许 (42)
,更不用说 (42+63)
。所以这不太可能是你想要的。
您的计算器似乎也没有任何运算符优先级,因此它会将 2+4*3 计算为 18,而不是 14。也许您不介意,但这有点不合常规。
Bison manual 中有一系列示例计算器。示例代码本身是 bison 分布的一部分,手册文本试图解释如何解释 bison 输入。第二个示例是带有括号和求幂的标准计算器——基本上就是您要实现的。