在翻译完CUCU编译器的三篇文章之后,一直有自己尝试去写个编译器的念头,最近的课余时间暂且搁置JOS实验,尝试自己写个编译器,然后若仅仅是个编译器则所做之事未免和CUCU太雷同了,因此除了编译器之外还打算写一个简单的运行时让编译器编译出的程序跑在这个运行时里,就像JAVA那般。
手上的参考资料有:龙书三(紫龙书)、深入理解JAVA虚拟机、自己翻译的3篇博客,尽量不去翻阅其它资料。
所有的代码均自己写,完全不使用任何开源代码及相关工具如LEX和YACC之类的
我甚至都不知道靠自己的能力能不能做出来,也不知道自己写的日志有没有问题,只能走一步看一步,也许之后发现前面写的完全不靠谱,把这个系列全部删掉也有可能。
不过这很coooooooooooooooool,不是么。。。。
一、语言的通俗描述
既然打算做一个带运行时的语言,我们可以去实现一个简单的精简过JAVA语言,就叫RAVA好了。
这个RAVA仅有以下规则,大部分都是JAVA的规则,或者精简过后的JAVA规则。
1、一个文件里只能定义一个类。
2、类名不能相同。
3、包含一个static int main()作为程序入口
4、一个类必须有一个构造函数
5、一个类中可以定义若干私有或共有变量,但变量必须要在构造函数中进行初始化,可以定义静态变量。
6、3种基本类型 char,int,double分别占1 、4、4字节。
7、支持数组,数组声明方式和java一样
8、使用new关键字新建对象或者数组。
9、可以声明调用函数,函数声明时必须说明访问权限(private public),可以定义静态函数。
10、函数必须有返回值,函数结束处必须有return。
11、控制语句只有if 、if else、while循环(不支持for循环)
12、其它一些java基本的规则(比如语句之后用分好分割,不能使用if for等作为标识符)
二、文法和范式
文法即语法,接下来要把上面通俗的规则变成所谓的语法,那么不可避免的问题就是:语法是什么。
通俗的讲,语法就是一门语言的规则,通过语法才能知道一个句子在这个语言中是不是合理的。那么就会引出第二个问题:如何描述语法。
关于文法的内容可参考我翻译的cucu编译器的文章http://blog.csdn.net/roger__wong/article/details/8498591 以及编译原理等相关资料。
文法由三部分组成:终结符号集合、非终结符号集合、一组产生式和开始符号
1、终结符号
终结符号又被称作词法单元,是词法分析器的输出内容,是代码中不可分割的基本元素,根据需要,我们定义如下符号为终结符号(每个符号之间用空格隔开):
if else while ( ) { } cpreop bitop logiop armtcop number literal id NUL new [ ] basetype class private public static return break continue . this ; = ,
其中cprop包括 > < >= <= == != 即比较运算符
bitop 为位运算符,包括<< >> & | ^
logiop 逻辑运算符 包括 && ||
armtcop 算数运算符 包括 + - * /
number 数字常量 例如12345整形火 1.2345小数
id 标识符 按java规则
literal 字符串常量 如"ROgerwong"
NUL 空串
basetype 基本类型 包括 int char double 三种
2、非终结符号
在产生式中出现的除终结符号外都是非终结符号。
3、开始符号
语法树的根,根据java语言特性定义class-def符号为开始符号
4、推导式
class-name --> id
type --> basetype|class name
member-var-declare --> private|public
NUL|static
type id ;
def-args --> type id |type id , def-args
func-name-->ids
args --> ids | ids, args
func-call --> ids . func-name(NUL|args)
ops --> bitop | logiop | artmop | cprop
ids-> id|
id.ids|
ids[expr] |
this
expr --> (expr)
ids|
number|
literal|
func-call|
expr ops expr|
var-declare --> type args|type[] args
class-init --> ids = new
type ( args )| type[expr]| typex[expr](args)
setvalue--> ids = expr
stmt --> continue;|
break;|
var-declare;|
class-init;|
setvalue;|
expr;|
stmts --> NUL|
stmt stmts|
if(expr) { stmts}|
if(expr) {stmts} else {stmts}
while(expr) { stmts}
func-body --> stmts return expr;
member-func-declare --> private|public
NUL|static
type func-name( NUL|def-args ) { func-body }
constructor --> public|private
class-name(NUL|def-args) {stmts}
class-members--> NUL|
member-func-declare class-members|
member-var-declare class-members|
constructor class-members
class-body-->class-members
class-def --> class class-name { class-body }