词法分析程序(扫描器)设计

合集下载

词法分析及词法分析程序

词法分析及词法分析程序
语义加工过程:
– w,p,n初值为0,e初值为1;
– 处理整数部分时,对于每个di ,令w=w10+di ; – 处理小数部分时,对于每个di ,令w=w10+di ;及n++;
– 处理指数时,E后若有‘-’号,令e=-1;计算指数值 p=p10+d;
– 在出口处,令ICON=w或FCON=w10^(e(p-n)).
(2)设当前处在Ai状态,所扫描的字符为ai+1,在结点Ai所 射出的诸矢线中,寻找标记为ai+1的矢线(若不存在,则 表明w有语法错误),读入ai+1,并进入状态Ai+1;
(3)重复(2),直到w中所有字符被读完且恰好进入终态F 时,宣告整个识别结束,w可被接受.
28
例:G[Z]:
状态转换图:
Z→0U∣1V
{return ( ICON= w ); {n++; w=w*10+d;}
{return (FCON =w*pow(10,e*p-n) ) ;} {n++;w=w*10+d;} error {p=p*10+d;}
e=-1; error {p=p*10+d;} error {p=p*10+d;} {return (FCON=w*pow(10,e*p-n) );
(1)对于G中形如Aa 的产生式,引矢线RA,且标记
为a;
(2)对于G中形如ABa 的产生式,引矢线 BA,且标
记为a。
34
由左线性文法构造状态转换图
已给文法G=({S,U},{0,1},{SS1 |U1, UU0 | 0},S)
R0
0
1
U1 S

词法分析程序实验报告

词法分析程序实验报告

词法分析程序实验报告篇一:词法分析器_实验报告词法分析器实验报告实验目的:设计、编制、调试一个词法分析子程序-识别单词,加深对词法分析原理的理解。

实验要求:该程序要实现的是一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分界符五大类。

并依次输出各个单词的内部编码及单词符号自身值。

(一)实验内容(1)功能描述:对给定的程序通过词法分析器弄够识别一个个单词符号,并以二元式(单词种别码,单词符号的属性值)显示。

而本程序则是通过对给定路径的文件的分析后以单词符号和文字提示显示。

(2)程序结构描述:函数调用格式:参数含义:String string;存放读入的字符串 String str; 存放暂时读入的字符串 char ch; 存放读入的字符 int rs 判断读入的文件是否为空 char []data 存放文件中的数据 int m;通过switch用来判断字符类型,函数之间的调用关系图:函数功能:Judgement()判断输入的字符并输出单词符号,返回值为空; getChar() 读取文件的,返回值为空;isLetter(char c) 判断读入的字符是否为字母的,返回值为Boolean类型; switch (m) 判断跳转输出返回值为空;isOperator(char c)判断是否为运算符的,返回值为Boolean类型; isKey(String string)判断是否为关键字的,返回值为Boolean类型; isDigit(char c) 判断读入的字符是否为数字的,返回值为Boolean类型。

(二)实验过程记录:本次实验出错3次,第一次无法输出双运算符,于是采用双重if条件句进行判断,此方法失败,出现了重复输出,继续修改if语句,仍没有成功。

然后就采用了直接方法调用解决此问题。

对于变量的判断,开始忘了考虑字母和数字组成的变量,结果让字母和数字分家了,不过改变if语句的条件,解决了此问题。

编译原理词法分析及词法分析程序

编译原理词法分析及词法分析程序
∴M能识别出L(G)中的全部句子。
状态图=>右线性文法
文法G[0] 0->a1
d 0
S->aA A->dA A->b
a c
1 2
b
d
3
1->d1 1->b
0->c
0->c2 2->d
S->c
S->cB,2有出弧 B->d
左线性文法=>状态转换图
设G=(VN,VT,P,S)是一左线性文法,令|VN|=K, 1) 则所要构造的状态转换图共有K+1个状态. 2) VN中的每个符号分别表示K个状态 2.1) G的开始符S为终止状态 3) 起始状态,用R(VN)标记
识别符号串与归约
S





从初态R到下一状态A对应Ba,即终结 符a归约成非终结符B; U 从状态B转换到状态A对应ABa,即将 Ba归约为A; 状态A转换到状态S(终态)对应S Aa,即 U 将Aa归约为开始符S. 归约成功,恰好进入终态,即状态转换图识 U 别了(或接受)该符号串. 识别00011的例子的归约过程
f是转换函数,是在K×Σ →K上的映像,即:如果f(ki,a)=kj, (ki,kj∈K)意味着,当前状态为ki,输入字符为a时,将转换 为下一个状态kj,我们把kj称作ki的一个后继状态;
1.确定的有限自动机
通常把这五要素组成的五元式M=(K,∑,f, S0,Z)称为确定的 有限自动机(DFA),它是相应的状态转化图的一种形式描 述,或者说,是状态转换矩阵的另一种表示。 在状态转换的每一步,据DFA当前所处状态及扫视的输入 字符,能唯一确定下一状态。

