atitit.自己动手开发编译器and解释器(1) ------词法分析--attilax总结
2. 2. 流程如下::: 词法分析(生成token流) >>>>语法分析(生成ast) >>解释执行... 2
4. 使用状态模式构建FSM (简单,易用。。推荐首选) 2
6.1. 词法分析(英语:lexical analysis)跟token
4
7.3. 使用NFA、DFA构建FSM( 专业方法,难度大) 6
1. 应用场景:::DSL 大大提升开发效率
为了大大提升开发效率,使用了大量DSL ,就需要实现自己的编译器、解释器了。。
String s = "@QueryAdptr(sqlwhere=\" clo1='@p' \",prop2=\"v2\") @Nofilt";
// 创建环境
所以,要解析注解...
网上马,,子能嘎自实现兰....
要是java 源码中的注解能使用java api读取了...
html中的注解嘎自实现兰.
作者:: 老哇的爪子 Attilax 艾龙, EMAIL:1466519819@qq.com
转载请注明来源: http://blog.csdn.net/attilax
2. 2. 流程如下::: 词法分析(生成token流) >>>>语法分析(生成ast) >>解释执行...
3. 如何进行词法分析?Fsm状态机(自动机)
A: 一种很简单的思路就是,用一个状态保存在处理到各个字符时的状态,比如是标识符或者数字或者空格等等,直到状态改变到可以认定是不同token的时候结束。
可以肯定的是,必然要对需要处理的数据挨个字符判断,然后在恰当的位置截断,得到一个个的token.
这里的核心在于将不同符号对应的字符给区别开,在一个字符无法表达此符号时将它截断,token形成。
4. 使用状态模式构建FSM (简单,易用。。推荐首选)
这种模式使用代码实现fsm 简单,易用。。推荐首选
使用这种方法,attilax初次实现词法分析,也只用一天时间
5. ---代码( 状态模式构建FSM )
public static List getTokenList() {
String s = "@QueryAdptr(sqlwhere=\" clo1='@p' \",prop2=\"v2\") @Nofilt";
s="@qu(at1=\"v1\" , at2 = \" v2 abc \",at3=\"v3\" ) ";
// 创建环境
AnnoPaserContext context = new AnnoPaserContext();
// 将状态设置到环境中
// 创建状态
context.setState(new iniState());
int n=0;
while(!( context.state instanceof FinishState))
{
// System.out.println(n);
// 请求
context.request(s);
n++;
if(n>200)
break;
}
for (Token tk : context.tokenList) {
//if(tk.value.trim().length()>0)
System.out.println(tk.value+"");
}
return (List) context.tokenList;
}
6. 词法分析概念
6.1. 词法分析(英语:lexical analysis)跟token
是计算机科学中将字符序列转换为单词(Token)序列的过程。进行词法分析的程序或者函数叫作词法分析器(Lexical analyzer,简称Lexer),也叫扫描器(Scanner)。词法分析器一般以函数的形式存在,供语法分析器调用。
这里的单词是一个字符串,是构成源代码的最小单位。从输入字符流中生成单词的过程叫作单词化(Tokenization),在这个过程中,词法分析器还会对单词进行分类。
词法分析器通常不会关心单词之间的关系(属于语法分析的范畴),举例来说:词法分析器能够将括号识别为单词,但并不保证括号是否匹配。
词法分析(lexical analysis)或扫描(scanning)是编译器的第一个步骤。词法分析器读入组成源程序的字符流,并且将它们组织成有意义的词素(lexeme)的序列,并对每个词素产生词法单元(token)作为输出。
简单的来说,词法分析就是将源程序(可以认为是一个很长的字符串)读进来,并且“切”成小段(每一段就是一个词法单元 token),每个单元都是有具体的意义的,例如表示某个特定的关键词,或者代表一个数字。而这个词法单元在源程序中对应的文本,就叫做“词素”。
token就是把程序的语句进行类似分词得到的单词。
6.2. 五种token类型
下面就是上述单词的正则表达式定义。
类型 |
正则表达式 |
例子 |
关键字string |
string |
string |
标识符(变量名) |
[a-z][a-z0-9]* |
str |
等号 |
= |
= |
字符串字面常量 |
"[^"]*" |
"hello world" |
分号 |
; |
; |
接下来的问题是,怎么用正则表达式表示的规则来进行词法分析呢?正则表达式利于我们理解单词的规则,但并不能拿来直接解析字符串。为此我们要引入有穷自动机的概念来真正处理输入字符串。
7. 其他词法分析方法
7.1. switchcase或者ifelse
这无意是最直观的方式,使用一堆条件判断,会编程的人都可以做到,对简单小巧的状态机来说最合适,但是毫无疑问,这样的方式比较原始,对庞大的状态机难以维护。
但checkStateChange()和performStateChange()这两个函数本身依然会在面对很复杂的状态机时,内部逻辑变得异常臃肿,甚至可能是难以实现。
在很长一段时期内,使用switch语 句一直是实现有限状态机的唯一方法,甚至像编译器这样复杂的软件系统,大部分也都直接采用这种实现方式。但 之后随着状态机应用的逐渐深入,构造出来的状态 机越来越复杂,这种方法也开始面临各种严峻的考验,其中最令人头痛的是如果状态机中的状态非常多,或者状 态之间的转换关系异常复杂,那么简单地使用switch语句构造出来的状态机将是不可维护的。
7.2. 状态表
,介绍了正则表达式、正则语言和DFA等工具。今次我们要开始涉及编译器前端最重要的阶段——语法分析。简单而言,这一步就要完整地分析整个编程语言的语法结构。上回说到词法分析的结果是将输入的字符串分解成一个个的单词流,也就是诸如关键字、标识符这样有特定意义的单词
7.3. 使用NFA、DFA构建FSM( 专业方法,难度大)
DFA实际上就是高级版的状态表
使用DFA的方法完成的可配置词法分析器的性能是相当好
一般来说,比较高性能的DFA的实现是一张二维的表。行代表字符,列代表DFA 的状态,单元格代表该状态经输入某个字符之后进行转移的目标状态。此外还有一张表用来记录哪些状态对应哪些规则的结束状态
确定有限自动机(英语:deterministic finite automaton, DFA)是一个能实现状态转移的自动机。对于一个给定的属于该自动机的状态和一个属于该自动机字母表的字符,它都能根据事先给定的转移函数转移到下一个状态(这个状态可以是先前那个状态)
这种模型就叫做有穷自动机(finite automation,FA),有时也叫有穷状态机(finite state machine)。
,还有一种非确定性有穷自动机(NFA),
string1 = null; 这句代码中的string1是一个标识符,代表一个变量。如果词法扫描器刚刚扫描到string,就报告发现了“关键字string”,那这里逻辑就不对 了。而如果等到DFA状态抓换到停机状态时再判断,就能判断到最长可能的的单词。比如,当词法分析器分析到了string时,它仍然没有停机,于是就输入 了下一个字符"1",这时词法分析的状态就从接受“关键字string”的状态转换到接受“标识符”的状态;然后词法分析器发现下一个字符是空格,而空格 接在string1后面并不是任何合法的单词,所以它就会转到停机状态。最后我们判断停机前最后一个状态是接受“标识符”的状态,于是报告成功扫描标识符 string1。这样就实现了最长匹配的目的。
先来看miniSharp的词法分析。miniSharp语言的单词根据优先级和不同种类可以分成以下五类:
1. 关键字
2. 标识符
3. 整型数字常量
4. 各种标点符号
5. 空白符、换行符和注释
必须识别为保留字,标识符(变量),常量,操作符(运算符 )和界符五大类 2
我们现在需要寻找一种可以描述token类型的工具,在此之前我们首先研究一下常见的记号的结构。为了表示出具有某种共性的字符串的集合,我们需要书写出一些能代表字符串集合的规则。这个集合中的所有成员都将被认为是一种特定类型的记号。
,直接使用正则表达式进行匹配配的话,不仅工作量大,而且速度缓慢。因此我们还需要另外一种专门为机器设计的表达方式。本文在以后的章节中会给出 一种算法把正则表达式转换为机器可以阅读的形式,就是这一章节所描述的有穷状态自动机。
从正则表达式到ε-NFA
7.3.1. DFA的局限
DFA是一種实际的计算模型,因为有平凡的线性时间、恒定空间的在线算法模拟在输入流上的DFA。给定两个DFA有有效算法找到识别它们所识别语言的并集、交集和补集的DFA。还有有效算法确定一个DFA是否接受任何给定字符串,一个DFA是否接受所有字符串,两个DFA是否识别同样的语言,和对特定正则语言找到状态数目最小的DFA(最小DFA)。
在另一方面,DFA在可识别的语言上有严格的限制—很多简单的语言,包括需要多于恒定空间来解决的任何问题,不能被DFA识别。经典的DFA不能识别的简单语言的例子是括号语言,就是由正确配对的括号组成的语言,比如 (()())。由形如anbn的字符串组成的语言,就是有限数目个a,随后是相等数目个b。可以证明没有DFA有足够状态来识别这种语言(通俗地说,因为需要至少2n个状态,而n是不恒定的)。
8. 参考
NFA_DFA算法 - 于公摊的杂货铺 - 博客频道 - CSDN.NET.htm
自己动手开发编译器(二)正则语言和正则表达式 - 装配脑袋 - 博客园.htm
Atitit. 有限状态机 fsm 状态模式 - attilax的专栏 - 博客频道 - CSDN.NET.htm
atitit.词法分析的实现token attilax总结 - attilax的专栏 - 博客频道 - CSDN.NET.htm
Atitit.注解解析(1)---------词法分析 attilax总结 java .net - attilax的专栏 - 博客频道 - CSDN.NET.htm