c语言 - 带有野牛和柔性的计算不起作用操作负数



我对这个野牛程序有问题。我不知道为什么重用不起作用。对于负数的操作,我只是使用相同的行来获取第一个数字并使用更多操作进行操作。我只是将第一个数字更改为负数。

calc.y

%{
#include <stdio.h>
#include <stdlib.h>
extern int yylex();
extern int yyparse();
extern FILE* yyin;
void yyerror(const char* s);
%}
%union {
    int ival;
    float fval;
}
%token<ival> T_INT
%token<fval> T_FLOAT
%token T_PLUS T_MINUS T_MULTIPLY T_DIVIDE T_LEFT T_RIGHT
%token T_NEWLINE T_QUIT
%left T_PLUS T_MINUS
%left T_MULTIPLY T_DIVIDE
%type<ival> expression
%type<fval> mixed_expression
%start calculation
%%
calculation: 
       | calculation line
;
line: T_NEWLINE
    | mixed_expression T_NEWLINE { printf("tResult: %fn", $1);}
    | expression T_NEWLINE { printf("tResult: %in", $1); } 
    | T_QUIT T_NEWLINE { printf("bye!n"); exit(0); }
;
mixed_expression: T_FLOAT                        { $$ = $1; }
      | T_MINUS T_FLOAT  { $$ = -$2; }    
      | mixed_expression T_PLUS mixed_expression     { $$ = $1 + $3; }
      | mixed_expression T_MINUS mixed_expression    { $$ = $1 - $3; }
      | mixed_expression T_MULTIPLY mixed_expression { $$ = $1 * $3; }
      | mixed_expression T_DIVIDE mixed_expression   { $$ = $1 / $3; }
      | T_LEFT mixed_expression T_RIGHT      { $$ = $2; }
      | T_MINUS mixed_expression T_RIGHT         { $$ = -$2; }
      | expression T_PLUS mixed_expression       { $$ = $1 + $3; }
      | expression T_MINUS mixed_expression      { $$ = $1 - $3; }
      | expression T_MULTIPLY mixed_expression   { $$ = $1 * $3; }
      | expression T_DIVIDE mixed_expression     { $$ = $1 / $3; }
      | mixed_expression T_PLUS expression       { $$ = $1 + $3; }
      | mixed_expression T_MINUS expression      { $$ = $1 - $3; }
      | mixed_expression T_MULTIPLY expression   { $$ = $1 * $3; }
      | mixed_expression T_DIVIDE expression     { $$ = $1 / $3; }
      | expression T_DIVIDE expression       { $$ = $1 / (float)$3; }
;
expression: T_INT               { $$ = $1; }
      | expression T_PLUS expression    { $$ = $1 + $3; }
      | expression T_MINUS expression   { $$ = $1 - $3; }
      | expression T_MULTIPLY expression    { $$ = $1 * $3; }
      | T_LEFT expression T_RIGHT       { $$ = $2; }
      | T_MINUS T_INT   { $$ = -$2; }
;
%%
int main() {
    yyin = stdin;
    do { 
        yyparse();
    } while(!feof(yyin));
    return 0;
}
void yyerror(const char* s) {
    fprintf(stderr, "Parse error: %sn", s);
    exit(1);
}

calclex.l

%option noyywrap
%{
#include <stdio.h>
#define YY_DECL int yylex()
#include "calc.tab.h"
%}
%%
[ t]   ; // ignore all whitespace
[0-9]+.[0-9]+  {yylval.fval = atof(yytext); return T_FLOAT;}
[0-9]+      {yylval.ival = atoi(yytext); return T_INT;}
n      {return T_NEWLINE;}
"+"     {return T_PLUS;}
"-"     {return T_MINUS;}
"*"     {return T_MULTIPLY;}
"/"     {return T_DIVIDE;}
"("     {return T_LEFT;}
")"     {return T_RIGHT;}
"exit"      {return T_QUIT;}
"quit"      {return T_QUIT;}
%%

正如我在评论中所说,这个问题被称为"一元减号",它描述了将正常的减法运算a - b与否定运算区分开来的麻烦,0 - a如果它缩写为 -a .常见的解决方案是添加一些代码,使减号根据位置充当两个不同的运算符。它是在Bison中通过实现不存在符号的优先级来完成的(此处NEG(,并将该优先级绑定到大小写-a

您需要在代码中执行此操作两次,一次用于T_FLOAT,第二次用于T_INT。我还删除了一行毫无意义的行,至少对我来说是这样。

calc.y

%{
#include <stdio.h>
#include <stdlib.h>
extern int yylex();
extern int yyparse();
extern FILE* yyin;
void yyerror(const char* s);
%}
%union {
    int ival;
    float fval;
}
%token<ival> T_INT
%token<fval> T_FLOAT
%token T_PLUS T_MINUS T_MULTIPLY T_DIVIDE T_LEFT T_RIGHT
%token T_NEWLINE T_QUIT
%left T_PLUS T_MINUS
%left T_MULTIPLY T_DIVIDE
%precedence NEG   /* unary minus */
%type<ival> expression
%type<fval> mixed_expression
%start calculation
%%
calculation: 
       | calculation line
;
line: T_NEWLINE
    | mixed_expression T_NEWLINE { printf("tResult: %fn", $1);}
    | expression T_NEWLINE       { printf("tResult: %in", $1); } 
    | T_QUIT T_NEWLINE           { printf("bye!n"); exit(0); }
;
mixed_expression: T_FLOAT                            { $$ = $1; }
      | T_MINUS mixed_expression %prec NEG           { $$ = -$2; }    
      | mixed_expression T_PLUS mixed_expression     { $$ = $1 + $3; }
      | mixed_expression T_MINUS mixed_expression    { $$ = $1 - $3; }
      | mixed_expression T_MULTIPLY mixed_expression { $$ = $1 * $3; }
      | mixed_expression T_DIVIDE mixed_expression   { $$ = $1 / $3; }
      | T_LEFT mixed_expression T_RIGHT              { $$ = $2; }
      /* | T_MINUS mixed_expression T_RIGHT             { $$ = -$2; } */
      | expression T_PLUS mixed_expression           { $$ = $1 + $3; }
      | expression T_MINUS mixed_expression          { $$ = $1 - $3; }
      | expression T_MULTIPLY mixed_expression       { $$ = $1 * $3; }
      | expression T_DIVIDE mixed_expression         { $$ = $1 / $3; }
      | mixed_expression T_PLUS expression           { $$ = $1 + $3; }
      | mixed_expression T_MINUS expression          { $$ = $1 - $3; }
      | mixed_expression T_MULTIPLY expression       { $$ = $1 * $3; }
      | mixed_expression T_DIVIDE expression         { $$ = $1 / $3; }
      | expression T_DIVIDE expression               { $$ = $1 / (float)$3; }
;
expression: T_INT                                    { $$ = $1; }
      | expression T_PLUS expression                 { $$ = $1 + $3; }
      | expression T_MINUS expression                { $$ = $1 - $3; }
      | expression T_MULTIPLY expression             { $$ = $1 * $3; }
      | T_LEFT expression T_RIGHT                    { $$ = $2; }
      | T_MINUS expression  %prec NEG                { $$ = -$2; }
;
%%
int main() {
    yyin = stdin;
    do { 
        yyparse();
    } while(!feof(yyin));
    return 0;
}
void yyerror(const char* s) {
    fprintf(stderr, "Parse error: %sn", s);
    exit(1);
}

文件calclex.l可以保持不变(尽管浮点数有点复杂(。

最新更新