例:文法G=({S,U},{0,1},{SS1 |U1,

编译原理实验报告

编译原理实验报告

编译原理实验报告班级姓名:学号:自我评定:实验一词法分析程序实现一、实验目的与要求通过编写和调试一个词法分析程序,掌握在对程序设计语言的源程序进行扫描的过程中,将字符形式的源程序流转化为一个由各类单词符号组成的流的词法分析方法。

二、实验内容根据教学要求并结合学生自己的兴趣和具体情况,从具有代表性的高级程序设计语言的各类典型单词中,选取一个适当大小的子集。

例如,可以完成无符号常数这一类典型单词的识别后,再完成一个尽可能兼顾到各种常数、关键字、标识符和各种运算符的扫描器的设计和实现。

输入:由符合或不符合所规定的单词类别结构的各类单词组成的源程序。

输出:把单词的字符形式的表示翻译成编译器的内部表示,即确定单词串的输出形式。

例如,所输出的每一单词均按形如(CLASS,VALUE)的二元式编码。

对于变量和常数,CLASS字段为相应的类别码;VALUE字段则是该标识符、常数的具体值或在其符号表中登记项的序号(要求在变量名表登记项中存放该标识符的字符串;常数表登记项中则存放该常数的二进制形式)。

对于关键字和运算符,采用一词一类的编码形式;由于采用一词一类的编码方式,所以仅需在二元式的CLASS字段上放置相应的单词的类别码,VALUE字段则为“空”。

另外,为便于查看由词法分析程序所输出的单词串,要求在CLASS字段上放置单词类别的助记符。

三、实现方法与环境词法分析是编译程序的第一个处理阶段,可以通过两种途径来构造词法分析程序。

其一是根据对语言中各类单词的某种描述或定义(如BNF),用手工的方式(例如可用C语言)构造词法分析程序。

一般地,可以根据文法或状态转换图构造相应的状态矩阵,该状态矩阵同控制程序便组成了编译器的词法分析程序;也可以根据文法或状态转换图直接编写词法分析程序。

构造词法分析程序的另外一种途径是所谓的词法分析程序的自动生成,即首先用正规式对语言中的各类单词符号进行词型描述,并分别指出在识别单词时,词法分析程序所应进行的语义处理工作,然后由一个所谓词法分析程序的构造程序对上述信息进行加工。

词法分析

词法分析

实验报告课程名称编译原理实验项目词法分析的实现专业计算机课文学与技术班级二班姓名陈雪莹学号08030212指导教师邓玉洁实验成绩2011年5月9日一.词法分析识别的语言介绍词法分析的英语解释是lexical analysis,是计算机科学中将字符序列转换为单词(Token)序列的过程。

进行语法分析的程序或者函数叫作词法分析器(Lexical analyzer,简称Lexer),也叫扫描器(Scanner)。

扫描器能够识别其所能处理的单词中可能包含的所有字符序列(单个这样的字符序列即前面所说的“语素”)。

例如“整数”单词可以包含所有数字字符序列。

很多情况下,根据第一个非空白字符便可以推导出该单词的类型,于是便可逐个处理之后的字符,直到出现不属于该类型单词字符集中的字符(即最长一致原则)。

词法分析器一般以函数的形式存在,供语法分析器调用。

词法分析阶段是编译过程的第一个阶段,是编译的基础。

这个阶段的任务是从左到右一个字符一个字符地读入源程序,即对构成源程序的字符流进行扫描然后根据构词规则识别单词(也称单词符号或符号)。

词法分析程序实现这个任务。

词法分析程序可以使用Lex等工具自动生成。

这里的单词是一个字符串,是构成源代码的最小单位。

从输入字符流中生成单词的过程叫作单词化(Tokenization),在这个过程中,词法分析器还会对单词进行分类。

单词经常使用正则表达式进行定义,像lex一类的词法分析器生成器就支持使用正则表达式。

语法分析器读取输入字符流、从中识别出语素、最后生成不同类型的单词。

其间一旦发现无效单词,便会报错。

二. 语言的正规式 ->NFA->DFA->流程图题目:设某一语言有如下单词:关键字:BEGIN , END , IF , THEN ,ELSE,for ,do,while<标识符>--><字母>|<标识符><字母>|<标识符><数字><无符号整数>--><数字>|<无符号整数><数字><分界符>-->+|-|*|/|;|(|)|{|}|<|<=|=|!=|>=|>|:=|<空格><字母>-->a|…|z|A|…|Z <数字>-->0|…|9 <空格>-->’ ’ (1)正规文法→正规式<标识符>:S <字母>:1 <数字>:n <无符号整数>:y <空格>:K <分界符>:c S →1|1S|nS y →n|ync →+|-|*|/|;|(|)|{|}|<|<=|=|!=|>=|>|:=|K 1→ a|…|z|A|…|Z n →0|…|9 K →’ ’(2)正规文法→正规式 (1) S→1|1S|nS (2) S→1 ,S→1S|nS (3) S→1, S→(1|n)S (4) S=(1|n)* 1(1) y→n|yn (2) y→n, y→yn (3) y→n*n (4) y=n(3)DFA 图:εε 1 1 ε ε +A0 1 2 4Bnεε nn(4)NFA 图:11nN3 A y BA BA B三.程序设计(1)总体设计(2)子程序设计scanner函数流程Sort函数流程Handlecom函数流程Recogdig流程图Recogid程序流程四.程序中的结构说明(1)符号表BEGIN0 END 1IF 2 THEN 3ELSE 4 for 5do 6 while7+ 8 —9id 29 * 11/ 12 ; 13(14 )15{ 16 } 17< 18 <= 19= 20 != 21>= 22 > 23== 24 <空格> 25 (2)结构体结构体说明struct symbolrecord 用来单词编码表初始化。

词法分析器设计思路

词法分析器设计思路
char s[100]; ifstream a; a.open("F:\\test.txt",ios::in); a>>s; cout<<s; } 这样做之后,文件test.txt里面的内容,就会存放 在字符数组s里面了。
思路
2、要对源程序从左到右一个个进行扫描。这里涉及 到几个问题:
(2)当把txt的文件先已经读进来,放在字符数组a中 之后,就要对这个数组里面的内容来逐个进行扫 描,因为是从左到右扫描,所以是从数组的0号 下标位置来扫描的。
20
)
40
]
60
思路
将这些单词存入内存怎样实现呢?
① 方法一:声明一个二维数组string A[60][2];
例如: A[0][0]=“and”; A[0][1]=“1”; A[1][0]=“array”; A[1][1]=“2”; ……
思路
将这些单词存入内存怎样实现呢?
② 方法二:将每个单词声明成为一个结构类型的结
点,每个单词的两个属性,即(单词本身值,
种别)作为这个节点的两个域的内容。
struct node{ string word; string type; //这个type定义成为int类型也可以
}; node A[60]; A[0].word=“and”; A[0].type=“1”; ……
思路
2、要对源程序从左到右一个个进行扫描。这里涉及 到几个问题:
即cout<<“(“<<A[0][0]<<“,”<<A[0][1]<<“)”;
找出来;分号,逗号等这些符号,example */
自己本身就是单词。
A:=B*C+37; X:=’ABC’

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

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

