如何在YACC中编写属性语法?

如何在YACC中编写属性语法?,yacc,Yacc,我现在开始学习YACC。我只是想知道如何在YACC中编写属性语法。请举例说明。我们可以使用union吗?网络上有很多yacc语法的例子。一个简单的谷歌搜索会带来很多链接。还有很多有用的链接网上有很多yacc语法的例子。一个简单的谷歌搜索会带来很多链接。还有一些有用的链接是的,您可以将属性与解析树中的节点相关联。每个节点都有一个单独的属性,即“美元说明符”。 下面是一个示例,其中属性用于表达式的值: expression : expression '+' expression { $$ = $1

我现在开始学习YACC。我只是想知道如何在YACC中编写属性语法。请举例说明。我们可以使用union吗?

网络上有很多yacc语法的例子。一个简单的谷歌搜索会带来很多链接。还有很多有用的链接

网上有很多yacc语法的例子。一个简单的谷歌搜索会带来很多链接。还有一些有用的链接

是的,您可以将属性与解析树中的节点相关联。每个节点都有一个单独的属性,即“美元说明符”。 下面是一个示例,其中属性用于表达式的值:

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
    } ;