Bison 野牛-将值传递给下一个产品
我有一个上面给出的bison语法,我正试图使用这个语法为我的编程语言创建一个AST。此语法用于分析字段声明,例如:Bison 野牛-将值传递给下一个产品,bison,abstract-syntax-tree,Bison,Abstract Syntax Tree,我有一个上面给出的bison语法,我正试图使用这个语法为我的编程语言创建一个AST。此语法用于分析字段声明,例如: field_dec: type id_list ; id_list: ID punct id_list | ID SQUARE_OPEN INTEGER SQUARE
field_dec: type id_list ;
id_list: ID punct id_list
| ID SQUARE_OPEN INTEGER SQUARE_CLOSED punct id_list
| ID punct
| ID SQUARE_OPEN INTEGER SQUARE_CLOSED punct
;
type: INT | BOOLEAN
;
punct: COMMA | SEMICOLON
;
我想问的是,当“type”non-terminal的值到达产品id\u列表时,如何将其传递给bison解析器
我的意思是,当我在解析阶段处于id\u list
production时,我希望获得每个标识符的类型,因为我需要将其存储在identifier节点中。我知道我们可以将$
值传递给上层产品,但是如何将一些值传递给解析阶段中产品之后的产品
在发布问题后,我发现我们可以将$n
与n<0一起使用,但我在网上找不到任何好的资源来阅读它,并且我尝试用n<0测试$n
,但它只给了我以下错误:
int a;
int a, b, c[10], d;
int a[10];
及
与其使用右递归来定义id\u list
(这实际上从来都不是您想要的),不如使用左递归规则来实现所需的效果
在下面的语法中,与声明器关联的类型始终可用作声明器本身的语义值。我还纠正了标点符号的处理:只有逗号分隔标识符,只有分号终止声明
为了使类型始终可用,有必要对语法进行“非规范化”,这会导致一定程度的重复。请参见下面的稍微重构的版本
bison.y:124.43-45: error: $-1 of ‘callout_arg’ has no declared type
callout_arg: expr {printf("testing %s\n", $-1);}
^^^
为简单起见,我假设所有语义值都只是字符串,但实际上您可能需要表示“类型”和“标识符”的特定类型。此外,避免所有可能的声明符语法的过度重复也会更干净,因为可能有两种以上的可能性。这也可以通过使用自定义语义类型来实现
这里有一个稍微复杂一点的版本:
decl_list: type ID { assign_type($1, $2); }
| type ID '[' INTEGER ']' { assign_array_type($1, $2, $4); }
| decl_list ',' ID { assign_type($1, $3); }
| decl_list ',' ID '[' INTEGER ']'
{ assign_array_type($1, $3, $5};
field_dec: decl_list ';'
%{
#包括
枚举类型{布尔,整数};
结构声明器{
常量字符*id;
布尔矩阵;
整数维;
}
%}
%联合{
枚举类型;
结构声明器decl;
常量字符*id;
长数;
}
%{
/*通过引用传递语义值以避免复制,
因为结构声明器有点大。
*/
void从decl分配类型(常量字符**类型,
结构声明器*dec){
if(dec->is\u数组)
分配数组类型(*类型,dec->id,dec->维度);
其他的
分配类型(*类型,十二月->id);
}
%}
%令牌T_ID
%令牌T_整数
%令牌T_INT“INT”
T_布尔“布尔”
%类型decl\u列表
%类型声明符
%%
类型:“boolean”{$$=boolean;}
|“int”{$$=INTEGER;}
字段_dec:decl_list';'
decl_列表:类型声明符{assign_type(&$1,&$2);}
|decl_列表','声明符{assign_type(&$1,&$3);}
声明符:ID{$$.ID=$1;
$$.is_array=false;
}
|ID'['整数']'{$$。ID=$1;
$$.is_array=true;
$$。维度=$3;
}
如问题所示,可以使用堆栈“向上引用”来代替声明器结构的使用。在我看来,这些参考文献有点脆弱,因为它们依赖于关于生产可能发生的环境的全局知识,而bison并不验证其使用。缺少验证的一个结果是,在使用此类引用时必须指定语义类型标记,这一事实在bison手册中是隐式的,这就是为什么您从bison收到错误消息的原因
确保为语义操作正确配置堆栈是一件棘手的事情,通常需要使用标记产品(或中间规则操作)。以下示例改编自bison手册,添加了必要的显式类型语法:
%{
#include <stdbool.h>
enum Type {BOOLEAN, INTEGER};
struct Declarator {
const char* id;
bool is_array;
int dimension;
}
%}
%union {
enum Type type;
struct Declarator decl;
const char* id;
long number;
}
%{
/* Pass semantic values by reference to avoid copying,
since the struct Declarator is a bit big.
*/
void assign_type_from_decl(const char** typ,
struct Declarator* dec) {
if (dec->is_array)
assign_array_type(*typ, dec->id, dec->dimension);
else
assign_type(*typ, dec->id);
}
%}
%token <id> T_ID
%token <number> T_INTEGER
%token T_INT "int"
T_BOOLEAN "boolean"
%type <type> decl_list
%type <decl> declarator
%%
type : "boolean" { $$ = BOOLEAN; }
| "int" { $$ = INTEGER; }
field_dec: decl_list ';'
decl_list: type declarator { assign_type(&$1, &$2); }
| decl_list ',' declarator { assign_type(&$1, &$3); }
declarator: ID { $$.id = $1;
$$.is_array = false;
}
| ID '[' INTEGER ']' { $$.id = $1;
$$.is_array = true;
$$.dimension = $3;
}
%类型和表达式固定器
%%
总数:
expr保持器“+”expr{…}
|expr保持器'-'expr{…}
;
定金:
/*空*/{previous_expr=$0;}
;
您可以使用$0
或$-N
引用值堆栈上以前的值,不过您需要注意始终正确输入类型。在您的情况下,您可能需要以下内容:
%type <number> sum expr retainer
%%
sum:
expr retainer '+' expr { ... }
| expr retainer '-' expr { ... }
;
retainer:
/* empty */ { previous_expr = $<number>0; }
;
%类型
... 产品的其他类型声明
%%
字段_dec:type id_list';';
id_list:id_decl{$$=make_list($1);}
|id_list',{$$=$0;}id_decl{$$=append_list($1,$3);}
;
id_decl:id{$$=declare_id($1,$0;}
|ID“['整数']”
{$$=declare_id($1,get_数组_type($0,$3));}
;
类型:INT{$$=&INT_-type;}{$$=&bool_-type;}
字段定义列表:/*空*/|字段定义列表字段定义;
如果您使用,它有语法上的糖分使这更容易(和更安全的类型):
%类型
%类型id_decl()
%类型id_列表()
…其他产品的其他类型声明
%%
字段_dec:type id_list($1)';
id_list($t):id_decl($t){$$=make_list($1);}
|id_list($t)''id_decl($t){$=append_list($1,$3);}
;
id_decl($t):id{$$=declare_id($1,$t);}
|ID“['INTEGER']”{$$=declare_ID($1,get_array_type($t,$3));}
;
类型:INT{$$=&INT_-type;}{$$=&bool_-type;}
字段定义列表:/*空*/|字段定义列表字段定义;
你的语法看起来不正确。id\u列表
没有终止分支:每个id\u列表
后面都必须跟着另一个id\u列表
,即它是无限的。@melpomene是的,谢谢你,我完全错过了它。
%type <number> sum expr retainer
%%
sum:
expr retainer '+' expr { ... }
| expr retainer '-' expr { ... }
;
retainer:
/* empty */ { previous_expr = $<number>0; }
;
%type<type> type
... other type declarations for productions
%%
field_dec: type id_list ';' ;
id_list: id_decl { $$ = make_list($1); }
| id_list ',' { $<type>$ = $<type>0; } id_decl { $$ = append_list($1, $3); }
;
id_decl: ID { $$ = declare_id($1, $<type>0; }
| ID '[' INTEGER ']'
{ $$ = declare_id($1, get_array_type($<type>0, $3)); }
;
type: INT { $$ = &int_type; } | BOOLEAN { $$ = &bool_type; }
field_dec_list : /* empty */ | field_dec_list field_dec ;
%type<type> type
%type<???> id_decl(<type>)
%type<list> id_list(<type>)
... other type declarations for other productions
%%
field_dec: type id_list($1) ';' ;
id_list($t): id_decl($t) { $$ = make_list($1); }
| id_list($t) ',' id_decl($t) { $$ = append_list($1, $3); }
;
id_decl($t): ID { $$ = declare_id($1, $t); }
| ID '[' INTEGER ']' { $$ = declare_id($1, get_array_type($t, $3)); }
;
type: INT { $$ = &int_type; } | BOOLEAN { $$ = &bool_type; }
field_dec_list : /* empty */ | field_dec_list field_dec ;