词法分析程序的设计与实现方法1:采用C作为实现语言,手工编制一.文法及状态转换图1.语言说明:C语言有以下记号及单词:(1)标识符:以字母开头的、后跟字母或数字组成的符号串。

(2)关键字:标识符集合的子集,该语言定义的关键字有32个,即auto,break,case,char,const,continue,default,do,double,else,enum, extern,float,for,goto,if,int,long,register,return,short,signed,static, sizeof,struct,switch,typedef ,union,unsigned ,void, volatile和while。

(3)无符号数:即常数。

(4)关系运算符:<,<=,==,>,>=,!=。

(5)逻辑运算符:&&、||、!。

(6)赋值号:=。

(7)标点符号:+、++、-、--、*、:、;、(、)、?、/、%、#、&、|、“”、,、.、{}、[]、_、^等(8)注释标记:以“/*”开始,以“*/”结束。

(9)单词符号间的分隔符:空格。

2.记号的正规文法:仅给出各种单词符号的文法产生式(1)标识符的文法id->letter ridrid->ε|letter rid|digit rid(2)无符号整数的文法digits->digit remainderremainder->ε|digit remainder(3)无符号数的文法num->digit num1num1->digit num1|. num2|E num4|εnum2->digit num3num3->digit num3|E num4|εnum4->+digits|-digits|digit num5digits->digit num5num5->digit num5|ε(4)关系运算符的文法relop-> <|<=|==|>|>=|!=(5)赋值号的文法assign_op->=(6)标点符号的文法special_symbol->+|-|*|%|#|^|(|)|{|}|[|]|:|;|”|?|/|,|.& (7)逻辑运算符的文法logic->&&| || | !(8)注释头符号的文法note->/starstar->*3.状态转换图其中,状态0是初始状态,若此时读入的符号是字母,则转换到状态1,进入标识符识别过程;如果读入的是数字,则转换到状态2,进入无符号数识别过程;……;若读入的符号是/,转换到状态11,再读入下一个符号,如果读入的符号是*,则转换到状态12,进入注释处理状态;如果在状态0读入的符号不是语言所定义的单词符号的开始字符,则转换到状态13,进入错误处理状态。

