实现自己的脚本语言ngscript之一:词法分析
正则表达式的理论基础可以参考装配脑袋的
如果学过编译原理的课程就更好了。
词法分析用到了我写的一个工具lexeroid。
下面说一些我写lexeroid时候遇到的问题。
Unicode
在 装配脑袋 的 自己动手开发编译器(四)利用DFA转换表建立扫描器 中,提到了等价类处理Unicode的方法。
我做了一些改进。
首先我把DFA Edge的输入改了,不再是一个char这种,而是一个Input类,它接受空(epsilon)或者begin和end范围(左闭右开区间)内的char。
然后我就可以把char1写成这样
public static NFA char1() {
return Re.range(0, 131072);
}
然后就支持中文了……
而定义regex时冲突的部分,比如定义了一个'a'-'z'的Input和一个'g'的Input在同一个Vertex上,会有一个reduce函数把'a'-'z'分离成'a'-'f'和'h'-'z'。
最长匹配
这个很多书上应该介绍过,就是设置一个lastFinal一样的东西,然后在DFA停机的时候把最后一个正确匹配的取出来。
NFA的组织
最开始我做的是把每个token的NFA分开,存成一个数组,然后每个生成DFA之后,在词法分析的时候一个一个去测试。后来发现这个似乎和用Java内置的正则表达式没什么区别。而且有一个问题是,token定义的顺序要十分小心,因为先定义的token会被优先匹配到。
后来我试了另外一种方法,就是等所有token生成NFA完之后,添加一个入口,用epsilon边把所有的NFA连起来形成一个大NFA,然后再用它生成的DFA去匹配。
最后
lexeroid定义token时大概是这个样子
LexerBuilder builder = new LexerBuilder();
builder.defineToken("if", Re.string("if"));
builder.defineToken("return", Re.string("return"));
builder.defineToken("else", Re.string("else"));
builder.defineToken("ident", Re.concat(
Re.or(Re.letter(), Re.chr('_')),
Re.many(Re.or(Re.or(Re.letter(), Re.chr('_')), Re.digit()))
));
builder.defineToken("string",
Re.concat(Re.chr('"'), Re.many(Re.char1()), Re.chr('"'))
); //此处省略N行
return builder.build();
代码可以从这里找到
https://github.com/wssccc/lexeroid.git
作为一个词法分析器,后面的文章中还会用到它。
相关资料
实现自己的脚本语言ngscript之一:词法分析的更多相关文章
- 实现自己的脚本语言ngscript之零
正式开始介绍前先扯点没用的. 从小玩basic长大的小朋友大多有一个梦想,就是自己实现一个basic解释器. 不过这里我实现的不是basic,而是一个语法和功能类似javascript的东西. 暂且称 ...
- 实现自己的脚本语言ngscript之三:语法设计
这是第四篇了,之所以隔了这么久才写,一方面是因为最近开始实习了,另一方面是因为设计语法真是要考虑很多东西. 于是我去读了这本书,里面实现了两种语言,一种跟js差不多语法,用ast解释执行:另一种语法类 ...
- 实现自己的脚本语言ngscript之四:代码生成
最近的进度 ngscript测试代码 function c1(a, b, c, d) { this.a = 1; this.b = new array(); this.b[0] = 1; this.b ...
- 实现自己的脚本语言ngscript之二:语法分析
ngscript的语法分析使用的是我自己的语法分析工具parseroid.与常用cc工具(yacc.bison.javacc.antlr.etc…)不同的是,parseroid生成的不是语法分析器的源 ...
- 脚本语言:Xmas(三)
自从将Xmas的GC换成现在的非迁移式的全局收集器后,最近几个月一直耗在Xmas上面:最明显的改变就是:更彻底地支持了面向对象.更强大的编译器. 所以,本文就来说说,真正的Xmas. 一.目标 一门语 ...
- 用PHP写一个最简单的解释器Part4(写一个最简单的脚本语言)
好吧!我承认我想标题党了.大家对解释器的吸引,绝对没有自己动手写一个脚本语言更有吸引力.不过如果看到标题过来的,可能也是 我承认,之前收藏的减肥视频,我都是这样对待他们的. 不过我还是相信很多程序猿o ...
- InstallShield 脚本语言学习笔记
InstallShield脚本语言是类似C语言,利用InstallShield的向导或模板都可以生成基本的脚本程序框架,可以在此基础上按自己的意愿进行修改和添加. 一.基本语法规则 ...
- JS脚本语言是什么意思?
javascript,Javascript是一种浏览器端的脚本语言,用来在网页客户端处理与用户的交互,以及实现页面特效.比如提交表单前先验证数据合法性,减少服务器错误和压力.根据客户操作,给出一些提升 ...
- 使用Lua脚本语言开发出高扩展性的系统,AgileEAS.NET SOA中间件Lua脚本引擎介绍
一.前言 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适合市 ...
随机推荐
- 关于jQuery,$(":button") 中的冒号是什么意思?
$(":button") 表示匹配所有的按钮.$("input:checked")表示匹配所有选中的被选中元素(复选框.单选框等,不包括select中的opti ...
- 4 C#和Java 的比较
2007年11月1日 1.访问控制方面:C#有public.internal.protected.private,比java多了个internal,其实它跟java的包访问差不多,interna ...
- Lost connection to MySQL server at ‘reading initial communication packet', system error: 0 mysql远程连接问题
在用Navicat for MySQL远程连接mysql的时候,出现了 Lost connection to MySQL server at ‘reading initial communicatio ...
- GDB源代码查找路径
在gdb程序的时候,有时候会发现源代码文件找不到,对于那些带调试信息的系统库或者第三方库,很多时候当你真正想gdb去追他源代码的时候你会发现gdb根本找不到这些源代码路径.这个时候有两种选择: [1] ...
- poj 1170 Shopping Offers
Shopping Offers Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 4696 Accepted: 1967 D ...
- alter system register
alter system register的用法 1 Static Registration via set the listener.ora2 Dynamic Instance Registrati ...
- android 代码混淆及问题大集锦
最近在需要对所开发的项目进行了代码混淆,在android studio中开启代码混淆其实还是挺方便的,不过因为代码混淆产生的问题非常多,特别是对于一些涉及到反射的第三方库经常因为名称的变化导致无法使用 ...
- JSP中两种模式的总结
运用JSP/Servlet实现的Web动态交互,主要采用: 模式一:JSP+JavaBean 链接:http://wxmimperio.coding.io/?p=155 模式二;JSP+Servlet ...
- JSP环境配置
为免以后忘记,记下了. Jdk在C盘,tomcat在D盘. 1.JAVA_HOME C:\Program Files\Java\jdk1.7.0_07 2.CATALINA_HOME D:\apach ...
- Phonegap 3.0 拍照 出错的说明
在官方3.0 提供的摄像机操作例子是不成功的,因为该例子没有说明摄像机操作需要添加Plugin. 添加插件方法(安装cordova3.0时必须使用官方命令行方式,通过nodejs安装,且装上了git) ...