DDL 解析
简单的解析完成后来看看 DDL
这样的脚本应当如何解析:
CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `userName` varchar(20) DEFAULT NULL COMMENT '用户名', `password` varchar(100) DEFAULT NULL COMMENT '密码', `roleId` int(11) DEFAULT NULL COMMENT '角色ID', PRIMARY KEY (`id`), ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8
原理类似,首先还是要看出规律(也就是语法):
- 表名是第一行语句,同时以
CREATE TABLE
开头。
- 每一个字段的信息(名称、类型、长度、备注)都是以 "`" 符号开头 "," 结尾。
- 主键是以 PRIMART 字符串开头的字段,以
)
结尾。
根据我们需要解析的数据种类,我这里定义了这个枚举:
然后在初始化类型时进行判断赋值:
由于需要解析的数据不少,所以这里的判断条件自然也就多了。
递归解析
针对于 DDL
的语法规则,我们这里还有需要有特殊处理的地方;比如解析具体字段信息时如何关联起来?
举个例子:
`userName` varchar(20) DEFAULT NULL COMMENT '用户名', `password` varchar(100) DEFAULT NULL COMMENT '密码',
这里我们解析出来的数据得有一个映射关系:
所以我们只能一个字段的全部信息解析完成并且关联好之后才能解析下一个字段。
于是这里我采用了递归的方式进行解析(不一定是最好的,欢迎大家提出更优的方案)。
} else if (value == '`' && pStatus == Status.BASE_INIT) { result.tokenType = DDLTokenType.FI; result.text.append(value); }
当当前字符为 ”`“ 符号时,将状态置为 "FI"(FieldInfo),同时当解析到为 "," 符号时便进入递归处理。
可以理解为将这一段字符串单独提取出来处理:
`userName` varchar(20) DEFAULT NULL COMMENT '用户名',
接着再将这段字符递归调用当前方法再次进行解析,这时便按照字段名称、类型、长度、注释的规则解析即可。
同时既然存在递归,还需要将子递归的数据关联起来,所以我在返回结果中新增了一个 pid
的字段,这个也容易理解。
默认值为 0,一旦递归后便自增 +1,保证每次递归的数据都是唯一的。
用同样的方法在解析主键时也是先将整个字符串提取出来:
PRIMARY KEY (`id`)
只不过是 "P" 打头 ")" 结尾。
} else if (value == 'P' && pStatus == Status.BASE_INIT) { result.tokenType = DDLTokenType.P_K; result.text.append(value); }
也是将整段字符串递归解析,再递归的过程中进行状态切换 P_K ---> P_K_V
最终获取到主键。
所以通过对刚才那段 DDL
解析得到的结果如下:
这样每个字段也通过了 pid
进行了区分关联。
所以现在只需要对这个词法解析器进行封装,便可以提供一个简单的 API
来获取表中的数据了。
总结
到此整个词法解析器的全部内容都已经完成了。
但这还只是整个编译语言知识点的冰山一角,后续还有语法、语义、中间、目标代码等一系列内容。
本文所有源码及插件地址: