文档库 最新最全的文档下载
当前位置:文档库 › 词法分析(NFA&DFA)

词法分析(NFA&DFA)

词法分析(NFA&DFA)
词法分析(NFA&DFA)

词法分析(NFA与DFA)

词法分析(1)---词法分析的有关概念以及转换图

词法分析是编译的第一个阶段,前面简介中也谈到过词法分析器的任务就是:字符流------>词法记号流

这里词法分析和语法分析会交错进行,也就是说,词法分析器不会读取所有的词法记号再使用语法分析器来处理,通常情况下,每取一个词法记号,就送入语法分析器进行分析,图解:

词法分析器是编译器中与源程序直接接触的部分,因此词法分析器可以做诸如

1).去掉注释,自动生成文档(c#中的///注释)

2).提供错误位置(可以通过记录行号来提供),当字符流变成词法记号流以后,就没有了行的概念

3).完成预处理,比如宏定义

1.词法记号,词法单元(lexeme),模式

模式是一种规则

每个词法单元都有一个特定记号

比如 int a=3,这里 int,a,=,3都是词法单元,每个词法单元都属于某个词

法记号,比如3就是"num"这个词法记号的一个词法单元,而模式规定了什么样的字符串的词法记号是什么样的(模式是一种规则)

某一特定模式规定了某个词法记号下的一类词法单元,比如:

模式:用字母开头的包含字母和数字的串

上面模式的词法记号:id(所有符合上面模式的字符串的记号都是id)

词法单元:a123或者 aabc等

词法记号举例(简称为记号):

1)每个的关键字都有属于自己的一个记号,比如关键字for,它可以使用记号f or;关键字int,可以使用记号int

2)所有的关系运算符只有一个记号,比如 >=,<=都用记号relation

3)所有的标识符只有一个记号,比如a123,aab使用记号id

4)所有的常数只有一个记号,比如123,22,32.3,23E10使用记号num

5)所有的字符串只有一个记号,比如"123","ab1"使用记号literal

在实际的编译器设计中,词法记号,一般用一个整形数字表示

词法记号的属性:

我们喜欢用<词法记号,属性>这个二元组来描述一个词法单元,比如,对于源代码:position := initial + rate * 60

对于词法单元 +,我们可以使用 来表示。

有些情况,更加复杂一点,比如对于 position,我们表示是这样的,,详细来说应该是这样的,假定属性是一个字符串,那么id将指向这样一个字符串"position\0",我们把存放这个字符串的地方叫做符号表。有些时候,属性是不必要的,比如 :=,表示赋值,我们可以使用 这样的表示这个词法单元,不过这个显得有些多于,因为assign_op和词法单元是一对一的,也就是assign_op只对应了:=,所以额外信息(属性)就显得多余的了

词法错误:

词法分析器是很难(有些错误还是可以检测)检测错误的,因为词法分析器的目的是产生词法记号流,它没有能力去分析程序结构,因此无法检测到和程序结构有关的错误,比如:

fi(a == b)

词法分析器不会找到这个错误,它认为 fi是一个标识符,而不是一个关键字,只有在后面的阶段中,这个错误才会被发现,这是一个与程序结构有关的错误词法分析器,只能检测到词法单元上的问题,比如 12.ab,作为一个词法单元,却不没有对应的模式,那么就是产生一个错误。

2.正规式:

前面说过模式是一种规则,为了使用,我们需要一种规范的方式来表达模式,这就是正规式

1)串和语言

字符类(又叫字母表):关于字符的有限集合

串:字符类上字符的有穷序列,串这个概念,具体来说是,某个字符类上的串串的长度:串中字符的个数,比如串 s = abc,那么串的长度为3,用|s|表示串的长度

空串:用ε表示

语言:某字符类上的串的集合,属于语言的串,成为语言的句子或字

比如:{abc, a}这就是一个语言,abc和a就是句子。另外空集也是属于语言

连接:x是串,y是串,x和y连接,结果就是 xy这个串。假如 x是串,x^3为 xxx。对于 x^n (n>=0),x^0 = ε

语言的运算(假定L和M是语言):

1. L U M = {s|s属于L或者M},例如:

L={1,2} M={3,4}那么 L U M = {1,2,3,4}

2. LM = {st|s属于L且t属于M},例如:

L={a,b} M={1,2}那么 LM = {a1,a2,b1,b2} ML={1a,1b,2a,2b}

3. L^n = LLL...LLL (n个L),例如:

L={a,b}那么 L^3 = {aaa,aab,aba,abb,baa,bab,bbb,bba}

注意 n可以为0,L^0 = {ε}

4. L* = L^0 U L^1 U L^2 U L^3 U ...

L*表示,语言L中,所有的句子(串)以任意数目任意顺序组成的句子的集合,包括ε,例如:

{a,b}* = {ε,a,b,ab,ba,aab,aba,baa,bba,bab,abb,aaa,bbb...}

L*叫做L的闭包

5. L+ = L^1 U L^2 U L^3 U...

L+表示,语言L中,所有的句子(串)以任意数目任意顺序组成的句子的集合,但是不包括ε

L+中的句子和 L*中的句子相比少一个ε

那么,我们通过上面的知识就可以表示一个标识符了,我们知道一般语言规定标识符是由字母开头,后接若干个字母或数字,我们可以这样来表示: L={a-z A -Z} N={0-9},那么标识符就是 L(L U N)*

2)正规式

正规式又叫正规表达式,正规式是模式得一种规范的表达形式,正规式描述了一个集合,这个集合是由串组成的,其实这个集合就是我们前面说过的语言,不过这里大家喜欢使用正规集这个术语。正规式 r表示正规集L(r)

正规式的运算:

1.闭包运算,运算优先级最高,(r)*表示 (L(r))*

2.连接运算,运算优先集合低于闭包,(r)(s)表示 (L(r))(L(s))

3.或运算,运算优先集合最低,(r) | (s)表示 (L(r)) U (L(s))

例如:

a | b表示集合(语言,正规集) {a,b}

(a | b)(a | b)表示集合(语言,正规集) {aa,ab,ba,bb}

a*表示由一切a字符组成的集合(语言,正规集),包括ε

(a | b)表示由a,b组成的集合(语言,正规集),包括ε

等价的正规式:(a | b) = (b | a)

正规式的代数性质:

1. r|s = s|r

2. r|(s|t) = (r|s)|t

3. (rs)t = r(st)

4. r(s|t) = rs|rt

5. εr = r

6. r** = r*

7. r* = (r|ε)*

注意,rs != sr因为连接运算是有顺序的,记住并理解2个最基本的运算:a|b 表示{a,b},ab表示{ab}

3.正规定义

我们可以使用名字 ->正规式这种表示,来说明一个等价的代替,比如:

dight -> 0|1|2|3|4|5|6|7|8|9

这里,我们就可以使用名字 digit来代替后面的正规表达式

我们可以对某个串集进行正规定义,比如我们对标识符集合进行正规定义:

letter -> A|B|...|Z|a|b|...|z

dight -> 0|1|2|3|4|5|6|7|8|9

id -> letter(letter|dight)*

