编译原理 词法分析

词法分析负责将字符流转为符号流(单词流)

注意:空格已经被删掉,因为没有具体的意义,在文末追加eof。

词法分析的实现方案: 1. 手工编码 GCC LLVM 2. 词法分析器的生成器 自动生成 

手工构造:

代码实现:

通过状态转移图进行识别,如果识别到了其他字符,如>a,识别到了a,那么需要回滚,即*处。

自动生成的方式:

输入声明式的规范,经过工具如c(lex flex),可以自动产生一个词法分析器。

1)如何获得声明式的规范? 正则表达式

 如何使用正则表达式表示程序语言设计中的词法?

语法糖 syntax sugar 

语法糖简化了编写。

声明式的规范即是re 正则表达式

2)如何实现该工具?

3)词法分析器

有限状态自动机

状态转移函数(q0,a)->q1,即当在q0状态遇到a时,转移到q1状态

从q0经过a,可以走到q0,q1即下一状态是一个状态集合(NFA 非确定)。

如果在所有状态上对于单一字符,下一个状态是确定的,则是DFA(确定的)。

NFA对于一个字符是否能走到可接受状态并不确定,因此可能需要回溯。

注意,NFA存在空串,即表示从一个状态转移到另一个状态可以通过空串转移,即直接跳转。

DFA的实现:有向图 1. 边上的信息 (字符)2.节点信息(如输入节点,输出节点)

如何从RE转换到NFA?

1. Thompson 算法 RE-> NFA

 

 

如下图所示即为该表达式对应的正则表达式

NFA->DFA

即将一个节点经过一个字符后能够达到的状态集合归纳为一个集合

需要注意的是,接受状态n9包括在了多个集合中,q1,q2都是接受状态。

1. 先对任何一个子集求转换过程,求结果

2.对结果求delta

基于深度优先去做

基于宽度优先去做

NFA转换为DFA

D[q,c]<- t 即为将子集之间字符读取,状态转换关系进行记录

worklist就是每次得到的状态的集合,实际上类似于深度优先节点中的父节点连接其子节点

q1,q2,q3中都有n9,除q0外都是接受状态。

子集构造算法:

1. esp_closure 给定一个集合,确定集合中起始节点经过eps转换能够达到的状态;

2. Q DFA里面所有的有限状态自动机

3. worklist 队列

4. 进入worklist的循环

    对于每一个字符,asic码c, 

     delta(q,c) 经过字符c可以到达的状态,改状态经过e-close,得到t

    则将q经过可以到达t的关系记录到D中(DFA)

最终所有的NFA中的状态都被考虑过了。

DFA的最小化:

Hopcropft对DFA进行最小化

q2,q3都包括接受状态,可以合并,q1和q4也可以合并

n非接受状态,a接受状态

对于所有的char b c A的集合都不会被分割,因此将q1,q2,q3合并为集合A

实际上是将经过输入状态的字符后,仍然跳转到相同状态的状态合并为一个集合

DFA的代码表示:

DFA是一个有向图,图,就可以用表来表示。

转移表 有n*m,n为状态集合个数,m为字符个数

nextToken 每次返回一个识别的字符

在while循环中,如果是接受状态,则清空,通过table【state】【c】进行查表

当读取到结束字符后面的字符时,将栈弹出,rollback 回退,回退回去

stack用于实现最长匹配 

栈底每次都是接受状态,每次接收到接受状态后,清空栈,将接受状态作为栈底。

当接受失败后,回滚,直到回滚到接收到状态弹出栈,即最后一个匹配的,最长匹配。

跳转表每个状态对应一长段代码

当使用代码失陷后,跳转表比转移表局部性更好,转移表可能代码量很大(状态很多),而跳转表每次只执行一段。

实验1 词法分析 一、 实验目的 调试并完成一个词法分析程序,加深对词法分析原理的理解。 二、 实验要求 1、 待分析的简单语言的词法 (1) 关键字: begin if then while do end 所有关键字都是小写。 (2) 运算符和界符: := + – * / < <= <> > >= = ; ( ) # (3) 其他单词是标识符(ID)和整型常数(NUM),通过以下正规式定义: ID=letter(letter| digit)* NUM=digit digit * (4)空格由空白、制表符和换行符组成。空格一般用来分隔ID、NUM,运算符、界符和关键字,词法分析阶段通常被忽略。 2、 各种单词符号对应的种别码 单词符号 种别码 单词符号 种别码 begin 1 : 17 if 2 := 18 then 3 > 20 while 4 <> 21 do 5 <= 22 end 6 < 23 letter(letter| digit)* 10 >= 24 digit digit * 11 = 25 * 13 ; 26 / 14 ( 27 + 15 ) 28 - 16 # 0 3、 词法分析程序的功能 输入:所给文法的源程序字符串。 输出:二元组(syn,token或sum)构成的序列。 其中:syn为单词种别码; token为存放的单词自身字符串; sum为整型常数。 三、结果验证 给定源程序 begin x:=9; if x>0 then x:=2*x+1/3; end# 输出结果。 四、源程序代码如下: #include<stdio.h> #include<string.h> #include<iostream.h> char prog[80],token[8]; char ch; int syn,p,m=0,n,sum=0; //p是缓冲区prog的指针,m是token的指针 char *rwtab[6]={"begin","if","then","while","do","end"}; void scaner() { for(n=0;n<8;n++) token[n]=NULL; ch=prog[p++]; while(ch=='_') 执行语句1; if((判断ch是字母字符的条件)) { m=0; while((ch>='A'&&ch<='Z')||(ch>='a'&&ch<='z')||(ch>='0'&&ch<='9')) { token[m++]=ch; ch=prog[p++];} token[m++]='\0'; p--; syn=10; for(n=0;n<6;n++) if(加入判断条件) {syn=n+1; break; } } else if(判断ch是数字字符的条件)' { sum=0; while(ch>='0'&&ch<='9') { sum=sum*10+ch-'0'; ch=prog[p++]; } p--;执行语句2; } else ………完成剩余程序代码 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值