Bison Parser:打印令牌中的麻烦

时间:2017-01-18 23:03:36

标签: c bison yacc

我已经做了一些更改,我尝试将$$更改为$ 2但我仍然有错误因为我不认识T_NUM和T_STR,并且它显示错误: $$ linha'没有声明的类型

bison -d -o gram.c pro.y:

pro.y:45.32-33: erro: $$ linha Does not have a declared type
 linha: ESCREVER lista ';' { if($$.u.type==T_STR){
                                ^^
pro.y:46.48-49: erro: $$ de linha Does not have a declared type
                                printf("[%s]\n",$$.u.str);
                                                ^^
pro.y:49.43-44: erro: $$  linha Does not have a declared type
                                    assert($$.u.type==T_NUM);
                                           ^^
pro.y:50.50-51: erro: $$ linha Does not have a declared type
                                    printf("%d\n",$$.u.num);
                                                  ^^
Makefile:9: recipe for target 'gram.c' failed
make: *** [gram.c] Error 1

野牛/ yacc代码(更新)

%{

  #include <stdio.h>
  #include "pro.h"
  int yylex(void);
  int yyerror(const char *s);
%}

%code requires
{
enum TokenType{ T_STR ,T_NUM };

}

%union{

  struct token{

    enum TokenType type;
    union{ char *str;
          int num;
         };
               }u;
      }


%token TERMINAR ESCREVER
%token SUBTRACAO 
%token MULTIPLICACAO 
%token DIVISAO 
%token SOMA
%token<u.num> NUM 
%token<u.str> TEXTO 
%type<u> elemento
%type<u.num> expr 
%type<u> lista
%start s

%%

s:linha s
 |TERMINAR ';' {return 0;}
 ;

linha: ESCREVER lista ';' { if($$.u.type==T_STR){
                               printf("[%s]\n",$$.u.str);
                                                } 
                            else{
                                   assert($$.u.type==T_NUM);
                                   printf("%d\n",$$.u.num);


                                        }}
     | VARS
     ;

lista: elemento { $$=$1; }
     | lista ',' elemento 
     ;

elemento:TEXTO { $<u.str>$=$1;}
        |expr  { $<u.num>$=$1;}
        ;





VARS :
     | NUM 
     | TEXTO
     | expr
     | TEXTO '=' VARS ';' /* para delcaracoes */
     ;



expr     : NUM  SOMA expr                {$$=$1+$3;}
         | NUM  SUBTRACAO expr           {$$=$1-$3;}
         | NUM  MULTIPLICACAO expr       {$$=$1*$3;}
         | NUM  DIVISAO expr             {$$=$1/$3;}
     | NUM  '+' expr                 {$$=$1+$3;}
         | NUM  '=' expr                 {$$=$1=$3;}
         | NUM  '-' expr                  {$$=$1-$3;}
         | NUM  '*' expr                 {$$=$1*$3;}
         | NUM  '/' expr                  {$$=$1/$3;}
         | NUM                           {$$=$1;   }
         ;             


%%

1 个答案:

答案 0 :(得分:2)

您需要能够判断您是否有u.stru.num值才能使用 - 这通常是通过添加标记来指示您拥有的值。因此,您可能在结构中有一个u.type元素,并且您可以将其设置为T_STRT_NUM(可能是枚举中的值),然后您就可以执行此操作:

if ($$.u.type == T_STR)
    printf("str: [%s]\n", $$.u.str);
else
{
    assert($$.u.type == T_NUM);  // Make sure it gets changed with more types
    printf("num: %d\n", $$.u.num);
}

事实上,你可能会将其纳入一个函数中;能够按需转储结构通常很有用。您需要考虑结构是否应该有标签,以便您可以更轻松地引用该类型。

%{
enum TokenType { T_STR, T_NUM };
%}

%union {

   struct token
   {
       enum TokenType type;
       union
       {
           char *str;
           int   num;
       };
   } u;
}

这使用在C11中添加的匿名联合类型。您现在可以将struct token *传递给适当打印数据的函数。