Yacc 打印一个与指定的不同的联合变量

Yacc prints a different union variable than the one specified

我正在尝试在 flex/yacc 中实现一个也支持实数的计算器(我还没有实现)。但是出于某种原因,我的代码没有打印表达式的值,而是只打印了表达式的类型,即 1 表示整数。这是 flex 文件

%{

#include <stdio.h>
#include "y.tab.h"
int c;
%}
%%
" "       ;
[a-z]     {
            c = yytext[0];
            yylval.a = c - 'a';
            return(LETTER);
          }
[0-9]     {
            c = yytext[0];
            yylval.a = c - '0';
            return(DIGIT);
          }
[^a-z0-9\b]    {
                 c = yytext[0];
                 return(c);
              }
%%

这是 yacc 文件

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

int iregs[26];
double dregs[26];
char type[26];
int base = 10;

void yyerror(char*);
int yywrap();
int yyparse();
int yylex();
%}

%start list

%union 
{ 
  int a; 
  double b;
  char type; /* 0 for double , 1 for integer */
}


%token DIGIT LETTER

%left '|'
%left '&'
%left '+' '-'
%left '*' '/' '%'
%left UMINUS  /*supplies precedence for unary minus */

%%                   /* beginning of rules section */

list:                       /*empty */
         |
        list stat '\n'
         |
        list error '\n'
         {
           yyerrok;
         }
         ;
stat:    expr
         {
           if(.type) {
             printf("%d\n",.a);
           }
           else {
             printf("%f\n",.b);
           }
         }
         |
         LETTER '=' expr
         {
           if(.type) {
             iregs[.a] = .a;
             type[.a] = 1;
           }
           else {
             dregs[.a] = .b;
             type[.a] = 0;
           }
         }
         ;
expr:    '(' expr ')'
         {
           $$ = ;
         }
         |
         expr '*' expr
         {
           if(.type && .type) { /* both integers */
             $$.a = .a * .a;
             $$.type = 1;
           }
           else if (!.type && !.type) { /* both doubles */
             $$.b = .b * .b;
             $$.type = 0;
           }
           else if (.type && !.type) { /* first integer second double */
             $$.b = .a * .b;
             $$.type = 0;
           }
           else { /* first double second integer */
             $$.b = .b * .a;
             $$.type = 0;
           }
         }
         |
         expr '/' expr
         {
           if(.type && .type) { /* both integers */
             $$.a = .a / .a;
             $$.type = 1;
           }
           else if (!.type && !.type) { /* both doubles */
             $$.b = .b / .b;
             $$.type = 0;
           }
           else if (.type && !.type) { /* first integer second double */
             $$.b = .a / .b;
             $$.type = 0;
           }
           else { /* first double second integer */
             $$.b = .b / .a;
             $$.type = 0;
           }
         }
         |
         expr '%' expr
         {
           if(.type && .type) { /* both integers */
             $$.a = .a % .a;
             $$.type = 1;
           }
           else { /* at least one double */
             yyerror("% is applied to integers only");
           }
         }
         |
         expr '+' expr
         {
           if(.type && .type) { /* both integers */
             $$.a = .a + .a;
             $$.type = 1;
           }
           else if (!.type && !.type) { /* both doubles */
             $$.b = .b + .b;
             $$.type = 0;
           }
           else if (.type && !.type) { /* first integer second double */
             $$.b = .a + .b;
             $$.type = 0;
           }
           else { /* first double second integer */
             $$.b = .b + .a;
             $$.type = 0;
           }
         }
         |
         expr '-' expr
         {
           if(.type && .type) { /* both integers */
             $$.a = .a - .a;
             $$.type = 1;
           }
           else if (!.type && !.type) { /* both doubles */
             $$.b = .b - .b;
             $$.type = 0;
           }
           else if (.type && !.type) { /* first integer second double */
             $$.b = .a - .b;
             $$.type = 0;
           }
           else { /* first double second integer */
             $$.b = .b - .a;
             $$.type = 0;
           }
         }
         |
         expr '&' expr
         {
           if(.type && .type) { /* both integers */
             $$.a = .a & .a;
             $$.type = 1;
           }
           else { /* at least one double */
             yyerror("& is applied to integers only");
           }
         }
         |
         expr '|' expr
         {
           if(.type && .type) { /* both integers */
             $$.a = .a | .a;
             $$.type = 1;
           }
           else { /* at least one double */
             yyerror("| is applied to integers only");
           }
         }
         |

        '-' expr %prec UMINUS
         {
           if(.type) {
             $$.a = -.a;
             $$.type = 1;
           }
           else {
             $$.b = -.b;
             $$.type = 0;
           }
         }
         |
         LETTER
         {
           if(type[.a]) {
             $$.a = iregs[.a];
             $$.type = 1;
           }
           else {
             $$.b = dregs[.a];
             $$.type = 0;
           }
         }
         |
         integer
         {
           $$.a = .a;
           $$.type = 1;
         }
         ;

integer:  DIGIT
         {
           $$.a = .a;
         }       
         |
         integer DIGIT
         {
           $$.a = base * .a + .a;
         }
         ;

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

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

int yywrap()
{
  return(1);
}

因为我在我的测试文件中使用整数,所以无论我使用什么表达式,这段代码只打印 1,我不知道为什么。

每个标记和语法规则只能使用联合中的一个值,而不是整个联合作为一个结构。