从零开始写个编译器吧 - tao语言的词法分析器(Tokenizer)的类型定义

620 查看

要为 tao 语言设计词法分析器,首先得知道 tao 语言是一种什么样的语言。不过呢,我脑海里还没有 tao 语言具体形象。我还是先贴一段 tao 语言的代码,大概展示下这是怎么回事吧。

def say_hello_world(who) 
    print “hello world ” + who 
end 
var name = “tao” 
say_hello_world name 
#我是注释,注释是这样写的

看起来可能是这个样子。这个系列中的 tao 语言我会采取一边写编译器,一边设计的形式。细节在之后的章节会逐步补充完整。本章只是些词法分析器,因此不必了解太多细节(也不必设计出来)。因此,tao语言的概念也暂时止步于此不作细节上的讨论。

OK,不过首先我们得把词法分析器能生成的单词类型定义好了。嗯,我想想,显然一个语言至少要这么几种类型嘛。

  • 关键字(Keyword)
  • 符号(Sign)
  • 标示符(Identifier)
  • 其中关键字和符号很好理解,标示符,则具体而言,就是用户定义的变量、函数定义中的函数名和参数名、被调用函数的函数名等等这些东西。

严格来说,仅由数字、英语字母、下划线的字符串(可以以'?'、'!'为结尾,但不能以数字为开头),如果没有被关键字占用,则统统称之为标示符。其正则表达式形如:

^[a-zA-Z_][0-9a-zA-Z_]*[!\?]?$

当然,关键字的形式和标示符是一样的(至少要满足标示符的正则表达式定义)。

然后,数据类型也要有:

  • 数字类型(Number)
  • 字符串(String)
  • 正则表达式(RegEx)

其中数字类型的形式和标示符的形式极为类似,不同点在于,数字类型要求必须以数字开头(当然结尾不可以接'?'和'!')这两个符号啦。其正则表达式形如:

^[0-9][0-9a-zA-Z_]*$

如此以来数字类型就和传统意义上的数字不一样了。形如"110police"也会被当做数字。此外,像3.14这种实数却不会被当作数字。嗯,这的确是问题,但是我不想在现在就解决这个问题,暂时不管啦,请先无视~~~。

另一个是正则表达式的定义,tao 语言中将 ` 符号置于两端来表示正则表达式。(什么,找不到这个符号,嗯,这个符号在“1”的左边,直接按下即可打出。)为什么用这个符号而不用 / 分开呢,猜一猜为什么呢?嗯,真正开始编码的时候揭示答案吧。

再然后,这些对编译器意义不大,但还是有点用处的类型:

  • 注释(Annotation)
  • 空格(Space)
  • 回车(NewLine)
  • 其中注释以 # 开始,单行注释。

最后的最后,还有一个类型是必须:

  • 终止符(EndSymbol)

这个类型不对应任何程序员可输入的形式,实际上,词法分析器会在解析完所有源代码之后,自动以一个该类型的单词结尾。这个类型是专门给语法分析器(Parser)使用的。