自己写一个编译器:第三天:词法分析
2016-02-14 00:00
162 查看
摘要: 自己写一个编译器系列第三天
词法分析
// 请移步《从零开发一个JVM语言》系列。
// 由于这篇文章有人收藏就不删除了。。
看下面这个表达式
它表达了什么呢?
人在观察一个表达式的过程中,实际上已经对它进行了词法分析。
没有接受过编程训练的人看到它的第一眼也会认为它的组成大概是这样:
|
这也就是词法分析要做的事。
词法(
我在进行词法分析时做的事情很少。仅仅是生成了包含token原始字符和所在位置,外加一些额外信息组成的节点串。
为了说明我的词法分析器,首先定义一个概念,层
每遇到4个缩进,则视为一个新的“层”。
此例中,有3个层次。
此外,有一些符号必然开启一个
我规定了几个简易的规则,使得其处理起来非常简便。
节点分为3种
规定若干
规定若干
规定若干
规定若干
规定注释符号
规定若干
规定若干
规定若干
而它们所有,都汇总到一个List
这个List是有顺序的。所有字符按其字符串长度降序排序。
##解析
一行一行读取。
检查其缩进,若=上一行+4,则视为新的
若比上一行小,则视为跳出
取出这一行
取
对其进行分析,分解出token
取该串之后的字符串,进行递归。
中间的分析过程最重要。不过也很简单
取该串在LINE位置下标之前的LINE的子串,若该串不为空,则记录为token
若该串是层开启符号,则记录该串为token后开启一个新ElementStartNode
若该串是强结束符号,则添加一个EndingNode并标记为强结束
若该串是分隔符号,则判断是否是不记录符号,若不是则记录该串为token
若该串是注释符号,则直接清空这一行后面所有的内容
若该串是字符串起始字符,则找到与之相同的符号,且前面没有转义标记的最先找到的字符,将其视为字符串,记录
若该串是PAIR中的
若该串是PAIR中的
若该串是特殊符号,则进行特殊处理
对LINE中尚未被解析的部分进行该算法。
##例子
会被解析成
词法分析
// 请移步《从零开发一个JVM语言》系列。
// 由于这篇文章有人收藏就不删除了。。
看下面这个表达式
1 + 2 * 3.4 - variable.field
它表达了什么呢?
人在观察一个表达式的过程中,实际上已经对它进行了词法分析。
没有接受过编程训练的人看到它的第一眼也会认为它的组成大概是这样:
|
1|
+|
2|
*|
3.4|
-|
variable|
.|
field|
这也就是词法分析要做的事。
词法(
lexical)分析做的事情很简单,仅仅是将给出的一个或几个句子拆分成便于处理的
token流。token流是指一串token。
我在进行词法分析时做的事情很少。仅仅是生成了包含token原始字符和所在位置,外加一些额外信息组成的节点串。
为了说明我的词法分析器,首先定义一个概念,层
class C a=1 <<<>>>
每遇到4个缩进,则视为一个新的“层”。
此例中,有3个层次。
class C,
a=1,
<<<>>>(getter/setter)
此外,有一些符号必然开启一个
层,即使后面的字符没有换行并添加缩进。
我规定了几个简易的规则,使得其处理起来非常简便。
节点分为3种
ElementStartNode该节点开启一条独立的节点链
Element该节点记录了实际信息
EndingNode该节点表示一个表达式/语句的结束(分为
STRONG和
WEAK,STRONG表示此语句必然结束,WEAK表示,若该语句尚未完成,则可以跨越该节点到下一条继续取token)
规定若干
层的开启符号
规定若干
强结束符号
规定若干
分隔符号(表示他们之前和之后是不同的节点,而其本身是否记录为节点要看另一个量:不记录符号)
规定若干
不记录符号
规定注释符号
规定若干
字符串起始字符
规定若干
层起始结束对(PAIR)(由一个开始,由另一个结束)
规定若干
特殊符号(这类符号需要特殊处理)
而它们所有,都汇总到一个List
SPLIT中
这个List是有顺序的。所有字符按其字符串长度降序排序。
##解析
一行一行读取。
检查其缩进,若=上一行+4,则视为新的
层,创建一个
ElementStartNode,并在其上链接之后解析的内容
若比上一行小,则视为跳出
层,找到对应层的ElementStartNode,然后在其后面继续添加节点
取出这一行
.trim()后的串LINE,进行如下算法
取
SPLIT中字符串
存在于LINE中,且在LINE中位置的下标最小 且 该串的长度最长的串
对其进行分析,分解出token
取该串之后的字符串,进行递归。
中间的分析过程最重要。不过也很简单
取该串在LINE位置下标之前的LINE的子串,若该串不为空,则记录为token
若该串是层开启符号,则记录该串为token后开启一个新ElementStartNode
若该串是强结束符号,则添加一个EndingNode并标记为强结束
若该串是分隔符号,则判断是否是不记录符号,若不是则记录该串为token
若该串是注释符号,则直接清空这一行后面所有的内容
若该串是字符串起始字符,则找到与之相同的符号,且前面没有转义标记的最先找到的字符,将其视为字符串,记录
若该串是PAIR中的
起始,则记录该串后开启一个新ElementStartNode
若该串是PAIR中的
结束,则找到对应ElementStartNode后在其后追加该串
若该串是特殊符号,则进行特殊处理
对LINE中尚未被解析的部分进行该算法。
##例子
class C(x=1):S y <-<>->
会被解析成
class C ( x = 1 ) : S y <-< (STRONG) >->
相关文章推荐
- 浅谈汇编器、编译器和解释器
- 让我们做个简单的解释器(三)
- 让我们做个简单的解释器(一)
- 用 350 行代码从零开始,将 Lisp 编译成 JavaScript
- Python的词法分析与语法分析
- 基于JSP编译器基本语法的使用详解
- C#命令行编译器配置方法
- Java虚拟机JVM性能优化(二):编译器
- AngularJS HTML编译器介绍
- 实现接口时@Override注解问题
- 条款06:若不想使用编译器自动生成的函数,就该明确拒绝
- g++编译 参数 .
- 关于 ndk和jni的区别
- vim中的杀手级插件: YouCompleteMe
- Google C++ unit test 在ARM Android 2.3 上的编译与使用
- 从代码示例了解ECMAScript5新特性
- Java的可移植性受到广泛使用
- C++ .H .CPP
- Windows Server 2003远程桌面多用户连接问题