如何在YACC中编写属性语法?
我现在开始学习YACC。我只是想知道如何在YACC中编写属性语法。请举例说明。我们可以使用union吗?网络上有很多yacc语法的例子。一个简单的谷歌搜索会带来很多链接。还有很多有用的链接网上有很多yacc语法的例子。一个简单的谷歌搜索会带来很多链接。还有一些有用的链接是的,您可以将属性与解析树中的节点相关联。每个节点都有一个单独的属性,即“美元说明符”。 下面是一个示例,其中属性用于表达式的值:如何在YACC中编写属性语法?,yacc,Yacc,我现在开始学习YACC。我只是想知道如何在YACC中编写属性语法。请举例说明。我们可以使用union吗?网络上有很多yacc语法的例子。一个简单的谷歌搜索会带来很多链接。还有很多有用的链接网上有很多yacc语法的例子。一个简单的谷歌搜索会带来很多链接。还有一些有用的链接是的,您可以将属性与解析树中的节点相关联。每个节点都有一个单独的属性,即“美元说明符”。 下面是一个示例,其中属性用于表达式的值: expression : expression '+' expression { $$ = $1
expression : expression '+' expression { $$ = $1 + $3; }
| expression '-' expression { $$ = $1 - $3; }
| NUMBER { $$ = $1; }
;
默认情况下,此单个属性是一个整数,但可以使用%union指令更改类型。不同类型的节点可以具有不同类型的属性。(这就是为什么它被称为%union,而不是类似于%type的东西。)如果需要多个属性,可以使用C结构或结构指针作为类型。是的,可以将属性与解析树中的节点相关联。每个节点都有一个单独的属性,即“美元说明符”。 下面是一个示例,其中属性用于表达式的值:
expression : expression '+' expression { $$ = $1 + $3; }
| expression '-' expression { $$ = $1 - $3; }
| NUMBER { $$ = $1; }
;
默认情况下,此单个属性是一个整数,但可以使用%union指令更改类型。不同类型的节点可以具有不同类型的属性。(这就是为什么它被称为%Union,而不是%1类。)如果你需要一个以上的属性,你可以使用C结构或结构指针作为类型。 < P>是的,你需要使用一些C++特性:对于AST树存储使用“符号”类集合,基于<代码> Sym < /C> >强>抽象<强>类。虚拟继承使您能够对STL容器和对象操作使用
Sym*
指针和dynamic_cast(o)
。对语法属性使用attr{}
map
完整(c)词法程序框架(c)源代码树请参见
如需了解答案,请参见上述语法,语法必须描述为
%defines %union { Sym*o; }
%token <o> NUMBER ADD SUB
%type <o> expression
expression : expression ADD expression {
// build AST node
$$=$2; $$->push($1); $$->push($3);
// synth .num attribute from nested nodes
$$->num = $1->num + $3->num ;
}
expression : expression SUB expression {
// build AST node
$$=$2; $$->push($1); $$->push($3);
// synth .num from nested nodes
$$->num = $1->num - $3->num ;
}
expression : NUMBER { $$=$1; } /* terminal should be used directly */
给树
<op:=> #0x5b1180
<sym:A> #0x5b1118
<op:+> #0x5b1348
<op:-> #0x5b11e8
1 #0x5b1250
num =
1 #0x5b12a8
<op:*> #0x4a07d8
<op:+> #0x5b13b0
2.3 #0x5b1418
num =
2.3 #0x5b1470
<op:^> #0x4a1090
4e-005 #0x4a1010
num =
4e-005 #0x4a1050
<op:/> #0x5bb730
num =
-0.0399165 #0x5bb850
<op:@> #0x5bb648
num =
-0.279415 #0x5bb6d0
<fn:sin> #0x5bb680
6 #0x5bb570
num =
6 #0x5bb5b0
7 #0x5bb768
num =
7 #0x5bb7a8
#0x5b1180
#0x5b1118
#0x5b1348
#0x5b11e8
1#0x5b1250
num=
1#0x5b12a8
#0x4a07d8
#0x5b13b0
2.3#0x5b1418
num=
2.3#0x5b1470
#0x4a1090
4e-005#0x4a1010
num=
4e-005#0x4a1050
#0x5bb730
num=
-0.0399165#0x5bb850
#0x5bb648
num=
-0.279415#0x5bb6d0
#0x5bb680
6#0x5bb570
num=
6#0x5bb5b0
7#0x5bb768
num=
7#0x5bb7a8
(*)回答:请注意属性语法关键字在静噪。
< P>是的,你需要使用一些C++特性:对于AST树存储使用“符号”类集合,基于<代码> Sym < /C> >强>抽象<强>类。虚拟继承使您能够对STL容器和对象操作使用Sym*
指针和dynamic_cast(o)
。对语法属性使用attr{}
map
完整(c)词法程序框架(c)源代码树请参见
如需了解答案,请参见上述语法,语法必须描述为
%defines %union { Sym*o; }
%token <o> NUMBER ADD SUB
%type <o> expression
expression : expression ADD expression {
// build AST node
$$=$2; $$->push($1); $$->push($3);
// synth .num attribute from nested nodes
$$->num = $1->num + $3->num ;
}
expression : expression SUB expression {
// build AST node
$$=$2; $$->push($1); $$->push($3);
// synth .num from nested nodes
$$->num = $1->num - $3->num ;
}
expression : NUMBER { $$=$1; } /* terminal should be used directly */
给树
<op:=> #0x5b1180
<sym:A> #0x5b1118
<op:+> #0x5b1348
<op:-> #0x5b11e8
1 #0x5b1250
num =
1 #0x5b12a8
<op:*> #0x4a07d8
<op:+> #0x5b13b0
2.3 #0x5b1418
num =
2.3 #0x5b1470
<op:^> #0x4a1090
4e-005 #0x4a1010
num =
4e-005 #0x4a1050
<op:/> #0x5bb730
num =
-0.0399165 #0x5bb850
<op:@> #0x5bb648
num =
-0.279415 #0x5bb6d0
<fn:sin> #0x5bb680
6 #0x5bb570
num =
6 #0x5bb5b0
7 #0x5bb768
num =
7 #0x5bb7a8
#0x5b1180
#0x5b1118
#0x5b1348
#0x5b11e8
1#0x5b1250
num=
1#0x5b12a8
#0x4a07d8
#0x5b13b0
2.3#0x5b1418
num=
2.3#0x5b1470
#0x4a1090
4e-005#0x4a1010
num=
4e-005#0x4a1050
#0x5bb730
num=
-0.0399165#0x5bb850
#0x5bb648
num=
-0.279415#0x5bb6d0
#0x5bb680
6#0x5bb570
num=
6#0x5bb5b0
7#0x5bb768
num=
7#0x5bb7a8
(*)回答:请注意静态中的属性语法关键字。我您更喜欢最简单的方法,是的,使用以下语法:: @ 此变体仍然构建带注释的AST树,但属性硬编码到类中。如果需要额外的属性,请使用虚拟继承,并手动跟踪属性树的有效性(根据生产规则)
%定义了%union{
结构AST{
字符串名;
双重价值;
虚拟字符串转储(int-depth=0);
向量嵌套;空推(Sym*);
}*节点;
}
/*令牌名称/值必须在lexer中填写*/
%令牌SYM NUM EQ ADD SUB MUL DIV POW LP RP
%ex型
//优先级降低到更高
%右均衡器
%左加副
%左多功能分区
%右PFX
%%
REPL:| REPL ex{cout dump()push($2);//一元运算符AST子树
$$->value=+$2->value;//+A
};
ex:SUB-ex%prec PFX{
$$=$1;$$->push($2);//一元运算符AST子树
$$->value=-$2->value;//-A
};
例:例加例{
$$=$2;$$->push($1);$$->push($3);//构建AST子树
$$->value=$1->value+$2->value;//不带密码的synth attr
} ;
ex:ex MUL-ex{
$$=$2;$$->push($1);$$->push($3);//构建AST子树
$$->value=$1->value*$2->value;//不带密码的synth attr
} ;
实际上,yacc-ng
应该支持%struct选项来像这样直接构建AST树,但是yacc
不能这样做,您应该将struct*
嵌套在%union
中,您更喜欢简单
%defines %union {
struct AST {
string name;
double value;
virtual string dump(int depth=0);
vector<AST*> nest; void push(Sym*);
} *node;
}
/* tokens name/value must be filled in lexer */
%token <node> SYM NUM EQ ADD SUB MUL DIV POW LP RP
%type <node> ex
// precedence down higher
%right EQ
%left ADD SUB
%left MUL DIV
%right PFX
%%
REPL : | REPL ex { cout << $2->dump() << endl } ;
ex : SYM { $$=$1; } ; // token as is
ex : NUM { $$=$1; } ; // token as is
ex : ADD ex %prec PFX {
$$=$1; $$->push($2); // unary operator AST subtree
$$->value = + $2->value; // + A
};
ex : SUB ex %prec PFX {
$$=$1; $$->push($2); // unary operator AST subtree
$$->value = - $2->value; // - A
};
ex : ex ADD ex {
$$=$2; $$->push($1); $$->push($3); // build AST subtree
$$->value = $1->value + $2->value; // synth attr without cryptic code
} ;
ex : ex MUL ex {
$$=$2; $$->push($1); $$->push($3); // build AST subtree
$$->value = $1->value * $2->value; // synth attr without cryptic code
} ;