编译器-语法制导翻译STD

Classic Expression Grammar :
0.Goal → Expr

1.Assign → ident = Expr;        //making Assign node
2.Expr → Expr + Term        //making plus node

3.             | Expr - Term        //making minus node

4.             | Term

5.Term → Term * Factor        //making Mult node

6.             | Term / Factor        //making div node

7.             | Factor

8.Factor → ident        //making ident node

9.                | num        //making num node

10.                | ( Expr )

x = a * 3 + b ;

扫描二维码关注公众号,回复: 16308031 查看本文章

parsing tree

 AST目的生成代码 所以本质上就是在parsing tree上剔除了多余的信息 但保留了原有的token信息和结构
AST:

load a → r1

load 3 → r2

Mult r1,r2 → r3

load b → r4

Add r3,r4 → r5

store r5 → x

yacc(Yet Another Compiler Compiler),是一个经典的生成语法分析器的工具。yacc生成的编译器主要是用C语言写成的语法解析器(Parser),需要与词法解析器Lex一起使用,再把两部份产生出来的C程序一并编译

GNU Bison 是一个通用的解析器生成器,它可以将注释的无上下文语法转换为使用 LALR (1) 解析表的确定性 LR 或广义 LR (GLR) 解析器。Bison 还可以生成 IELR (1) 或规范 LR (1) 解析表。一旦您熟练使用 Bison,您可以使用它开发广泛的语言解析器,从简单的桌面计算器中使用的解析器到复杂的编程语言。

Bison 与 Yacc 向上兼容:所有正确编写的 Yacc 语法都可以在 Bison 上正常使用。熟悉 Yacc 的任何人都应该可以轻松使用 Bison。

说白了 Yacc和Bison做的工作就是从一个语法和相关行为 即​​​​​​​                                                                   生成了closure ActionTable GotoTable 并最终生成了c code
所以他们是comilper-compiler 他们编译语法 生成的c code成了编译器的一个前端部分

 在Yacc和Bison中 使用$$表达左边 $num表达右边 比如上面的第五行 表示为
$$ → $1 $2 $3
$$ = MakingMultNode($1,$3)

 这一行只是把Term替换成Factor 不生成新的node 
$$ = $1

$本质上一个指向node的指针
MakingMultNode(Node * n1, Node * n2)
createNewNode n
n.left = n1
n.right = n2
return &n

也就是说 每次在LR(1)文法中执行reduce 7的时候 执行的其实是$$ = $1来生成AST


对于8 9 行这种置换成terminal的 
MakingIdentNode(token)
MakingNumNode(num)

cost(add) = 1
cost(sub) = 1
cost(mult) = 3
cost(div) = 7
cost(loadident) = 4
cost(store) = 3
cost(loadnum) = 1

0.Goal → Expr        //$$ = $1

1.Assign → ident = Expr;        //$$ = $3 + cost(store)
2.Expr → Expr + Term        //$$ =$1 +cost(add) + $3

3.             | Expr - Term        //$$ =$1 +cost(sub) + $3

4.             | Term        //$$ = $1

5.Term → Term * Factor        //$$ = $1 +cost(mult) + $3

6.             | Term / Factor        //$$ = $1 + cost(div) + $3

7.             | Factor        //$$ = $1

8.Factor → ident        //$$ = cost(loadident)

9.                | num        //$$ = cost(loadnum)

10.                | ( Expr )  //$$ = $2

 可以看到 cost of ident 是4 置换到Factor并不会再次cost 它们之间只是链接link的关系 最后传到Term也是4 同理num传到Factor是cost 1
最后Term作为$1 mult作为$2 Factor作为$3 它们的cost分别为 4 3 1 加起来是8 传给上面的$$
其他分支同理 

猜你喜欢

转载自blog.csdn.net/weixin_43754049/article/details/126321259
今日推荐