语言处理器的第一个组成部分是词法分析器(lexical analyzer、lexer或scanner)。程序的源代码最初只是一长串字符串。从内部来看,源代码中的换行也能用专门的(不可见)换行符表示,因此整个源代码是一种相连的长字符串。这样的长字符串很难处理,语言处理器通常会首先将字符串中的字符以单词为单位分组,切割成多个子字符串。这就是词法分析。 3.1 Token对象 程序设计领域中的单词包含+或==之类的符号。例如,下面是某个程序中的一行代码。 while i < 10 { 词法分析会把它拆分为下面这样的字符串。 "while" "i" "<" "10" "{" 这句代码被分割为了5个字符串。其中while是一个词语,但要把<与{也称作词语,的确有些不自然,因此,人们通常把词法分析的结果称为单词 (token)。 词法分析将筛选出程序的解释与执行必需的成分。单词之间的空白或注释都会在这一阶段被去除。例如, i = i + 1 // increment i=i+1 这两行代码词法分析的结果相同,都将是5个单词: "i" "=" "i" "+" "1" 在经过词法分析之后,程序员便无需再处理代码的注释,也不用考虑单词之间是否含有空白符。 A 感觉就像是去除了程序中无用的内容,筛选出了有价值的信息呢。 词法分析器将把程序源代码视作字符串,并把它分割为若干单词。分割后得到的单词并不是简单地用String对象表示,而是使用了代码清单3.1中的Token对象。这种对象除了记录该单词对应的字符串,还会保存单词的类型、单词所处位置的行号等信息。代码清单3.1中使用的StoneException是RuntimeException的一个子类(代码清单3.2)。 实际的单词是Token类的子类的对象。Token类根据单词的类型,又定义了不同的子类。Stone语言含有标识符、整型字面量和字符串字面量这三种类型的单词,每种单词都定义了对应的Token类的子类。每种子类都覆盖了Token类的isIdentifier(如果是标识符则为真)、isNumber(如果是整型字面量则为真)及isString(如果是字符串字面量则为真)方法,并根据具体类型返回相应的值。 F 把单词的种类限定为3种,还真是敷衍啊。 H 用is什么的方法来区别不同的类型也有些…… F 以后想要增加单词的类型也不行了吧。 C 这里的确有些随便了,应该用enum之类的才对。 此外,Stone语言还定义了一个特别的单词Token.EOF(end of file),用于表示程序结束。类似的还有Token.EOL(end of line),用于表示换行符。不过它是一个String对象,也就是说,只是一个单纯的字符串。