使用两个以上的参数计算 min/max

Calculating min/max with more than two parameters

作为家庭作业,我们得到了一个只能做+运算的基本计算器,我们必须实现更多的功能。我们必须实现括号运算符、符号运算符和最小最大函数。最后一项任务是扩展 min/max 函数以使用两个以上的参数计算 min/max,这就是我目前遇到的任务。

我当前的 calc.l lex 文件:

%{
extern int yylval;
extern int sym[];
extern int yyerror(char *s);
#include "y.tab.h"
%}

%%

[a-z]   {
           yylval = *yytext - 'a';
           return VARIABLE;
        }

[0-9]+  {
           yylval = atoi(yytext);
           return INTEGER;
        }

[(),]   { return *yytext; }

":="    return ASSIGN;
"+"     return PLUS;
"-"     return MINUS;
"/"     return DIVIDE;
"%"     return MODULO;
"*"     return TIMES;
"<"     return SMAS;
"<="    return SMGAS;
"=="    return IS;
"!="    return NOTIS;
">="    return BGGAS;
">"     return BGAS;

"min"   return MIN;
"max"   return MAX;

"\n"    return NEWLINE;

[ \t]   ;

.       yyerror("Invalid character");

%%

int yywrap() {
 return 1;
}

我当前的 calc.y yacc 文件:

%{
#include <stdio.h>
int sym[26];
int yylex();
int yyerror(char *s);
%}

%token VARIABLE ASSIGN INTEGER NEWLINE
%left PLUS
%left TIMES
%left MINUS
%left DIVIDE
%left MODULO
%left UMINUS
%left UPLUS
%left SMAS SMGAS IS NOTIS BGAS BGGAS
%left MIN MAX

%%

program: program statement
       |
       ;

statement: expr NEWLINE
             { printf("%d\n", ); }
         | VARIABLE ASSIGN expr NEWLINE
             { sym[] = ; }
         ;

expr: INTEGER            { $$ = ; }
      | VARIABLE         { $$ = sym[]; }
      | expr PLUS expr   { $$ =  + ; }
      | expr TIMES expr  { $$ =  * ; }
      | expr MINUS expr  { $$ =  - ; }
      | expr DIVIDE expr { $$ =  / ; }
      | expr MODULO expr { $$ =  % ; }
      | '(' expr ')'     { $$ = ;      }

      | MINUS expr %prec UMINUS { $$ = -; }
      | PLUS expr %prec UPLUS { $$ = ; }

      | expr SMAS  expr   { $$ =  < ;  }
      | expr SMGAS expr   { $$ =  <= ; }
      | expr IS    expr   { $$ =  == ; }
      | expr NOTIS expr   { $$ =  != ; }
      | expr BGGAS expr   { $$ =  >= ; }
      | expr BGAS  expr   { $$ =  > ;  }

      | MIN '(' expr ',' expr ')' { if ( < ){ $$ = ; } else if ( > ){ $$ = ; }; }
      | MAX '(' expr ',' expr ')' { if ( > ){ $$ = ; } else if ( < ){ $$ = ; }; }

      ;

%%

int yyerror(char *s) {
  fprintf(stderr, "%s\n", s);
  return 0;
}

int main() {
  yyparse();
  return 0;
}

我认为一种解决方案是在 min/max 函数中用 , 分隔每个值并计算它,然后将其返回给 min/max 函数,但我不确定如何实施它。我能想到的唯一解决方案相当复杂。由于项目不应该那么复杂,我想我缺少一种简单的方法。

min(5, 6) returns 5 它应该是这样的,它应该如何工作的预期方式是 (min 6, 7, 3) 和 return 3 你可以扩展它有无数个参数。

你们有什么想法吗?

谢谢!

AIUI 你应该处理 min/max 的任意数量的参数。这样做的标准方法是

  • 首先将参数列表移动到单独的规则中,例如arg_list: expr ',' expr ; 并使 return 成为一个列表(类对象)。 min/max 的(子)规则然后根据 returned 列表进行计算。
  • 其次,通过使 arg_list 规则递归处理 1 到 n 个条目,类似于 expr 规则本身。 min/max 规则仍然需要根据列表进行计算,只需假设任意长度 >= 1,而不是长度 == 2。

您需要 max(x,y)max(x,y,z,q..)

一个可能的解决方案是 (... x , z ...) 可重复的,因此您将需要很少的规则。注意var,它是用来判断我们需要什么操作的。

expr ',' expr { if(var==1){$$=>?:;}else{$$=<?:;}; }
'(' expr ')' { $$ = ;}
MAX  expr    { $$ = ;}
MAX  expr    { $$ = ;}

在你的 *.l 文件中你需要外部变量(我们称之为 varextern int var

还为 maxmin 添加一个 redex 规则,这会将我们的变量设置为 1 或 0:

min { op =0;}
max { op =1;}

其中 1 是最大值,最小值是 0。

这是在 .l 文件中完成的,因为我们想在进行操作之前先设置 var

如果在.y文件中进行操作,var将在操作后设置。

也将变量添加到您的 *.y 文件 (int var =0)

.y 文件中,您 MAXMIN 应该是 %tokens。另外,在 first/second 位置添加 ,%right(您可以使用 COMMA 而不是 ,)。否则如果你有 ..4,5*5,.. if 将首先比较然后乘以它。