第二章 词法分析

第二章 词法分析

8
单词种别表示单词的种类, (1) 单词种别表示单词的种类,是语法分 析所需要的信息。 析所需要的信息。 一个语言的单词符号如何划分种类、 一个语言的单词符号如何划分种类、分为 几类、如何编码都属于技术性问题, 几类、如何编码都属于技术性问题,主要取 决于处理上的方便。 决于处理上的方便。 通常让每种单词对应一个整数码, 通常让每种单词对应一个整数码,这样可 最大限度地把各个单词区别开来。 最大限度地把各个单词区别开来。
6
(4) 运 算 符 : 如 “ +” 、 “ − ” 、 “ * ” 、 /”、 >”、 <”等 “/”、“>”、“<”等。 (5) 界符:在语言中是作为语法上的分界符 界符: 号使用的, 号使用的 , 如“ , ”、 “ ;” 、 “( ” 、 “ ) ” 等。 一个程序语言的保留字、 一个程序语言的保留字、运算符和界符 的个数是确定的, 的个数是确定的,而标识符或常数的使用则 不限定个数。 不限定个数。
24
终态一般对应一个return( 语句。 终态一般对应一个return( )语句。 return意味着从词法分析器返回到调用段 return意味着从词法分析器返回到调用段 一般指返回到语法分析器。 ,一般指返回到语法分析器。
图2–4 含有分支或回路的状态示意 (a) 含分支的状态 ;(b) 含回路的状态 含分支的状态i; 含回路的状态i
(3,’if’) (1,指向 的符号表入口) 指向i (1,指向i的符号表入口) (4,’=’) (2,’5’) (3,’then’) (1,指向 的符号表入口) 指向x (1,指向x的符号表入口) (4,’:=’) (1,指向 的符号表入口) 指向y (1,指向y的符号表入口) (5,’;’)

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

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

实验1-3 《编译原理》S语言词法分析程序设计方案一、实验目的了解词法分析程序的两种设计方法之一:根据状态转换图直接编程的方式;二、实验内容ﻩ1.根据状态转换图直接编程编写一个词法分析程序,它从左到右逐个字符的对源程序进行扫描,产生一个个的单词的二元式,形成二元式(记号)流文件输出。

在此,词法分析程序作为单独的一遍,如下图所示。

具体任务有:(1)组织源程序的输入(2)拼出单词并查找其类别编号,形成二元式输出,得到单词流文件(3)删除注释、空格和无用符号(4)发现并定位词法错误,需要输出错误的位置在源程序中的第几行。

将错误信息输出到屏幕上。

(5)对于普通标识符和常量,分别建立标识符表和常量表(使用线性表存储),当遇到一个标识符或常量时,查找标识符表或常量表,若存在,则返回位置,否则返回0并且填写符号表或常量表。

标识符表结构:变量名,类型(整型、实型、字符型),分配的数据区地址注:词法分析阶段只填写变量名,其它部分在语法分析、语义分析、代码生成等阶段逐步填入。

常量表结构:常量名,常量值三、实验要求1.能对任何S语言源程序进行分析ﻩ在运行词法分析程序时,应该用问答形式输入要被分析的S源语言程序的文件名,然后对该程序完成词法分析任务。

2.能检查并处理某些词法分析错误词法分析程序能给出的错误信息包括:总的出错个数,每个错误所在的行号,错误的编号及错误信息。

本实验要求处理以下两种错误(编号分别为1,2):1:非法字符:单词表中不存在的字符处理为非法字符,处理方式是删除该字符,给出错误信息,“某某字符非法”。

2:源程序文件结束而注释未结束。

注释格式为:/* …… */四、保留字和特殊符号表单词的构词规则:字母=[A-Za-z]数字=[0-9]标识符=(字母|_)(字母|数字)*数字=数字(数字)*(.数字+| )四、S语言表达式和语句说明ﻩ1.算术表达式:+、-、*、/、%ﻩ2.关系运算符:>、>=、<、<=、==、!=3.赋值运算符:=,+=、-=、*=、/=、%=ﻩ4.变量说明:类型标识符变量名表;5.类型标识符:int char floatﻩ6.If语句:if表达式then 语句[else语句] ﻩ7.For语句:for(表达式1;表达式2;表达式3) 语句ﻩ8.While语句:while表达式do 语句9.S语言程序:由函数构成,函数不能嵌套定义。

词法分析器设计与实现

词法分析器设计与实现

词法分析器设计与实现一、问题描述:设计并实现一个小型程序语言(Micro)的词法分析器,实现源程序的输入,预处理词法分析,最后以编译程序需要的内部表示形式(二元组)将识别的单词符号输出。

利用状态转换图设计Micro语言的词法规则,用C语言实现该词法分析程序。

实验环境:C/C++开发平台。

二、Micro的单词分类:标识符:字母打头的字母/数字串常数:数字打头的数字串保留字:begin,end, var,read,write,integer,real符号:+,*,(,),:,=,;三、设计思想1)本程序的状态转换图如下:图1:标识符状态表示图图2:识别常数状态表示图图3:识别符号状态表示图2)状态转换图的实现a)ch 字符变量,读进最新的源程序字符b)strToken 字符数组,存放构成单词符号的字符串有了以上定义,对常数状态转换图可得:if(ch>='0'&&ch<='9'){strToken[i++]=ch;ch=fgetc(in);while(ch>='0'&&ch<='9'){strToken[i++]=ch;ch=fgetc(in);}if(ch!='.') {strToken[i++]='\0';fprintf(out,"%s%d,%c%s%c%s\n","(",3,'"',strToken,'"',")"); }else{strToken[i++]=ch;ch=fgetc(in);while(ch>='0'&&ch<='9'){strToken[i++]=ch;ch=fgetc(in);}strToken[i++]='\0';fprintf(out,"%s%d,%c%s%c%s\n","(",3,'"',strToken,'"',")"); }while(ch==' '){ch=fgetc(in);}}3)单词符号及内部种别码,对Micro种别码的设定:四、实验结果本次实验输入输出都采用文件形式。