请通过上面的例子理解正规定义。

在我们表达正规表达式的时候,可以使用一些符号使得表达简化

1) +,表示一个或者多个实力,比如,a+表示 {a,aa,aaa,aaaa,...}。区别一下*,他们的关系是这里 r+ = r* | ε

2)字符组,[abc]表示a|b|c,还可以这样表示[a-zA-Z]表示字母表中的字符

4.状态转换图

状态转换图是对词法分析器进行分析过程的描述,我们看一个判断关系运算的状态转化图:

1)图中圆圈表示状态

2)箭头叫做边。X状态的边,一般指的是由X状态出发,指向其他状态的边

3)边上的符号叫做标记

如何来使用这个图?假定输入字符串是 <=,那么识别开始时,发现 <和状态0与状态1间的边上的标记一样,那么就进入1状态,下一个输入字符为=,将进入2状态,识别结束,返回二元组

上图中2,3,4,5,7,8状态,他们表示识别了一个关系运算符,这个状态叫做接受状态

状态4上面有一个*,表示说,输入指针需要回移。所谓的输入指针,就是指向输入字符串中现在被读入的字符的位置,4状态会多读取一个字符,所以需要回移,也就是要注意的是,识别完成之后,输入指针指向的是被识别对象的最后一个字

符,而不是待识别对象的第一个字符,这样的规定在实现词法分析器时,是有一定的意义,举例说明:

输入字符串为: a>b

识别的时候,从>开始,读入下一个字符b时,进入4状态,这个时候,输入指针指向b,这时候需要回移

我们在需要回移的状态上加一个*

每个状态后面有一个return(relop,XX)这个是状态的行为,这里具体来说就是返回一个二元组的行为,词法分析器分析的结果就是得到二元组(词法记号和属性的二元组),这个二元组可以表示一个特定的字符串。其实上面的*,也是表示行为,也就是输入指针回移的行为,我们可以看见,只有在接受状态才会有行为出现

对一门典型的语言来说状态可能有几百个

5.如何编写一个词法分析器

1)根据需要写出正规定义

2)根据正规定义画出转换图

3)根据转换图写出词法分析器

这里详细讨论面向过程的语言来实现一个词法分析器(比如c语言),并且主要讨论的是第3步

1)我们需要一个 nextchar()函数,取得缓存中下一个等待分析的字符,这个函数完成年2个任务

1.让输入指针向前移动一位

2.返回输入指针指向的字符

2)定义一个变量 token_beginning,在每个状态转换图开始的时候,记录输入指针的位置,定义forward变量作为输入指针

3)状态转换图被实现成为代码之后,每个状态都有属于自己的一块代码,这些代码按顺序完成以下工作:

1.读取一个字符,通过nextchar()函数

2.读取的字符(标志),如果它和当前状态的边上的标记相同,那么状态将

转换到边所指向的状态,具体实现只需要一个语句就是 state = xxx(xxx 为目标状态);如果当前状态的所有边的标记和这个读取字符不一样,那么表示没有找到token(词法记号),这时候需要调用 fail()函数

3.fail()函数完成这样的功能:a.指针回移,完成 forward= token_be

ginning的操作 b.找到适当的开始状态(也就是寻找另外一个转换图的开始状态)。假定所有的转换图都被尝试过,并且无法匹配,这时候会调用一个发现错误的小程序,来报告错误

4.请不要随意添加行为到各个状态所持有的代码中,应该以转换图中表示

的行为为准

4)定义一个全局变量lexical_value,用于保存一个指针,这个指针由install_id()和 install_num()两个函数中的一个返回

5)定义两个整形变量 start,state,分别表示一个转换图的开始状态和当前的状态

6) nexttoken(),这是词法分析器的主程序,可以说,我们通过调用nexttoken()就完成了词法分析,这个函数一定是这样的格式:

while(1){

switch(state){

case xx:

...

case yy:

...

default:

...

}

}

关于详细的设计这里就不说了,举例说明一个转换图如何转换成为程序:

这是一个识别浮点数的例子,看下面的代码:

#include

#include

#include

char *nexttoken();

char nextchar();

void next();

void back();

char* gettoken();

char cbuf[]="12.3*********klj12.2e2jj778"; int forward = -1;

int main(){

while(1){

printf("%s\n",nexttoken());

if(forward >= strlen(cbuf)-1){

getchar();

return 0;

}

}

}

int state;

int start;

char* nexttoken(){

char c;

state = 12;

while(1){

switch(state){

case 12:

start = forward;

if(isdigit(c)){

state = 13;

}else{

next();

}

break;

case 13:

c = nextchar();

if(isdigit(c))

state = 13;

else if(c == 'e'||c == 'E') state = 16;

else if(c == '.')

state = 14;

else

state = 19;

break;

case 14:

c = nextchar();

if(isdigit(c))

state = 15;

break;

case 15:

c = nextchar();

if(isdigit(c))

state = 15;

else if(c == 'e'|| c == 'E')

else

state = 19;

break;

case 16:

c = nextchar();

if(isdigit(c))

state = 18;

else if(c == '+' || c == '-') state = 17;

break;

case 17:

c = nextchar();

if(isdigit(c))

state = 18;

break;

case 18:

c = nextchar();

if(isdigit(c))

state = 18;

else

state = 19;

break;

case 19:

back();

return gettoken();

}

}

}

char nextchar(){

forward ++;

return cbuf[forward];

}

void back(){

forward --;

}

void next(){

forward ++;

}

char token_buf[128];

char* gettoken(){

int i,j=0;

for(i = start; i <= forward; i ++){ token_buf[j++] = cbuf[i];

}

token_buf[j] = '\0';

return token_buf;

}

词法分析(2)---NFA

假定一个输入符号(symbol),可以得到2个或者2个以上的可能状态,那么这个f inite automaton就是不确定的,反之就是确定的。例如:

这就是一个不确定的无限自动机,在symbol a输入的时候,无法确定状态应该转向0,还是1

不论是确定的finite automaton还是非确定的finite automaton,它们都可以精确的描述正规集(regular sets)

我们可以很方便的把正规表达式(regular expressions)转换成为不确定 finit e automaton

2. NFA(Nondeterministic Finite Automaton)

非确定的无限自动机,我们用NFA这个术语表示,它是一个数学模型(model):

1.一个关于状态的集合S

2.一个关于输入符号(input symbols)的集合Σ

3.函数 move : (状态,符号) -> P(S)

4.一个开始状态s0,是一个唯一的状态

5.一个结束(接受)状态集合F

注意,P(S),表示S的幂集。在NFA中,input symbol可以为ε

转换函数(transition function)的含义就是,一个确定的状态已经从这个状态出发的一条边的标签(符号symbol),可以确定它的下一个状态组成的集合,比如上图(这个转换图就是NFA的一种表示方式),0状态,a符号,确定了一个状态的集合{0,1}

3.转换图(transition graph)的表示

我们知道,计算机是无法直接表示一个图,我们应该如何来表示一个转换图?使用表格就是一个最简单的方法,每行表示一个状态,每列表示一个input symbol,这种表格被叫做 transtion table(转换表)

