返回

编译器一日一练(DIY系列之复杂语法树)

发布时间:2023-09-22 15:13:51 270


        代码地址:​​https://github.com/feixiaoxing/DIYCompiler​​

        之前一章,我们谈到过简单语法树的构建。说是语法树,其实就是一个tree node。它的左子树是一个整数,右子树也是一个整数。所有的工作都是为了构建一个div_node。

        在此基础上,大家可以思考一下,如果是一个连续的除法,这个时候应该怎么处理?一个比较容易想到的办法就是在原来简单语法树的基础之上,构建更为复杂的语法树。

div_node expr() throws NumberFormatException :
{
Token a ;
Token b ;
div_node div;
}
{
a =
{
value_node node_a = new value_node();
node_a.set_value(Integer.parseInt( a.image ));

div = new div_node();
div.set_left_node(node_a);

}

(
"/" b =
{
value_node node_b = new value_node();
node_b.set_value(Integer.parseInt( b.image ));

if(div.get_right_node() == null)
{
div.set_right_node(node_b);
}
else
{
div_node prev = div;
div = new div_node();

div.set_left_node(prev);
div.set_right_node(node_b);
}
}
)*


{ return div ; }
}

        上面的代码是一个比较典型的实现方式。其中最重要的几句代码,就是div.get_right_node()这个判断。首先,不管怎么说,node_a和div肯定是要创建的。至于node_b是否要创建,这个要看现场的情况。这里假设node_b需要创建,情况也会有两说。一是当前div的右子树还是null,这个时候不用说,直接赋值上就可以。二是当前div已经满了,这个时候如何解决呢?其实就是在当前div的基础之上再增加一个父节点,将node_b挂到这个父节点上就可以了。

        二叉树的访问方法一般是左、右、根,因此有了上面的这个构建语法树的办法,才会按照左、右、根的访问方法将语句按照原来的布局继续解析下去。至此,大家会发现,不管有多少的除法运算,最终的返回值都是一个div_node,只不过他的下面有多少层左子树罢了。

很多编译课程告诉我们,其实后面还有语义分析、中间代码生成,汇编生成等等。但其实来说,有了语法树,本身就可以做很多事情,甚至不需要后面的步骤都可以。比如有了这个除法的语法树,计算就是一件很容易的事情了,

class div_node extends node
{
div_node() { set_node_type("/");}

public int get_value() {
int left = 0, right = 0;

// get left node
if(get_left_node().get_node_type() == "/")
{
left = ((div_node)get_left_node()).get_value();
}
else
{
left = ((value_node)get_left_node()).get_value();
}

// get right node
if(get_right_node() == null)
{
return left;
}
else
{
right = ((value_node)get_right_node()).get_value();
return left/right;
}
}
}

        首先它会查看是否有递归,如果有递归左子树,就会继续递归调用。接着,它会看右子树,看是否确实有除法计算,没有的话,直接返回left即可;有的话,需要进行left、right的除法运算。

        上面给出的都是代码的片段,这里给出完整的代码。其实这后面的逻辑都不复杂,关键是思考怎么一步一步实现这一点的。此外,一定要动手实践。哪怕是再简单的东西,有没有自己动手去做,效果还是大不一样的。

options {
STATIC = false;
}

PARSER_BEGIN(Parse)
import java.io.*;

class node
{
public node left;
public node right;
public String node_type;

node() {this.left = this.right = null;}
public void set_left_node(node left) { this.left = left;}
public node get_left_node() { return this.left;}

public void set_right_node(node right) { this.right = right;}
public node get_right_node() {return this.right;}

public void set_node_type(String node_type) {this.node_type = node_type;}
public String get_node_type() {return this.node_type;}
}

class value_node extends node
{
public int value;

value_node() { set_node_type("value_node");}
public int get_value() { return this.value;}
public void set_value(int value) {this.value = value;}
}

class div_node extends node
{
div_node() { set_node_type("/");}

public int get_value() {
int left = 0, right = 0;

// get left node
if(get_left_node().get_node_type() == "/")
{
left = ((div_node)get_left_node()).get_value();
}
else
{
left = ((value_node)get_left_node()).get_value();
}

// get right node
if(get_right_node() == null)
{
return left;
}
else
{
right = ((value_node)get_right_node()).get_value();
return left/right;
}
}
}

public class Parse {

public static void main(String[] args) {
for (String arg : args) {
try {
System.out.println(evaluate(arg).get_value());
} catch (ParseException ex) {
System.err.println(ex.getMessage());
}
}
}

public static div_node evaluate(String src) throws ParseException {
Reader reader = new StringReader(src);
return new Parse(reader).expr();
}
}
PARSER_END(Parse)

SKIP: { <[" ", "\t", "\r", "\n"]> }
TOKEN: {

}

div_node expr() throws NumberFormatException :
{
Token a ;
Token b ;
div_node div;
}
{
a =
{
value_node node_a = new value_node();
node_a.set_value(Integer.parseInt( a.image ));

div = new div_node();
div.set_left_node(node_a);

}

(
"/" b =
{
value_node node_b = new value_node();
node_b.set_value(Integer.parseInt( b.image ));

if(div.get_right_node() == null)
{
div.set_right_node(node_b);
}
else
{
div_node prev = div;
div = new div_node();

div.set_left_node(prev);
div.set_right_node(node_b);
}
}
)*


{ return div ; }
}
特别声明:以上内容(图片及文字)均为互联网收集或者用户上传发布,本站仅提供信息存储服务!如有侵权或有涉及法律问题请联系我们。
举报
评论区(0)
按点赞数排序
用户头像
精选文章
thumb 中国研究员首次曝光美国国安局顶级后门—“方程式组织”
thumb 俄乌线上战争,网络攻击弥漫着数字硝烟
thumb 从网络安全角度了解俄罗斯入侵乌克兰的相关事件时间线
下一篇
java web开发(web 语言开发pk) 2023-09-22 12:08:34