自制脚本语言(12) 作用域与符号表

摘要:介绍了自制语言的编译器对符号表的处理。

YF语言中,符号表的基本结构是hash表。每个AST,附带了3个hash表,变量表,类型表,函数表。例如<String, R_Variable>就是变量表,记录变量的名称和值。类型表记录各种类型,array、class、interface、function、generic。函数表则记录了函数名和函数体、函数类型的对应关系。

一个文件有若干class和interface定义,此外的部分是脚本,可以定义变量、函数等。同时,class或脚本都没有main()函数。脚本本身就是main()。脚本内的函数可以访问脚本范围的变量与函数。而类型的作用域都是全局的(全局是指本文件范围)。文件头部import其他文件之后,可以访问其class、interface,但不能访问其脚本变量和函数。

作用域跟AST的层次有关以及访问者有关。举例来说,每个stmt_list都是一个单独的作用域。codegenerator保留一个栈list<AST>,访问AST时,遇到stmt_list,就把这个AST加入栈顶。遇到define variable,就生成一个新的符号,这个符号加入栈顶AST的符号表中。当后面要查找variable,就从栈顶开始依次查找符号表。当访问者离开这个AST,把栈顶AST退出。这样,不在作用域内的变量引用就是非法的。而作用域范围可以嵌套。内层作用域可以访问外层作用域定义的变量或者函数。

查找函数的方法,除了函数的名称,还要有函数的类型签名,如int(int, int)。这可以用于函数重载。

class内部不允许访问外部的变量及函数。但是子类可以访问父类。这里就有一个作用域控制问题。class范围内,每个定义的field和method都记录入type对象中,同时递归地记录了全部super class以及interface。在class范围内查找变量或者函数时,优先在codegenerator的符号表相关AST栈中查找。AST栈中每个AST,在codegenerator初次访问时,都打上了一个标记,标明此处是什么范围。比如全局范围,标记是0b1,class范围标记是0b10,局部变量的标记是0b100,等等。当codegenerator发起一个查找时,自身的标记如果不符合,就不被允许查找。这样就杜绝了从class内部访问外部的脚本的变量。那么,当class内部查找不到变量时,就会访问类型表,查找当前class的成员记录。若当前class类型中查找不到记录,则继续向super类型中查找。直到找到符号或者找不到而throw exception。

值得一提的是this关键字。遇到this关键字,查找顺序发生变化。省略前面从AST查找的步骤而是直接通过类型表中找。因为在class范围内的AST的符号表,无非有两种情况,class的成员,或者局部变量。没有this关键字,那么符号可能是类成员也可能仅仅是局部变量,有了this关键字,符号只能是成员。所以必须从class类型中去找。前面一种情况下局部变量对类型成员的覆盖,也是通过AST栈来实现。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值