可以说使用表格是最简单的表示方式,但是我们可以注意到在这个图中状态1和input symbol a,是没有下一个状态的(空集合),也就是,对于一个大的状态图,我们可能花费大量的空间,而其中空集合会消耗不少空间,但是这种消耗又不是必须的,所以,作为最简单的一种实现方式,却不是最优的

语言(language)被NFA定义成为一个input string的集合,而这个集合中的元素则是被NFA受接受的所有的字符串(那些可以从开始状态到某接受状态的input string)

至于存储的方式,可以试试邻接表。注意,使用什么样的数据结构来保存NFA 按情况不同而不同,在一些特殊情况下,某些数据结构会变得很方便使用,而换入其他情况,则不可以使用了。

词法分析(3)---DFA

1. DFA(Deterministic Finite automaton)

DFA就是确定的有限自动机,因为DFA和NFA关系密切,我们经常需要把他们拿到一起来讲,NFA可以转化成为一个DFA,DFA依然是一个数学model,它和NFA 有以下区别

1.不存在ε-transition,也就是说,不存在ε为input symbol的边

2.对于move函数,move : (state, symbol) -> S,具体来说就是,一个

状态和一个特定的input symbol,不会映射到2个不同的状态。这样的结果是,每个状态,关于每个特定的input symbol,只有一条出边

下图就是一个DFA:

接受语言(a|b)*ab,注意一下,接受语言(a|b)*ab的DFA我们前面见过,就是这张图:

2. DFA的行为

我们用一个算法来模拟DFA的行为

s = s0;

c = nextchar();

while(c != EOF){

s = move(s,c);

c = nextchar();

}

if(s属于F)

return "yes"

else

return "no"

词法分析(4)---NFA与DFA的转化

1.子集构造(Subset Construction)

这是一个转换NFA到DFA的算法。我们知道NFA和DFA的区别最主要的就是一个状态和一个input symbol是否能够确定一个状态的问题,对于NFA,它将确定一个组状态,而DFA将确定一个状态,因此,我们有一个很好的办法就是把NFA 的状态集对应每个DFA的状态,这就是subset construction的思想,不过这只是大概泛泛而论,我们需要更加明确的认识

1) NFA在任何一个input symbol下,映射的状态集(通过move函数,这个集合通常用T字母表示)应该被知道

2)必须保证1)中状态集都对应了DFA中的一个状态

具体算法:

Input :一个NFA N

Output :接受相同语言的DFA D

Method :为D构架一个transition table(转换表) Dtran,每个DFA的状态是一个NFA的状态集合(这里一定要注意前面说过的1)2)两点)。我们定义一些操作:

s表示NFA的状态,T表示NFA的状态集合,a表示一个input symbol

ε-transition(ε转换)就是说input symbol为ε时的transition(转换)操作(operation)描述(description)

ε-closure(s)从NFA的状态s出发,只通过ε-transition到达的NFA的状态

集合

ε-closure(T)NFA的集合T中的状态p,只通过ε-transition到达的NFA的状态集合,再求这些集合的交集。用数学表达就是 {p|p属于

ε-closure(t) , t属于T}

move(T,a)NFA的集合,这个集合在input symbol为a,状态为T中任意状态情况下,通过一个转换得到的集合

注意一下,所有的操作都是针对NFA的状态或者状态集合,得到的时NFA的状态集合,或者说是DFA看为一个状态

Subset Construction

初始Dstates,它仅仅含有状态(D的状态)ε-closure(s0),并且状态未被标记,s0表示开始状态,注意,Dstates放的是D的状态

