atitit.自己动手开发编译器and解释器(1) ------词法分析--attilax总结

1.   应用场景:::DSL 大大提升开发效率 1

2. 2. 流程如下::: 词法分析(生成token流) >>>>语法分析(生成ast) >>解释执行... 2

3. 如何进行词法分析?Fsm状态机(自动机)
2

4. 使用状态模式构建FSM  (简单,易用。。推荐首选) 2

5. ---代码( 状态模式构建FSM ) 3

6. 词法分析概念 3

6.1. 词法分析(英语:lexical analysis)跟token
4

6.2. 五种token类型 4

7. 其他词法分析方法 5

7.1.  switchcase或者ifelse 5

7.2.  状态表
5

7.3. 使用NFA、DFA构建FSM( 专业方法,难度大) 6

7.3.1. DFA的局限 7

8. 参考 7

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

atitit.自己动手开发编译器and解释器(1) ------词法分析--attilax总结的更多相关文章

  1. atitit.自己动手开发编译器and解释器(2) ------语法分析,语义分析,代码生成--attilax总结

    atitit.自己动手开发编译器and解释器(2) ------语法分析,语义分析,代码生成--attilax总结 1. 建立AST 抽象语法树 Abstract Syntax Tree,AST) 1 ...

  2. 自己动手开发编译器(五)miniSharp语言的词法分析器

    稍微说明一点,整型常量和上面的标识符的词法,在调用lex.DefineToken时都多传了一个参数.这个参数是可选的描述信息,如果不传会直接使用正则表达式的字符串形式.而标识符的正则表达式有4万多个字 ...

  3. 自己动手开发编译器(四)利用DFA转换表建立扫描器

    上回我们介绍了两种有穷自动机模型——确定性有穷自动机DFA和非确定性有穷自动机,以及从正则表达式经过NFA最终转化为DFA的算法.有些同学表示还是难以理解NFA到底怎么转化为DFA.所以本篇开头时我想 ...

  4. atitit.提升软件开发的效率and 质量的那些强大概念and方法总结

    atitit.提升软件开发的效率and 质量的那些强大概念and方法总结 1. 主流编程中三个最糟糕的问题 1 1.1. 从理解问题后到实现的时间很长 1 1.2. 理解和维护代码  2 1.3. 学 ...

  5. Atitit. 提升软件开发效率and 开发质量---java 实现dsl 4gl 的本质and 精髓 O725

    Atitit. 提升软件开发效率and 开发质量---java 实现dsl 4gl 的本质and 精髓  O725 1. DSL主要分为三类:外部DSL.内部DSL,以及语言工作台. 1 2. DSL ...

  6. Linux 小知识翻译 - 「编译器和解释器」

    这次聊聊「编译器和解释器」. 编程语言中,有以C为代表的编译型语言和以Perl为代表的解释型语言.不管是哪种,程序都是以人类能够理解的形式记录的,这种形式计算机是无法理解的. 因此,才会有编译器和解释 ...

  7. 学了编译原理能否用 Java 写一个编译器或解释器?

    16 个回答 默认排序​ RednaxelaFX JavaScript.编译原理.编程 等 7 个话题的优秀回答者 282 人赞同了该回答 能.我一开始学编译原理的时候就是用Java写了好多小编译器和 ...

  8. Atitit codeblock c++开发环境建立attilax总结

    Atitit codeblock c++开发环境建立attilax总结 1.1. C++的重要意义 1 1.2. 项目ide的选项 1 1.3. 安装MinGW  (基于GCC的C++编译器)  50 ...

  9. java编写编译器和解释器

     on 2012-07-14 21:24 Bang 阅读(102) 评论(0) 编辑 收藏  续 第二部分 初始后端实现 框架后端支持编译器和解释器.现在框架抽象类Backend有两个极简版实现,一个 ...

随机推荐

  1. mysql求交集:UNION ALL合并查询,inner join内连接查询,IN/EXISTS子查询

    两个要求交集的表(列)的结构要一致,对应的字段数,字段类型都应该相同:将两个数据的数据列用 UNION ALL 关键字合并:将上面的所有需要比较的列 GROUP BY :最后 HAVING COUNT ...

  2. TYVJ 2002 扑克牌 题解

    P2002 扑克牌 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 Admin生日那天,Rainbow来找Admin玩扑克牌……玩着玩着Rainbow觉得太没 ...

  3. SQL Server 2005 中实现通用的异步触发器架构 (转)

    在SQL Server 2005中,通过新增的Service Broker可以实现异步触发器的处理功能.本文提供一种使用Service Broker实现的通用异步触发器方法. 在本方法中,通过Serv ...

  4. OpenStack 部署总结之:单节点icehouse网桥的配置

    部署完icehouse,安装完实例之后.假设虚拟主机须要和外部进行通信.还须要对宿主机的网桥进行配置 宿主机的配置 改动ifcfg-em1的内容为下面内容: DEVICE=em1 ONBOOT=yes ...

  5. 【转】四大机器学习降维算法:PCA、LDA、LLE、Laplacian Eigenmaps

    最近在找降维的解决方案中,发现了下面的思路,后面可以按照这思路进行尝试下: 链接:http://www.36dsj.com/archives/26723 引言 机器学习领域中所谓的降维就是指采用某种映 ...

  6. GIL线程全局锁 协程

    GIL线程全局锁 线程全局锁(Global Interpreter Lock),即Python为了保证线程安全而采取的独立线程运行的限制,说白了就是一个核只能在同一时间运行一个线程.对于io密集型任务 ...

  7. vb.net 鼠标控制

    Public Class Form1 Public Declare Sub mouse_event Lib "user32" Alias "mouse_event&quo ...

  8. 微信小程序 - 输入起点、终点获取距离并且进行路线规划(腾讯地图)

    更新: 2018-9-19 腾讯官方经纬度转详细地址,详细地址转经纬度 index.wxml <!--地图容器--> <map id="myMap" style= ...

  9. 聊聊高并发(二十)解析java.util.concurrent各个组件(二) 12个原子变量相关类

    这篇说说java.util.concurrent.atomic包里的类,总共12个.网上有非常多文章解析这几个类.这里挑些重点说说. watermark/2/text/aHR0cDovL2Jsb2cu ...

  10. Java之开发工具(1) - Eclipse 如何设置注释的模板

    最常用的注释就是对类的说明和方法的说明,关于这类代码的注释方式,在Eclipse中可以这样进行设置: windows---preferences...---java--code style--code ...