词法分析程序设计与实现

词法分析程序设计与实现
ﻩif(ch=='>')
ﻩ{
ﻩﻩsyn=21;
ﻩtoken[m++]=ch;
ﻩ}
ﻩelseif(ch=='=')
{
ﻩsyn=22;
ﻩtoken[m++]=ch;
ﻩ}
else
{
ﻩsyn=23;
ﻩp--;
ﻩ}
break;
case'>':m=0;token[m++]=ch;
ch=prog[p++];
ﻩif(ch=='=')

ﻩcase 11: cout<<"("<<syn<<","<<sum<<")"<<endl;break;
case -1:cout<<"Errorin row"<<row<<"!"<<endl;break;
ﻩﻩcase -2:row=row++;break;
default:cout<<"("<<syn<<","<<token<<")"<<endl;break;
charch;
intsyn,p,m=0,n,row,sum=0;
char *rwtab[6]={"begin","if","then","while","do","end"};
voidscaner()
{
ﻩfor(n=0;n<8;n++)token[n]=NULL;

实验一手工编写简易词法分析程序

实验一手工编写简易词法分析程序

编译原理实验报告日期:班级:题目:组员:1实验目的及要求1.通过设计、编写、调试一个具体的词法分析程序,加深对词法分析原理的理解。

2.掌握在对程序设计语言源程序进行扫描的过程中, 将其分解为各类单词的词法分析方法。

2实验平台Windows + VC + Win32 Console3实验步骤1.查询资料,了解词法分析器的工作过程与原理。

2.分析题目,整理出基本设计思路。

3.实践编码,将设计思想转换用c语言编码实现,编译运行。

4.测试功能,多次设置包含不同字符,关键字的待解析文件,仔细察看运行结果,检测该分析器的分析结果是否正确。

通过最终的测试发现问题,逐渐完善代码中设置的分析对象与关键字表,拓宽分析范围提高分析能力。

4实验内容4.1 实现下述功能, 并将分析结果保存在文件中. (既可以参考范例程序, 也可以独立完成)程序输入/输出示例:输入一段C语言程序,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、界符。

(遇到错误时可显示“Error”,然后跳过错误部分继续显示)输入源程序示例:main ( ){int a , b =10;int c ;c = a + b * 20;}输出固定表格如下输出动态表格如下运算符表44.2 程序:#include<string.h>#include<stdio.h>#include<stdlib.h>#include<ctype.h>//定义关键字char*Key[10]={"main","void","int","char","printf","scanf","else","if","return"}; char Word[20],ch; // 存储识别出的单词流int IsAlpha(char c) { //判断是否为字母if(((c<='z')&&(c>='a'))||((c<='Z')&&(c>='A'))) return 1;else return 0;}int IsNum(char c){ //判断是否为数字if(c>='0'&&c<='9') return 1;else return 0;}int IsKey(char *Word){ //识别关键字函数int m,i;for(i=0;i<9;i++){if((m=strcmp(Word,Key[i]))==0){if(i==0)return 2;elsereturn 1;}}return 0;}void scanner(FILE *fp){ //扫描函数char Word[20]={'\0'};char ch;int i,c;ch=fgetc(fp); //获取字符,指针fp并自动指向下一个字符if(IsAlpha(ch)){ //判断该字符是否是字母Word[0]=ch;ch=fgetc(fp);i=1;while(IsNum(ch)||IsAlpha(ch)){ //判断该字符是否是字母或数字Word[i]=ch;i++;ch=fgetc(fp);}Word[i]='\0'; //'\0' 代表字符结束(空格)fseek(fp,-1,1); //回退一个字符c=IsKey(Word); //判断是否是关键字if(c==0) printf("\t\t├───────┼───┼───────┤\n\t\t │%s\t\t│1\t│1\t\t│\n",Word);//不是关键字else if(c==2)printf("\t\t├───────┼───┼───────┤\n\t\t │%s\t\t│2\t│3\t\t│\n",Word);elseprintf("\t\t├───────┼───┼───────┤\n\t\t │%s\t\t│3\t│1\t\t│\n",Word); //输出关键字}else //开始判断的字符不是字母if(IsNum(ch)){ //判断是否是数字Word[0]=ch;ch=fgetc(fp);i=1;while(IsNum(ch)){Word[i]=ch;i++;ch=fgetc(fp);}Word[i]='\0';fseek(fp,-1,1); //回退printf("\t\t├───────┼───┼───────┤\n\t\t │%s\t\t│3\t│1\t\t│\n",Word);}else //开始判断的字符不是字母也不是数字{Word[0]=ch;switch(ch){case'[':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│5\t│7\t\t│\n",Word); break;case']':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│5\t│9\t\t│\n",Word); break;case'(':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│5\t│3\t\t│\n",Word); break;case')':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│5\t│4\t\t│\n",Word); break;case'{':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│5\t│5\t\t│\n",Word); break;case'}':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│5\t│6\t\t│\n",Word); break;case',':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│5\t│1\t\t│\n",Word); break;case'"':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│5\t│8\t\t│\n",Word); break;case';':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│5\t│2\t\t│\n",Word); break;case'+':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word);//运算符"+="}else if(ch=='+'){printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word); //判断结果为"++"}else {fseek(fp,-1,1);printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│1\t\t│\n",Word); //判断结果为"+"}break;case'-':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word); }else if(ch=='-'){printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word); //判断结果为"--"}else {fseek(fp,-1,1);printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│2\t\t│\n",Word); //判断结果为"-"}break;case'*':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│3\t\t│\n",Word);break;case'/':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│4\t\t│\n",Word);break;case'!':case'=':ch=fgetc(fp);if(ch=='='){printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word);}else {fseek(fp,-1,1);printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│5\t\t│\n",Word);}break;case'<':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word); //判断结果为运算符"<="}else if(ch=='<'){printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word);//判断结果为"<<"}else {fseek(fp,-1,1);printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word); //判断结果为"<"}break;case'>':ch=fgetc(fp);Word[1]=ch;if(ch=='=') printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word);else {fseek(fp,-1,1);printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word);}break;case'%':ch=fgetc(fp);Word[1]=ch;if(ch=='='){ printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word);}if(IsAlpha(ch)) printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t│类型标识符\t│ \t│\n",Word);else {fseek(fp,-1,1);printf("\t\t├───────┼───┼───────┤\n\t\t│%s \t│取余运算符\t│ \t\n",Word);}break;default:printf("\t\t├───────┼───┼───────┤\n\t\t│无法识别字符! \t\t\t\t │\n"); break;}}}main(){char in_fn[30]; //文件路径FILE *fp;printf("\n请输入源文件名(包括路径和后缀名):");while(true){gets(in_fn);//scanf("%s",in_fn);if((fp=fopen(in_fn,"r"))!=NULL) break; //读取文件内容,并返回文件指针,该指针指向文件的第一个字符else printf("文件路径错误!请重新输入:");}printf("\n**************************** 单词类别表****************************\n");printf("\t\t┌───────┬───────┐\n\t\t│单词类型\t│单词种别\t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│标识符 \t│1 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│保留字 \t│2 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│常量 \t│3 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│运算符 \t│4 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│分界符 \t│5 \t│\n",Word);printf("\t\t└───────┴───────┘\n",Word);printf("\n**************************** 保留字表******************************\n");printf("\t\t┌───────┬───────┐\n\t\t│保留字 \t│地址指针\t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│int \t│1 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│float \t│2 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│main \t│3 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│printf \t│4 \t│\n",Word);printf("\t\t└───────┴───────┘\n",Word);printf("\n**************************** 运算符表******************************\n");printf("\t\t┌───────┬───────┐\n\t\t│算符 \t│地址指针\t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│+ \t│1 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│- \t│2 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│* \t│3 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│/ \t│4 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│= \t│5 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│其他 \t│6 \t│\n",Word);printf("\t\t└───────┴───────┘\n",Word);printf("\n**************************** 分界符表******************************\n");printf("\t\t┌───────┬───────┐\n\t\t│界符 \t│地址指针\t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│, \t│1 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│; \t│2 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│( \t│3 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│) \t│4 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│{ \t│5 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│} \t│6 \t│\n",Word);printf("\t\t└───────┴───────┘\n",Word);printf("\n**************************** 词法分析结果如下******************************\n");printf("\t\t┌───────┬───┬───────┐\n\t\t│单词名称\t│类别\t│地址指针\t│\n",Word);do{ch=fgetc(fp);if(ch=='#') break; //文件以#结尾,作为扫描结束条件else if(ch==' '||ch=='\t'||ch=='\n'){} //忽略空格,空白,和换行else{fseek(fp,-1,1); //回退一个字节开始识别单词流scanner(fp);}}while(ch!='#');printf("\t\t└───────┴───┴───────┘\n",Word);return(0);}5实验结果5.1 解析源文件:main ( ){int a , b =10;int c ;c = a + b * 20;}#5.2 解析结果:6实验总结分析在本次实验,使我们再次浏览了有关C语言的一些基本知识,特别是对文件,字符串进行基本操作的方法。

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

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

编译原理实验报告实验一一、实验名称:词法分析器的设计二、实验目的: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 〈stdio.h〉#include <math.h>#include <string。

h>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]);}while(a[i]!=’#’);i=1;j=0;get();while(s!=’#'){ memset(token,0,20);switch(s){case 'a':case ’b':case ’c':case ’d':case ’e’:case ’f’:case 'g’:case ’h':case 'i':case ’j':case 'k’:case ’l':case 'm’:case 'n':case ’o':case ’p':case ’q’:case 'r’:case 's’:case 't’:case ’u’:case ’v’:case ’w’:case ’x':case ’y':case ’z’:while(letter(s)||digit(s)){token[j]=s;j=j+1;get();}retract();k=lookup(token);if(k==0)printf("(%d,%s)”,6,token);else printf("(%d,—)",k);break;case ’0':case ’1’:case ’2':case ’3':case '4’:case '5’:case ’6':case ’7’:case ’8’:case '9’:while(digit(s)){token[j]=s;j=j+1;get();}retract();printf(”%d,%s",7,token);break;case '+':printf(”(’+',NULL)”);break;case ’-':printf("(’-',null)");break;case ’*':printf(”('*’,null)");break;case '<':get();if(s=='=’) printf(”(relop,LE)”);else{retract();printf("(relop,LT)");}break;case ’=':get();if(s=='=’)printf("(relop,EQ)");else{retract();printf(”('=',null)”);}break;case ’;':printf(”(;,null)");break;case ' ’:break;default:printf("!\n”);}j=0;get();} }六:实验结果:实验二一、实验名称:语法分析器的设计二、实验目的:用C语言编写对一个算术表达式实现语法分析的语法分析程序,并以四元式的形式输出,以加深对语法语义分析原理的理解,掌握语法分析程序的实现方法和技术.三、实验原理:1、算术表达式语法分析程序的算法思想首先通过关系图法构造出终结符间的左右优先函数f(a),g(a)。

词法分析程序的设计(共15张PPT)

词法分析程序的设计(共15张PPT)
词法分析作为语法分析的子程序 自身值是编译其他阶段需要的信息
➢方法二:每个基本字一个编码;所有标识符 方法一:按单词的5大种类每种一个码,例如标识符为l,常数为2,基本字为3,运算符为4,界符为5。
GetChar();
分别判别ch字符是否为字为母或一数字 个编码;常数按类型分类,每类一个编 码;每个运算符一个编码;每个界符一个编 码。
(1,指向x的符号表入口)
(3,‘then’) 方法一:按单词的5大种类每种一个码,例如标识符为l,常数为2,基本字为3,运算符为4,界符为5。
(1,指向y的符号表入口)
(1,指向y的符号表入口)
(1,指向x的符号表入口 else If(ch=‘/’) {状态 l 的对应程序段;}
)
(4,‘:=’)
二元式(单词种别,单词自身的值) 对常数,基本字,运算符,界符就是他们本身的值
3. 换行符不能删,对于错误处理起作用。 (1,指向i的符号表入口)
每当遇到左括号,则计数器加1
❖ 复合型特殊符,如“:=”的处理
读到“:”时不能判断是否为冒号,必须读下一字符。
第9页,共15页。
❖ 括号类配对: “‘”和“’”、左注释符和右注释符的配对。也 可以把begin …end ,if …then,[ ],{ },( )等语 法配对在词法分析中进行处理 处理方法:
第5页,共15页。
单词的机内表示
二元式(单词种别,单词自身的值) 种别是语法分析需要的信息 二元式(单词种别,单词自自身身的值)值是编译其他阶段需要的信息 种别编码(常用整数编码) 常数按类型分类,每类一个编码;
二元式(单词种别,单词自身的值) GetChar();
➢ 方法一:按单词的5大种类每种一个码,例 常数按类型分类,每类一个编码;
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

#include <stdio.h>
#include <string.h>
char prog[80],token[8],ch;
int syn,p,m,n,sum;
char *rwtab[6]={"begin","if","then","while","do","end"};
void scaner()
{ sum=0;
for(m=0;m<8;m++)token[m++]=NULL;
ch=prog[p++];
m=0;
while((ch==' ')||(ch=='\n'))
{
ch=prog[p++];
}
if(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A')))
{
while(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))||((ch>='0')&&(ch<='9')))
{
token[m++]=ch;
ch=prog[p++];
}
p--;
syn=10;
for(n=0;n<6;n++)
if(strcmp(token,rwtab[n])==0)
{ syn=n+1;
break;
}
}
else if((ch>='0')&&(ch<='9'))
{
while((ch>='0')&&(ch<='9'))
{
sum=sum*10+ch-'0';
ch=prog[p++];
}
p--;
syn=11;
}
else switch(ch)
{ case '<':token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{ syn=22;
token[m++]=ch;
}
else
{ syn=20;
p--;
}
break;
case '>':token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{ syn=24;
token[m++]=ch;
}
else
{ syn=23;
p--;
}
break;
case '+': token[m++]=ch;
ch=prog[p++];
if(ch=='+')
{ syn=17;
token[m++]=ch;
}
else
{ syn=13;
p--;
}
break;
case '-':token[m++]=ch;
ch=prog[p++];
if(ch=='-')
{ syn=29;
token[m++]=ch;
}
else
{ syn=14;
p--;
}
break;
case '!':ch=prog[p++];
if(ch=='=')
token[m++]=ch;
}
else
{ syn=31;
p--;
}
break;
case '=':token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{ syn=25;
token[m++]=ch;
}
else
{ syn=18;
p--;
}
break;
case '*': syn=15;
token[m++]=ch;
break;
case '/': syn=16;
token[m++]=ch;
break;
case '(': syn=27;
token[m++]=ch;
break;
case ')': syn=28;
token[m++]=ch;
break;
case '{': syn=5;
token[m++]=ch;
break;
case '}': syn=6;
token[m++]=ch;
break;
case ';': syn=26;
token[m++]=ch;
break;
case '\"': syn=30;
token[m++]=ch;
break;
token[m++]=ch;
break;
case ':':syn=17;
token[m++]=ch;
break;
default: syn=-1;
break;
}
token[m++]='\0';
}
void main()
{
p=0;
printf("\n please input a string(end with '#'):/n");
do{
scanf("%c",&ch);
prog[p++]=ch;
}while(ch!='#');
p=0;
do{
scaner();
switch(syn)
{case 11:printf("( %-10d%5d )\n",sum,syn);
break;
case -1:printf("you have input a wrong string\n");
getch();
exit(0);
default: printf("( %-10s%5d )\n",token,syn);
break;
}
}while(syn!=0);
getch();
}。

相关文档
最新文档