while ( Dstates有未标记的状态 T ) { // T是D中的一个状态,也是N中一个状态集

标记 T;

for ( input symbol a ){ //遍历所有的input symbo l

U = ε-closure(move(T, a)); // move为NFA的move函数

if ( U不在 Dstates中 )

把U作为尚未标记的状态加入Dstates;

Dtran[T, a] = U

}

注意,状态s,ε-closure(s)一定包含s

我们先来熟悉上面的操作operation,再来看上面的算法

ε-closure(0) = {0, 1, 2, 4, 7} //从0状态出发的,input symbol为ε

的所有状态的集合

ε-closure(3) = {1, 2, 3, 4, 6, 7}

ε-closure(8) = {8}

ε-closure( {3, 8} ) = ε-closure(3) U ε-closure(8) = {1, 2, 3, 4, 6, 7, 8}

move(0,a) =空

move(7,a) = {8}

move(8,b) = {9}

move( {0, 1, 2, 4, 7}, a) = move(0,a) U move(1,a) U move(2,a) U move (4,a) U move(7,a) = {3, 8}

现在可以回去理解一下算法了。

这里再说说求ε-closure(T)的算法:

把T的所有状态压入stack(栈);

词法分析程序设计与实现

实验一词法分析程序设计与实现 一、实验目的及内容 调试并完成一个词法分析程序,加深对词法分析原理的理解。 二、实验原理(状态转换图) 1、C语言子集 (1)关键字: begin if then while do end 所有关键字都是小写。 (2)运算符和界符: := + –* / < <= <> > >= = ; ( ) # (3)其他单词是标识符(ID)和整型常数(NUM),通过以下正规式定义:ID=letter(letter| digit)* NUM=digit digit * (4)空格由空白、制表符和换行符组成。空格一般用来分隔ID、NUM,运算符、界符和关键字,词法分析阶段通常被忽略。 2、各种单词符号对应的种别码 3、词法分析程序的功能

输入:所给文法的源程序字符串。 输出:二元组(syn,token或sum)构成的序列。 其中:syn为单词种别码; token为存放的单词自身字符串; sum为整型常数。 二、软件平台及工具 PC机以及VISUAL C++6.0软件。 三、实验方法、步骤(或:程序代码或操作过程) (1)程序代码: #include #include #include char prog[80],token[8]; char ch; int syn,p,m=0,n,row,sum=0; 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==' ') { ch=prog[p]; p++; } if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')) { m=0; while((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')) { token[m++]=ch; ch=prog[p++];

C语言词法分析器构造实验报告

C语言词法分析器构造实验报告 02计算机(2)2002374203 冯绍欣 一、题目要求: 完成一个C语言的词法分析器的构造。此词法分析器能识别附值语句、循环语句、条件语句、并能处理注释。 二、设计方案: 这个词法分析器分析的主要关键字有:main, int, float, char, if, else, for, while, do, switch, case, break; default。选择要分析的c文件,首先对其去掉注释和与空格处理,再根据字符的不同类型分析。 1、全局数据结构: 字符数组set[ ]:存放从文件中读到的所有字符; str[ ]:存放经过注释处理和预空格处理的字符; strtoken[ ]:存放当前分析的字符; 结构体KEYTABLE:存放关键字及其标号; 全局字符变量ch:当前读入字符; 全局整型变量sr, to:数组str, strtoken 的指针。 2、以层次图形式描述模块的组成及调用关系 3、主要函数的设计要求(功能、参数、返回值): openfile:打开文件; GetChar:将下一个输入字符读到ch中,搜索指示器前移一字符位置; GetBC:检查ch中的字符是否为空白。若是,则调用GetChar直至ch中进入一个非空白字符;

Concat:将ch中的字符连接到strtoken之后; IsLetter 和IsDigit:布尔函数过程,分别判断ch中的字符是否为字母和数字; Reserve:整型函数过程,对strtoken中的字符串查找关键字表,若是关键字则返回编码,否则返回-1; Retract:将搜索指示器回调一个字符位置,将ch置为空白字符; reflesh:刷新,把strtoken数组置为空; prearrange1:将注释部分置为空格; prearrange2:预处理空格,去掉多余空格; analysis:词法分析; main:主函数。 4、状态转换图: 字符a包括:= , & , | , + , -- 字符b包括:-- , < , > , | , * 字符c包括:, , : , ( , ) , { , } , [ , ] , ! ,# , % , ” , / , * , + , -- , > , <, . 三、源代码如下: #include #include char set[1000],str[500],strtoken[20]; char sign[50][10],constant[50][10]; char ch; int sr,to,id=0,st=0; typedef struct keytable /*放置关键字*/ { char name[20];

词法分析器的实现与设计

题目:词法分析器的设计与实现 一、引言................................ 错误!未定义书签。 二、词法分析器的设计 (3) 2.1词的内部定义 (3) 2.2词法分析器的任务及功能 (3) 3 2.2.2 功能: (4) 2.3单词符号对应的种别码: (4) 三、词法分析器的实现 (5) 3.1主程序示意图: (5) 3.2函数定义说明 (6) 3.3程序设计实现及功能说明 (6) 错误!未定义书签。 7 7 四、词法分析程序的C语言源代码: (7) 五、结果分析: (12) 摘要:词法分析是中文信息处理中的一项基础性工作。词法分析结果的好坏将直接影响中文信息处理上层应用的效果。通过权威的评测和实际应用表明,IRLAS是一个高精度、高质量的、高可靠性的词法分析系统。众所周知,切分歧义和未登录词识别是中文分词中的两大难点。理解词法分析在编译程序中的作用,加深对有穷自动机模型的理解,掌握词法分析程序的实

现方法和技术,用c语言对一个简单语言的子集编制一个一遍扫描的编译程序,以加深对编译原理的理解,掌握编译程序的实现方法和技术。Abstract:lexical analysis is a basic task in Chinese information processing. The results of lexical analysis will directly affect the effectiveness of the application of Chinese information processing. The evaluation and practical application show that IRLAS is a high precision, high quality and high reliability lexical analysis system. It is well known that segmentation ambiguity and unknown word recognition are the two major difficulties in Chinese word segmentation. The understanding of lexical analyse the program at compile, deepen of finite automata model for understanding, master lexical analysis program implementation method and technology, using C language subset of a simple language compilation of a scanned again compiler, to deepen to compile the principle solution, master compiler implementation method and technology. 关键词:词法分析器?扫描器?单词符号?预处理 Keywords: lexical analyzer word symbol pretreatment scanner 一、引言 运用C语言设计词法分析器,由指定文件读入预分析的源程序,经过词法分析器的分析,将结果写入指定文件。本程序是在Visual?Studio环境下,使用C语言作为开发工具。基于实验任务

实验1-3 《编译原理》词法分析程序设计方案

实验1-3 《编译原理》S语言词法分析程序设计方案 一、实验目的 了解词法分析程序的两种设计方法之一:根据状态转换图直接编程的方式; 二、实验内容 1.根据状态转换图直接编程 编写一个词法分析程序,它从左到右逐个字符的对源程序进行扫描,产生一个个的单词的二元式,形成二元式(记号)流文件输出。在此,词法分析程序作为单独的一遍,如下图所示。 具体任务有: (1)组织源程序的输入 (2)拼出单词并查找其类别编号,形成二元式输出,得到单词流文件 (3)删除注释、空格和无用符号 (4)发现并定位词法错误,需要输出错误的位置在源程序中的第几行。将错误信息输出到屏幕上。 (5)对于普通标识符和常量,分别建立标识符表和常量表(使用线性表存储),当遇到一个标识符或常量时,查找标识符表或常量表,若存在,则返回位置,否则返回0并且填写符号表或常量表。 标识符表结构:变量名,类型(整型、实型、字符型),分配的数据区地址 注:词法分析阶段只填写变量名,其它部分在语法分析、语义分析、代码生成等阶段逐步填入。 常量表结构:常量名,常量值 三、实验要求 1.能对任何S语言源程序进行分析 在运行词法分析程序时,应该用问答形式输入要被分析的S源语言程序的文件名,然后对该程序完成词法分析任务。 2.能检查并处理某些词法分析错误 词法分析程序能给出的错误信息包括:总的出错个数,每个错误所在的行号,错误的编号及错误信息。 本实验要求处理以下两种错误(编号分别为1,2): 1:非法字符:单词表中不存在的字符处理为非法字符,处理方式是删除该字符,给出错误信息,“某某字符非法”。 2:源程序文件结束而注释未结束。注释格式为:/* …… */ 四、保留字和特殊符号表

C++实现词法分析器

#include #include using namespace std; char inchar[80], token[8]; char character; int zbbm, p, m = 0, n, row, sum = 0; char *blz[6] = { "while", "if", "else", "switch", "case" }; void input() { for (n = 0; n<8; n++) token[n] = NULL; character = inchar[p++]; while (character == ' ') { character = inchar[p]; p++; } if ((character >= 'a'&&character <= 'z') || (character >= 'A'&&character <= 'Z')) { m = 0; while ((character >= '0'&&character <= '9') || (character >= 'a'&&character <= 'z') || (character >= 'A'&&character <= 'Z')) { token[m++] = character; character = inchar[p++]; } token[m++] = '\0'; p--; zbbm = 6; for (n = 0; n<5; n++) if (strcmp(token, blz[n]) == 0) { zbbm = n + 1; break; } } else if ((character >= '0'&&character <= '9')) { { sum = 0; while ((character >= '0'&&character <= '9')) { sum = sum * 10 + character - '0'; character = inchar[p++]; } } p--; zbbm = 7; if (sum>32767) zbbm = -1; } else switch (character) { case'<':m = 0; token[m++] = character; character = inchar[p++]; if (character == '=') { zbbm = 11; token[m++] = character; }

编译原理词法分析程序的设计实验报告

编译原理词法分析程序设计实验报告 【实验目的】 1.了解词法分析的主要任务。 2.熟悉编译程序的编制。 【实验容】 根据某文法,构造一基本词法分析程序。找出该语言的关键字、标识符、整数以及其他一些特殊符号,给出单词的种类和值。 【实验要求】 1.构造一个小语言的文法 类C小语言文法(以EBNF表示) <程序>::=<分程序>{<分程序>} . <分程序>::=<标识符>’(’<变量说明部分>{,<变量说明部分>}’)’<函数体> <变量说明部分>::=int<标识符>{,<标识符>} <函数体>::=’{’[<变量说明部分>;]<语句序列>’}’ <语句序列>::=<语句序列>;<语句>|<语句> <语句>::=<赋值语句>|<条件语句>|<循环语句>|<函数调用语句> <赋值语句>::=<标识符>=<表达式> <表达式>::=[+|-]<项>{<加法运算符><项>} <项>::=<因子>{<乘法运算符><因子>} <因子>:=<标识符>|<无符号整数> <加法运算符>::= +|- <乘法运算符>::= *|/ <条件语句>::=if<条件>’{’<语句序列>’}’[else’{’<语句序列>’}’] <条件>::=<表达式><关系运算符><表达式> <关系运算符>::= ==|!=|>|<|>=|<= <循环语句>::=for’(’<表达式>;<条件>;<表达式>’)’ ’{’<语句序列>’}’

<函数调用语句>::=<标识符>’(’<标识符>{,<标识符>}|<空>’)’ <标识符>::=<字母>{<字母>|<数字>} <无符号整数>::=<数字>{<数字>} <字母>::=a|b|c|…|X|Y|Z <数字>::=0|1|2|…|8|9 单词分类情况 关键字:int if else for 标识符:以字母开头的字母和数字的组合 关系运算符: ==|!=|>|<|>=|<= 加法运算符:+|- 乘法运算符: *|/界符:,;{ } ( ) 2.设计单词的输出形式,单词的种类和值的表示方法 种别码单词值 如:1 int 3. 编写词法分析程序cffx.c 实现基本的词法分析器,能够分析关键字、标识符、数字、运算符(需要有“==”或“:=”之类需要超前搜索的运算符)以及其他一些符号。 // 编译原理词法分析程序.cpp #include #include #include typedef struct words { int id; char name[20]; char value[20]; }word; char integer[20]={'i','n','t'}; char iff[20]={'i','f'}; char elsee[20]={'e','l','s','e'}; char forr[20]={'f','o','r'}; int main() { char code[10000];

实验一、词法分析器(含源代码)

词法分析器实验报告 一、实验目的及要求 本次实验通过用C语言设计、编制、调试一个词法分析子程序,识别单词,实现一个C语言词法分析器,经过此过程可以加深对编译器解析单词流的过程的了解。 运行环境: 硬件:windows xp 软件:visual c++6.0 二、实验步骤 1.查询资料,了解词法分析器的工作过程与原理。 2.分析题目,整理出基本设计思路。 3.实践编码,将设计思想转换用c语言编码实现,编译运行。 4.测试功能,多次设置包含不同字符,关键字的待解析文件,仔细察看运行结果,检测该分析器的分析结果是否正确。通过最终的测试发现问题,逐渐完善代码中设置的分析对象与关键字表,拓宽分析范围提高分析能力。 三、实验内容 本实验中将c语言单词符号分成了四类:关键字key(特别的将main说明为主函数)、普通标示符、常数和界符。将关键字初始化在一个字符型指针数组*key[]中,将界符分别由程序中的case列出。在词法分析过程中,关键字表和case列出的界符的内容是固定不变的(由程序中的初始化确定),因此,从源文件字符串中识别出现的关键字,界符只能从其中选取。标识符、常数是在分析过程中不断形成的。 对于一个具体源程序而言,在扫描字符串时识别出一个单词,若这个单词的类型是关键字、普通标示符、常数或界符中之一,那么就将此单词以文字说明的形式输出.每次调用词法分析程序,它均能自动继续扫描下去,形成下一个单词,直到整个源程序全部扫描完毕,从而形成相应的单词串。 输出形式例如:void $关键字

流程图 、程序 流程图: 开始 输入源文件路径 路径是否有 效 是初始化文件指针 否 将字符加入字符数 组Word[] 是空格,空白或换 行吗 是字母吗是数字吗否否是界符吗否打开源文件 跳过该字符 是是 文件结束? 否 将字符加入字符数 组Word[] 否 将字符加入字符数组Word[] 是 指向下一字符识别指针内容 指向下一字符 是字母惑数字 吗 是 将word 与关键字表key 进行匹 配 否匹配?是输出word 为关键字 输出word 为普通标示符 否将字符加入字符数组Word[] 指向下一字符输出word 为常数 识别指针内容 回退 是数字吗 是 否输出word 为界符 指向下一字符 结束 是输出Word 内容为不可识别 将字符加入字符数组Word[]

单词的词法分析程序设计

单词的词法分析程序设计 1实验题目 对于给定的源程序(如C语言或Pascal等),要求从组成源程序的字符行中寻找出单词,并给出它们的种别和属性——输出二元组序列。以便提供给语法分析的时候使用。要求能识别所有的关键字,标志符等,并且能够对出先的一些词法规则的错误进行必要的处理。 2 实验内容和要求 1. 给出语言的词法规则描述 2. 要求识别标识符、关键字、整常数、字符常数、浮点常数等 3. 要求能识别单界符:+,-,÷,×,:等符号 4. 双界符:/*,:=,等 5. 要求完成一些相关的辅助任务。一个任务实滤掉源程序中的注释、空格、制表符、换行符;另一个任务是使编译器能够将发现的错误信息与源程序的出错位置联系起来,以及错误的类型等。 3 待分析的词法文件 文件名称为:C:\1.txt (分析结果见7:程序结果) 4实验分析与设计过程 实验分析与设计过程 1. 实验说明 分析语言的选择:由于对C语言比较熟悉,我选择分析的程序为C语言编写的程序。 2. 词法分析器的功能以及输出形式分析 1) 功能: i. 对于输入的C源程序,输出单词符号,把相应的源程序的字符串转 换成单词符号的序列。 ii. 保存符号表,为所有的标识符建立一个符号表,以便于在语法和语义分析的时候使用。 iii. 错误输出与提示

2) 结果输出形式: i. 对于token用二元组输出, ii. 符号表可以单独输出到文件中 iii. 错误输出到界面即可 3. 单词符号的表示 各种关键字(保留字、基本字),各种运算符、各种分界符,都用一个种别码来标识。例:关键字break、保留字asm、运算符”+”、在源程序中1,2,3表示。即所规定得到的中别码对应的词法描述为: 1为关键字2为标志符 3为常数4为运算符或界符 5 算法描述 由于这是一个用高级语言编写一个词法分析器,使之能识别输入串,并把分析结果(单词符号,标识符,关键字等等)输出.输入源程序,输入单词符号,本词法分析器可以辨别关键字,标识符,常数,运算符号和某些界符,运用了文件读入来获取源程序代码,再对该源程序代码进行词法分析,这就是词法分析器的基本功能.当词法分析器调用预处理子程序处理出一串输入字符放进扫描缓冲区之后,分析器就从此缓冲区中逐一识别单词符号.当缓冲区里的字符串被处理完之后,它又调用预处理子程序来处理新串. 编写的时候,使用了文件的输入和输出,以便于词法分析的通用型,同时在文件输出时,并保存在输出文件output文件中。 从左到右扫描程序,通过初始化:1为关键字;2为标志符; 3为常数;4为运算符或界符。 扫描过程如下: 1.指针扫描所打开的文件首,如果是字母开始处理字符关键字或者标识符2.为单字符运算、限界符,写入输出文件并将扫描文件指针回退一个字符; 3.为双字符运算、限界符,写输出文件; 4.读入的下一个字符为文件结束符; 5.只考虑是否为单字符运算、限界符,若是,写输出文件

编译原理实验报告《词法分析器的构造》

《词法分析器的构造》实验报告 一、实验名称 词法分析器的构造 二、实验目的 设计、编制、调试一个词法分析程序,对单词进行识别和编码,加深对词法分析原理的理解。 三、实验内容和要求 编写一个C语言词法分析器,要求: 1、允许用户自己输入源程序并保存为文件 2、系统能够输出经过预处理后的源程序(去掉注释、换行、空格等) 3、能够将该源程序中所有的单词根据其所属类型(整数、保留字、运算符、标识符等。定义的类C语言中的标识符只能以字母或下划线开头)进行归类显示,例如:识别保留字:if、int、for、while、do、return、break、continue等,其他的都识别为标识符;常数为无符号整形数;运算符包括:+、-、*、/、=、>、<、>=、<=、!=等;分隔符包括:,、;、{、}、(、)等。 4、实现文件的读取操作,而不是将文本以字符串形式预存于程序中。文本内容为待分析的类C语言程序。 例如下面为一段C语言源程序: main() { int a,b; a = 10; b = a + 20; } 要求输出如下 (2,’main’) (5,’(’) (5,’)’) (5,’{ ’) (1,’int’) (2,’a’) (5,’,’)

(2,’b’) (5,’;’) (2,’a’) (4,’=’) (3,’10’) (5,’;’) (2,’b’) (4,’=’) (2,’a’) (4,’+’) (3,’20’) (5,’;’) (5,’}’) 四、主要仪器设备 硬件:微型计算机。 软件: Visual C++ 6.0(也可以是其它集成开发环境)。 五、实验过程描述 1、状态转换图

编译原理实验报告2-词法分析程序的设计

实验2 词法分析程序的设计 一、实验目的 掌握计算机语言的词法分析程序的开发方法。 二、实验内容 编制一个能够分析三种整数、标识符、主要运算符和主要关键字的词法分析程序。 三、实验要求 1、根据以下的正规式,编制正规文法,画出状态图; 标识符<字母>(<字母>|<数字字符>)* 十进制整数0 | ((1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)*) 八进制整数0(1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7)* 十六进制整数0x(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)* 运算符和界符+ - * / > < = ( ) ; 关键字if then else while do 2、根据状态图,设计词法分析函数int scan( ),完成以下功能: 1)从文本文件中读入测试源代码,根据状态转换图,分析出一个单词, 2)以二元式形式输出单词<单词种类,单词属性> 其中单词种类用整数表示: 0:标识符 1:十进制整数 2:八进制整数 3:十六进制整数 运算符和界符,关键字采用一字一符,不编码 其中单词属性表示如下: 标识符,整数由于采用一类一符,属性用单词表示 运算符和界符,关键字采用一字一符,属性为空 3、编写测试程序,反复调用函数scan( ),输出单词种别和属性。 四、实验环境 PC微机 DOS操作系统或Windows 操作系统 Turbo C 程序集成环境或Visual C++ 程序集成环境 五、实验步骤 1、根据正规式,画出状态转换图;

实验1 词法分析程序的设计与开发

编译原理实验报告 一、实验目的 ? 深入理解有限自动机及其应用 ? 掌握词法分析程序的开发。 ? 掌握根据语言的词法规则构造识别其单词的有限自动机的方法 ? 深入理解词法分析程序自动生成原理 二、实验要求 ? 掌握各类单词的形式描述 ?用直接转向法实现有限自动机的代码编写。 ? 独立完成PL0语言的词法分析器。 ? 掌握词法分析程序自动生成工具LEX 的使用。 三、实验原理 词法分析是编译过程的第一阶段。它的任务就是对输入的字符串形式的源程序按顺序进行扫描,根据源程序的词法规则识别具有独立意义的单词(符号),并输出与其等价的Token 序列。 有限自动机是描述程序设计语言单词构成的工具,而状态转换图是有限自动机的比较直观的描述方法。我们使用确定的有限状态自动机,简记为DFA 。 PL/0的语言的词法分析器将要完成以下工作: (1) 跳过分隔符(如空格,回车,制表符); (2) 识别诸如begin ,end ,if ,while 等保留字; (3) 识别非保留字的一般标识符,此标识符值(字符序列)赋给全局量id ,而全局量sym 赋值为SYM_IDENTIFIER 。 (4) 识别数字序列,当前值赋给全局量NUM ,sym 则置为SYM_NUMBER ; (5) 识别:=,<=,>=之类的特殊符号,全局量sym 则分别被赋值为SYM_BECOMES ,SYM_LEQ ,SYM_GEQ 等。 课程名称: 编译原理 班级: 计算1614 实验成绩: 指导教师: 付永钢 姓名: 施心萍 实验项目名称: 实验一 词法分析程序设计与开发 学号: 201621121097 上机实践日期:

编译原理课程设计报告C语言词法与语法分析器的实现

编译原理课程设计报告 课题名称:编译原理课程设计 C-语言词法与语法分析器的实现

C-词法与语法分析器的实现 1.课程设计目标 (1)题目实用性 C-语言拥有一个完整语言的基本属性,通过编写C-语言的词法分析和语法分析,对于理解编译原理的相关理论和知识有很大的作用。通过编写C-语言词法和语法分析程序,能够对编译原理的相关知识:正则表达式、有限自动机、语法分析等有一个比较清晰的了解和掌握。(2)C-语言的词法说明 ①语言的关键字: else if int return void while 所有的关键字都是保留字,并且必须是小写。 ②专用符号: + - * / < <= > >= == != = ; , ( ) [ ] { } /* */ ③其他标记是ID和NUM,通过下列正则表达式定义: ID = letter letter* NUM = digit digit* letter = a|..|z|A|..|Z digit = 0|..|9 注:ID表示标识符,NUM表示数字,letter表示一个字母,digit表示一个数字。 小写和大写字母是有区别的。 ④空格由空白、换行符和制表符组成。空格通常被忽略。 ⑤注释用通常的c语言符号/ * . . . * /围起来。注释可以放在任何空白出现的位置(即注释不能放在标记)上,且可以超过一行。注释不能嵌套。

(3)程序设计目标 能够对一个程序正确的进行词法及语法分析。 2.分析与设计 (1)设计思想 a.词法分析 词法分析的实现主要利用有穷自动机理论。有穷自动机可用作描述在输入串中识别模式的过程,因此也能用作构造扫描程序。通过有穷自动机理论能够容易的设计出词法分析器。b.语法分析 语法分析采用递归下降分析。递归下降法是语法分析中最易懂的一种方法。它的主要原理是,对每个非终结符按其产生式结构构造相应语法分析子程序,其中终结符产生匹配命令,而非终结符则产生过程调用命令。因为文法递归相应子程序也递归,所以称这种方法为递归子程序下降法或递归下降法。其中子程序的结构与产生式结构几乎是一致的。 (2)程序流程图 程序主流程图: 词法分析: 语法分析:

词法分析程序的设计与实现

实验一词法分析程序的设计与实现 一、实验内容 【实验目的和要求】 设计、编制、调试一个具体的词法分析程序,加深对词法分析原理的理解。 【实验内容】 通过对PL/0词法分析程序(GETSYM)的分析,并在此基础上按照附录A中给出的PL/0语言的语法描述,编写一个PL/0语言的词法分析程序。此程序应具有如下功能:输入为字符串(待进行词法分析的源程序),输出为单词串,即由(单词、类别)所组成的二元组序列。 有一定检查错误的能力,例如发现2A这类不能作为单词的字符串。 【实验环境】 Windows PC机,任何语言。 【提交内容】 提交实验报告,报告内容如下: 目的要求、算法描述、程序结构、主要变量名说明、程序清单、调试情况、设计技巧、心得体会。 提交源程序和可执行文件。 【学时】 4课时。 二、实验说明 词法分析程序的任务就是扫描源程序,依据词法规则识别单词并报告构词错误信息。通常将单词分为5种类型。

1)基本字:也叫关键字、保留字,是程序设计语言用来表示特定语法含义的一种标识符,如if、begin等。 2)运算符:如+、-、*、/、:=、>、<等。 3)标识符:用户定义的变量名、常数名、函数名等。不同的高级程序设计语言对关键字是否可以作为普通标识符有不同的要求,有的语言允许程序员使用关键字作为普通标识符,有的程序设计语言则不允许程序员将关键字用着普通标识符(如C/C++、Pascal等都不允许)。在允许程序员将关键字用作普通标识符的程序设计语言的编译器中,编译器必须具备能够区分一个标识符到底是关键字还是普通标识符的功能。 4)常数:如23、6等。 5)界符:如“,”、“;”、“(”、“)”、“.”等。 注意事项 ●空格的作用仅仅是将一个个单词分割开来,源程序中的空格不具备别的语法意义,在语法分析及其后续阶段都没有任何作用,因此,词法分析的另一个工作是过滤空格。 ●注释对整个源程序的编译也没有任何语法意义,只是为了便于阅读和交流,因此,有的编译程序的词法分析程序也负责过滤注释。 ●输出的单词符号采用[单词类别,单词自身值]的二元组形式来表示。 ●为了使扫描程序尽可能的高效,在进行词法分析程序的设计和实现时还需十分注意扫描程序结构的实际细节问题。 ●用于间隔单词的空格和我们通常所说的键盘上的空格是不同的,这里的空格指的是所有能引起一个单词结束的字符,它们包括空格、制表或回车换行符。 ●a*(b+c)这样的没有空格间隔的情况时要正确地识别出所有的单词 ●123ab这样的字符串时,一般字符串的首字符必须为字母,不要将123识别为数字,将ab识别为标识符 转换图说明

