yacc:区分整数和浮点数

mas*_*ief 5 yacc compiler-theory

我应该写一个程序来做 2 + 2 = 4 和 2.2 + 2 = 4.2。

我已经这样做了,因此它将所有内容都视为浮点数,但这是“错误的”。我必须区分它们。这是我到目前为止所拥有的:

%{
#include <stdio.h>
#include <ctype.h>
%}

%token <dval> FLOAT
%token <ival> INTEGER

%union
{
   float dval;
   int ival;
}

%type <dval> command exp term factor

%%

command : exp           {printf("%f\n",$1);}
    ;

exp : exp '+' term      {$$ = $1 + $3;}
    | exp '-' term      {$$ = $1 - $3;}
    | term          {$$ = $1;}
    ;

term    : term '*' factor   {$$ = $1 * $3;}
    | factor        {$$ = $1;}
    ;

factor : '(' exp ')'        {$$ = $2;}
    | FLOAT         {$$ = $1;}
    | INTEGER       {$$ = $1;}
    ;

%% 

int main()
{ 
  return yyparse();
}

int yylex()
{
   int c;
   while( (c=getchar()) == ' ');
   if( isdigit(c) )
   {
      ungetc(c, stdin);
      float f1;
      scanf("%f", &f1);
      int i1 = (int) f1;
      if(f1 == 0)
      {
         yylval.ival = 0;
     return INTEGER;
      }
      else if( (((float) i1) / f1 ) == 1)
      {
     yylval.ival = i1;
         return INTEGER;
      }
      else
      {
     yylval.dval = f1;
     return FLOAT;
      }
      //scanf("%f",&yylval.dval);
      //return(NUMBER);
   }
   if(c == '\n') return 0;
   return c;
}

int yyerror(char *s)
{
   fprintf(stderr,"%s\n",s);
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

我的问题是每个表达式只能有 1 种类型。现在一切基本上都是浮动的,所以虽然操作是正确的,但这不是正确的解决方案。

我想定义更多的表达式,基本上有 factor_int 和 factor_float,然后替换其中的所有内容,但这似乎是错误的。我不知道如何完成这项工作,而且我看到的教程并没有真正帮助我。

Jac*_*ack 2

基本上你可以做这样的事情:

%{
#include <stdio.h>
#include <ctype.h>

struct number
{
  union
  {
    int ival;
    float fval;
  }
  char type;
}

char INT_TYPE = 1;
char FLOAT_TYPE = 2;

%}

%union
{
   struct number value;
}

%token <value> FLOAT INTEGER command exp term factor

int yylex()
{
   ...
   if(f1 == 0)
   {
     yylval.value.type = INT_TYPE;
     yylval.value.ival = 0
   }
   ...
}
Run Code Online (Sandbox Code Playgroud)

等等..

通过这种方式,您可以在减少规则时检查操作数,确保生成新的正确类型..例如:

exp : exp '+' term {
   if ($1.type == INT_TYPE && $3.type == INT_TYPE)
   {
      $$.type = INT_TYPE;
      $$.ival = $1.ival + $3.ival;
   }
   else if ($1.type == INT_TYPE && $3.type == FLOAT_TYPE)
   {
      // this is a sort of implicit conversion to float
      $$.type = FLOAT_TYPE; 
      $$.fval = $1.ival + $3.fval;
   }
   // and so on

}
Run Code Online (Sandbox Code Playgroud)

附言。我用 Flex+Bison 做了类似的事情,我不知道 Lex+Yacc 是否支持所有内容,但我认为是的。