Bison Parser:打印令牌中的问题
Bison Parser: trouble in print token
我已经做了一些更改,我尝试将 $$ 更改为 $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
bison/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 { $$=; }
| lista ',' elemento
;
elemento:TEXTO { $<u.str>$=;}
|expr { $<u.num>$=;}
;
VARS :
| NUM
| TEXTO
| expr
| TEXTO '=' VARS ';' /* para delcaracoes */
;
expr : NUM SOMA expr {$$=+;}
| NUM SUBTRACAO expr {$$=-;}
| NUM MULTIPLICACAO expr {$$=*;}
| NUM DIVISAO expr {$$=/;}
| NUM '+' expr {$$=+;}
| NUM '=' expr {$$==;}
| NUM '-' expr {$$=-;}
| NUM '*' expr {$$=*;}
| NUM '/' expr {$$=/;}
| NUM {$$=; }
;
%%
您需要能够判断您是否有一个 u.str
或 u.num
值可以使用 — 这通常是通过添加一个标志来指示您有哪个来完成的。因此,您可能在结构中有一个 u.type
元素,并将其设置为 T_STR
或 T_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 *
传递到函数中以适当地打印数据。
我已经做了一些更改,我尝试将 $$ 更改为 $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
bison/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 { $$=; }
| lista ',' elemento
;
elemento:TEXTO { $<u.str>$=;}
|expr { $<u.num>$=;}
;
VARS :
| NUM
| TEXTO
| expr
| TEXTO '=' VARS ';' /* para delcaracoes */
;
expr : NUM SOMA expr {$$=+;}
| NUM SUBTRACAO expr {$$=-;}
| NUM MULTIPLICACAO expr {$$=*;}
| NUM DIVISAO expr {$$=/;}
| NUM '+' expr {$$=+;}
| NUM '=' expr {$$==;}
| NUM '-' expr {$$=-;}
| NUM '*' expr {$$=*;}
| NUM '/' expr {$$=/;}
| NUM {$$=; }
;
%%
您需要能够判断您是否有一个 u.str
或 u.num
值可以使用 — 这通常是通过添加一个标志来指示您有哪个来完成的。因此,您可能在结构中有一个 u.type
元素,并将其设置为 T_STR
或 T_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 *
传递到函数中以适当地打印数据。