词法分析小结

词法分析小结 -总结 []词法是编译器的第一阶段,它的工作就是从输入(源代码)中取得token,以作为parser (语法分析)的输入,一般在词法分析阶段都会把一些无用的空白字符(white space,即空格、tab和换行)以及注释剔除,以降低下一步分析的复杂度,词法分析器一般会提供一个gettoken()这样的,parser可以在做语法分析时调用词法分析器的这个方法来得到下一个token,所以词法分析器并不是一次性遍历所有源代码,而是采取这种on-demand的方式:只在parser需要时才工作,并且每次只取一个token,。token和lexeme 首先,token不等于lexeme。token和lexeme的关系就类似于面向对象语言中“类”和“实例”(或“对象”)之间的关系,这个用中文不知该如何解释才好,比如语言中的变量a和b,它们都属于同一种token:identifier,而a的lexeme是”a”,b则是”b”,而每个关键字都是一种token。token 可以附带有一个值属性,例如变量a,当调用词法分析器的gettoken()时,会返回一个identifier类型的token,这个token带有一个属性“a”,属性可以是多样的,例如表示数字的token可以带有一个表示数字值的属性,它是整型的。如下代码:int age = 23;int count = 50;可以依次提取出8个token:int(值为”int”),id(值为”age”),assign(值为”=”),number(值为整型数值23),int(值为”int”),id(值为”count”),assign(值为”=”),number(值为50)正则表达式 正则表达式可以用来描述字符串模式,例如我们可以用digit+来表示number的token,其中digit表示单个数字(这里说正则表达式并不完全和实现的正则引擎所识别的正则表达式等价,这里只是为了描述问题而已)。然而像c语言的的多行注释,用正则表达式来描述就比较麻烦,此时更倾向于直接用有穷自动机(finite automaton)来描述,因为用它来描述非常直观且很容易。有穷自动机(finite automata) 有穷自动机也称为有限状态机,状态在输入字符的作用下发生迁移,因此,它可以用来识别token,也因此,我们只要画得出fa,之后再用代码实现这个fa,那词法分析器也就差不多弄好了。有穷自动机分确定性(dfa)和非确定性(nfa)两种,如果对于同一个输入,只会有一个确定的状态迁移线,也就是只有一个确定的“下一状态”,那就是dfa,否则就是nfa。因为dfa对于同一个输入只有一个确定的下一状态,所以词法分析器当然优先采用它,那nfa拿来干嘛用呢?nfa用来做描述用时更方便,我们可以非常迅速地画出一个识别token的nfa图,但要想直接画出个dfa那要动不少脑筋。根据正则表达式构建nfa 如上所述,nfa更容易画出,那我们就先研究nfa,在定义token时,我们可以用正则表达式来描述它,因为正则表达式干这行很合适,例如一个digit+就可以描述数字,多方便。因此,我们需要根据正则表达式画出与之等价的nfa。而这个算法非常简单,就是tompson’s construction,这个书上写得很清楚了。将nfa转化成dfa(nfa的确定化)对于计算机来说,面对同一个输入,如果有多个下一状态,那计算机就不清楚要转到哪个状态,所以我们期望能从正则表达式得到dfa,而不是nfa,因为这样将来编程实现时比较(同一输入有确定的一个下一状态),而幸运的是,每个nfa都可以转化成dfa。为什么nfa 可以转化成dfa?因为fa(finite automata)中的状态都是我们自己画的,只要fa能正确的识别token,那就ok了,也就是,如果nfa和dfa都可以达到一样的效果:识别token,那其它的我们就不管了。而nfa确定化的本质,就是将原来多个状态改用一个状态来表示,新状态其实是一个状态集,比如nfa中状态s1在输入a下可以到达s2和s3,那么,在dfa中,就把s2和s3合起来认为是一个状态。还有一个问题是nfa中的空转换(?输入),如果s1在?输入下可以到达s2,就表示s1可以无条件地转移到s2,那s1和s2自然可以合并起来作为dfa中的一个状态,于是nfa转dfa的算法也就好理解了。但首先得先定义下空闭包

