首页 > 解决方案 > Yacc 打印一个与指定变量不同的联合变量

问题描述

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

%{

#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($1.type) {
             printf("%d\n",$1.a);
           }
           else {
             printf("%f\n",$1.b);
           }
         }
         |
         LETTER '=' expr
         {
           if($3.type) {
             iregs[$1.a] = $3.a;
             type[$1.a] = 1;
           }
           else {
             dregs[$1.a] = $3.b;
             type[$1.a] = 0;
           }
         }
         ;
expr:    '(' expr ')'
         {
           $$ = $2;
         }
         |
         expr '*' expr
         {
           if($1.type && $3.type) { /* both integers */
             $$.a = $1.a * $3.a;
             $$.type = 1;
           }
           else if (!$1.type && !$1.type) { /* both doubles */
             $$.b = $1.b * $3.b;
             $$.type = 0;
           }
           else if ($1.type && !$3.type) { /* first integer second double */
             $$.b = $1.a * $3.b;
             $$.type = 0;
           }
           else { /* first double second integer */
             $$.b = $1.b * $3.a;
             $$.type = 0;
           }
         }
         |
         expr '/' expr
         {
           if($1.type && $3.type) { /* both integers */
             $$.a = $1.a / $3.a;
             $$.type = 1;
           }
           else if (!$1.type && !$1.type) { /* both doubles */
             $$.b = $1.b / $3.b;
             $$.type = 0;
           }
           else if ($1.type && !$3.type) { /* first integer second double */
             $$.b = $1.a / $3.b;
             $$.type = 0;
           }
           else { /* first double second integer */
             $$.b = $1.b / $3.a;
             $$.type = 0;
           }
         }
         |
         expr '%' expr
         {
           if($1.type && $3.type) { /* both integers */
             $$.a = $1.a % $3.a;
             $$.type = 1;
           }
           else { /* at least one double */
             yyerror("% is applied to integers only");
           }
         }
         |
         expr '+' expr
         {
           if($1.type && $3.type) { /* both integers */
             $$.a = $1.a + $3.a;
             $$.type = 1;
           }
           else if (!$1.type && !$1.type) { /* both doubles */
             $$.b = $1.b + $3.b;
             $$.type = 0;
           }
           else if ($1.type && !$3.type) { /* first integer second double */
             $$.b = $1.a + $3.b;
             $$.type = 0;
           }
           else { /* first double second integer */
             $$.b = $1.b + $3.a;
             $$.type = 0;
           }
         }
         |
         expr '-' expr
         {
           if($1.type && $3.type) { /* both integers */
             $$.a = $1.a - $3.a;
             $$.type = 1;
           }
           else if (!$1.type && !$1.type) { /* both doubles */
             $$.b = $1.b - $3.b;
             $$.type = 0;
           }
           else if ($1.type && !$3.type) { /* first integer second double */
             $$.b = $1.a - $3.b;
             $$.type = 0;
           }
           else { /* first double second integer */
             $$.b = $1.b - $3.a;
             $$.type = 0;
           }
         }
         |
         expr '&' expr
         {
           if($1.type && $3.type) { /* both integers */
             $$.a = $1.a & $3.a;
             $$.type = 1;
           }
           else { /* at least one double */
             yyerror("& is applied to integers only");
           }
         }
         |
         expr '|' expr
         {
           if($1.type && $3.type) { /* both integers */
             $$.a = $1.a | $3.a;
             $$.type = 1;
           }
           else { /* at least one double */
             yyerror("| is applied to integers only");
           }
         }
         |

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

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

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

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

int yywrap()
{
  return(1);
}

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

标签: compiler-constructionyacc

解决方案


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


推荐阅读