编译原理实验报告(词法分析器语法分析器)

编译原理实验报告

实验一 一、实验名称:词法分析器的设计 二、实验目的:1,词法分析器能够识别简单语言的单词符号 2,识别出并输出简单语言的基本字.标示符.无符号整数.运算符.和界符。 三、实验要求:给出一个简单语言单词符号的种别编码词法分析器 四、实验原理: 1、词法分析程序的算法思想 算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。 2、程序流程图 (1 (2)扫描子程序

3

五、实验内容: 1、实验分析 编写程序时,先定义几个全局变量a[]、token[](均为字符串数组),c,s( char型),i,j,k(int型),a[]用来存放输入的字符串,token[]另一个则用来帮助识别单词符号,s用来表示正在分析的字符。字符串输入之后,逐个分析输入字符,判断其是否‘#’,若是表示字符串输入分析完毕,结束分析程序,若否则通过int digit(char c)、int letter(char c)判断其是数字,字符还是算术符,分别为用以判断数字或字符的情况,算术符的判断可以在switch语句中进行,还要通过函数int lookup(char token[])来判断标识符和保留字。 2 实验词法分析器源程序: #include #include #include int i,j,k; char c,s,a[20],token[20]={'0'}; int letter(char s){ if((s>=97)&&(s<=122)) return(1); else return(0); } int digit(char s){ if((s>=48)&&(s<=57)) return(1); else return(0); } void get(){ s=a[i]; i=i+1; } void retract(){ i=i-1; } int lookup(char token[20]){ if(strcmp(token,"while")==0) return(1); else if(strcmp(token,"if")==0) return(2); else if(strcmp(token,"else")==0) return(3); else if(strcmp(token,"switch")==0) return(4); else if(strcmp(token,"case")==0) return(5); else return(0); } void main() { printf("please input string :\n"); i=0; do{i=i+1; scanf("%c",&a[i]);

编译原理词法分析习题集带答案

《编译原理》习题(一)——词法分析 一、是非题(请在括号内,正确的划√,错误的划×) 1.编译程序是对高级语言程序的解释执行。(× ) 2.一个有限状态自动机中,有且仅有一个唯一的终态。(×) 9.两个正规集相等的必要条件是他们对应的正规式等价。(× ) 二、选择题 1.词法分析器的输出结果是_____。 A.( ) 记号 B.( ) 相应条目在符号表中的位置 C.( ) 记号和属性二元组D.( ) 属性值 2.正规式 M 1 和 M 2 等价是指_____。 A.( ) M1和M2的状态数相等 B.( ) M1和M2的有向边条数相等 C.( ) M1和M2所识别的语言集相等D.( ) M1和M2状态数和有向边条数相等3.语言是 A.句子的集合 B.产生式的集合 C.符号串的集合 D.句型的集合 4.编译程序前三个阶段完成的工作是 A.词法分析、语法分析和代码优化 B.代码生成、代码优化和词法分析 C.词法分析、语法分析、语义分析和中间代码生成 D.词法分析、语法分析和代码优化 5.扫描器所完成的任务是从字符串形式的源程序中识别出一个个具有独立含义的最小语法单位即 A.字符 B.单词 C.句子 D.句型 6.构造编译程序应掌握______。 A.( )源程序B.( ) 目标语言 C.( ) 编译方法D.( ) 以上三项都是 7.词法分析的任务是 A.识别单词 B.分析句子的含义 C.识别句子 D.生成目标代码 三、填空题 1.计算机执行用高级语言编写的程序主要有两种途径:___解释__和__编译___。 3.编译过程可分为(词法分析),(语法分析),(语义分析与中间代码生成),(优化)和(目标代码生成)五个阶段。 6.扫描器的任务是从(源程序中)中识别出一个个(单词符号)。 17.一张转换图只包含有限个状态,其中有一个被认为是(初)态;而且实际上至少要有一个(终)态。 1.编译程序首先要识别出源程序中每个(单词),然后再分析每个(句子)并翻译其意义。3.通常把编译过程分为分析前端与综合后端两大阶段。词法、语法和语义分析是对源程序的(分析),中间代码生成、代码优化与目标代码的生成则是对源程序的(综合)。 5.对编译程序而言,输入数据是(源程序),输出结果是(目标程序)。

编译原理实验-词法分析器的设计与实现.docx

南华大学 计算机科学与技术学院实验报告 (2018~2019学年度第二学期) 课程名称编译原理 实验名称词法分析器的设计与 实现 姓名学号 专业班级 地点教师

1.实验目的及要求 实验目的 加深对词法分析器的工作过程的理解;加强对词法分析方法的掌握;能够采用一种编程语言实现简单的词法分析程序;能够使用自己编写的分析程序对简单的程序段进行词法分析。 实验要求 1.对单词的构词规则有明确的定义; 2.编写的分析程序能够正确识别源程序中的单词符号; 3.识别出的单词以<种别码,值>的形式保存在符号表中,正确设计和维护 符号表; 4.对于源程序中的词法错误,能够做出简单的错误处理,给出简单的错误 提示,保证顺利完成整个源程序的词法分析; 2.实验步骤 1.词法分析规则 <标识符>::=<字母>|<标识符><字母>|<标识符><数字> <常数>::=<数字>|<数字序列><数字> <数字序列>::=<数字序列><数字>|<数字>|<.> <字母>::=a|b|c|……|x|y|z <数字>::=0|1|2|3|4|5|6|7|8|9 <运算符>::=<关系运算符>|<算术运算符>|<逻辑运算符>|<位运算符>|<赋值运算符> <算数运算符>::=+|-|*|/|...|-- <关系运算符>::=<|>|!=|>=|<=|== <逻辑运算符>::=&&| || |! <位运算符>::=&| | |! <赋值运算符>::==|+=|-=|/=|*= <分界符>::=,|;|(|)|{|}|:| // |/**/ <保留字>::=main|if|else|while|do|for|...|void

(完整版)基于LEX的词法分析器实验报告

编译原理课程实验报告 实验名称:基于LEX的词法分析器 学生姓名:赵宁 学生学号: 2013020109 指导教师毛静

一、实验目标 自动构造C-语言的的词法分析器,要求能够掌握编译原理的基本理论,,理解编译程序的基本结构,掌握编译各阶段的基本理论和技术,掌握编译程序设计的基本理论和步骤.,增强编写和调试高级语言源程序的能力,掌握词法分析的基本概念和实现方法,熟悉C-语言的各种Token。 二、实验原理及方法 Lex输入文件由3个部分组成:定义集(definition),规则集(rule)和辅助程序集(auxiliary routine)或用户程序集(user routine)。这三个部分由位于新一行第一列的双百分号分开,因此,Lex输入文件的格式如下 {definitions} %% {rules} %% {auxiliary routines} 而且第一部分用“%{”和“%}”括起来。 第一和第三个部分为C语言的代码和函数定义,第二个部分为一些规则。 定义正则表达式如下 ID = letter letter* NUM = digit digit* Letter = a|…|z|A|…|Z Digit = 0|…|9 Keyword = else|if|int|return|void|while Special symbol = +|-|*|/|<|<=|>|>=|==|!=|=|;|,|(|)|[|]|{|}|/*|*/ White space = “” Enter = \n 在lex中的构造 letter [A-Za-z] digit [0-9] id ({letter}|[_])({letter}|{digit}|[_])* error_id ({digit})+({letter})+

相关文档
相关文档 最新文档