单词的词法分析程序设计
词法分析及词法分析程序
– 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语句的条件,解决了此问题。
实验一词法分析(单词识别)
实验一:词法分析一、实验目的:通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。
并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。
编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。
并依次输出各个单词的内部编码及单词符号自身值。
(遇到错误时可显示“Error”,然后跳过错误部分继续显示)二、实验预习提示1、词法分析器的功能和输出格式词法分析器的功能是输入源程序,输出单词符号。
词法分析器的单词符号常常表示成以下的二元式(单词种别码,单词符号的属性值)。
本实验中,采用的是一类符号一种别码的方式。
2、单词的BNF表示<标识符>-> <字母><字母数字串><字母数字串>-><字母><字母数字串>|<数字><字母数字串>|<下划线><字母数字串>|ε<无符号整数>-> <数字><数字串><数字串>-> <数字><数字串> |ε<加法运算符>-> +<减法运算符>-> -<大于关系运算符>-> ><大于等于关系运算符>-> >=3、“超前搜索”方法词法分析时,常常会用到超前搜索方法。
如当前待分析字符串为“a>+”,当前字符为’>’,此时,分析器倒底是将其分析为大于关系运算符还是大于等于关系运算符呢?显然,只有知道下一个字符是什么才能下结论。
于是分析器读入下一个字符’+’,这时可知应将’>’解释为大于运算符。
但此时,超前读了一个字符’+’,所以要回退一个字符,词法分析器才能正常运行。
在分析标识符,无符号整数等时也有类似情况。
词法分析程序的设计(共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大种类每种一个码,例 常数按类型分类,每类一个编码;
词法分析程序设计与实现.doc
实验一词法分析程序设计与实现实验目的及内容调试并完成一个词法分析程序,加深对词法分析原理的理解。
二、实验原理(状态转换图)C语言子集关键字:begin if then while do end所有关键字都是小写。
运算符和界符::=+–*/<<=<>>>==;()#其他单词是标识符( ID)和整型常数( NUM),通过以下正规式定义:ID=letter ( letter| digit)*NUM=digit digit *空格由空白、制表符和换行符组成。
空格一般用来分隔ID、NUM,运算符、界符和关键字,词法分析阶段通常被忽略。
各种单词符号对应的种别码单词符号种别码单词符号种别码begin 1 : 17if 2 := 18then 3 > 20while 4 <> 21do 5 <= 22end 6 < 23letter(letter| digit)* 10 >= 24digit digit * 11 = 25* 13 ; 26/ 14 ( 27+ 15 ) 28- 16 # 0词法分析程序的功能输入:所给文法的源程序字符串。
输出:二元组( syn,token 或 sum)构成的序列。
其中: syn 为单词种别码;token 为存放的单词自身字符串;sum 为整型常数。
软件平台及工具PC机以及 VISUAL C++软件。
实验方法、步骤(或:程序代码或操作过程)( 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++];}token[m++]='\0';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')){{sum=0;while((ch>='0'&&ch<='9')){sum=sum*10+ch-'0';ch=prog[p++];}}p--;syn=11;if(sum>32767)syn=-1;}else switch(ch){case'<':m=0;token[m++]=ch;ch=prog[p++];if(ch=='>'){syn=21;token[m++]=ch;}else if(ch=='='){syn=22;token[m++]=ch;}else{syn=23;p--;}break;case'>':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=24;token[m++]=ch;}{syn=20;p--;}break;case':':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=18;token[m++]=ch;}else{syn=17;p--;}break;case'*':syn=13;token[0]=ch;break;case'/':syn=14;token[0]=ch;break;case'+':syn=15;token[0]=ch;break;case'-':syn=16;token[0]=ch;break;case'=':syn=25;token[0]=ch;break;case';':syn=26;token[0]=ch;break;case'(':syn=27;token[0]=ch;break;case')':syn=28;token[0]=ch;break;case'#':syn=0;token[0]=ch;break;case'\n':syn=-2;break;default: syn=-1;break;}}void main(){p=0;row=1;cout<<"Please input string:"<<endl;do{(ch);prog[p++]=ch;}while(ch!='#');p=0;do{scaner();switch(syn)case 11: cout<<"("<<syn<<","<<sum<<")"<<endl; break;case -1: cout<<"Error in row "<<row<<"!"<<endl; break;case -2: row=row++;break;default: cout<<"("<<syn<<","<<token<<")"<<endl;break;}}while (syn!=0);}( 2)创建编辑程序( 3)连接、编译和调试程序( 4)运行程序五、实验过程原始记录( 测试数据、图表、计算等) (1)给定源程序begin x:=8; if x>0 then x:=2*x+1/5;end#输出结果(2)源程序(包括上式未有的while 、do 以及判断错误语句):beginx<=$;whilea<0dob<>9-x;end#。
词法分析程序的设计与实现
词法分析程序的设计与实现方法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,进入错误处理状态。
实验一 编写词法分析程序
实验一编写词法分析程序1 实验类型设计型实验,4学时。
2 实验目的通过设计、调试词法分析程序,掌握词法分析程序的设计工具,即有穷自动机,进一步理解自动机理论;掌握文法转换成自动机的技术及有穷自动机实现的方法;会确定词法分析器的输出形式及标识符与关键字的区分方法;加深对课堂教学的理解,提高词法分析方法的实践能力。
3 背景知识词法分析作为相对独立的阶段来完成(对源程序或中间结果从头到尾扫描一次,并作相应的加工处理,生成新的中间结果或目标程序)。
在词法分析过程中,编译程序从外部介质中读取源程序文件中的各个字符,为正确地识别单词,有时还需进行超前搜索和回退字符等操作。
因此,为了提高读盘效率和便于扫描器进行工作,通常可采用缓冲输入的方案,即在内存中设置一个适当大小的输入缓冲区,将磁盘上的源程序字符串分批送入该缓冲区中,供扫描器进行处理。
词法分析程序的一般设计方案是:1、程序设计语言词法规则⇒正则文法⇒ FA;或:词法规则⇒正则表达式⇒ FA;2、NFA确定化⇒ DFA;3、DFA最小化;4、确定单词符号输出形式;5、化简后的DFA+单词符号输出形式⇒构造词法分析程序。
从设计方案可知,要构造词法分析程序,必须掌握以下三个知识点:文法、正则表达式和FA。
文法与语言的形式定义如下:一个形式文法G 是下述元素构成的一个元组(V N,V T,P,S )。
其中:1、V T—非空有限的终结符号集,即Σ;终结符:一个语言不可再分的基本符号。
2、V N—非空有限的非终结符号集;非终结符:也称语法变量,用来代表语法范畴。
一个非终结符代表一个一定的语法概念,是一个类(集合)记号,而不是一个体记号。
3、S —开始符号/识别符号,S∈V N;4、P —产生式规则集(或叫规则或生成式或重写规则);产生式:形如α → β或α ::= β的表达式,其中α为左部,β为右部。
α∈(V T∪V N)+且至少含一个V N;β∈(V T∪V N)*。
(完整word版)编译原理词法分析程序实现实验报告
(完整word版)编译原理词法分析程序实现实验报告实验一词法分析程序实现一、实验内容选取无符号数的算术四则运算中的各类单词为识别对象,要求将其中的各个单词识别出来。
输入:由无符号数和+,-,*,/, ( , ) 构成的算术表达式,如1.5E+2-100。
输出:对识别出的每一单词均单行输出其类别码(无符号数的值暂不要求计算)。
二、设计部分因为需要选取无符号数的算术四则运算中的各类单词为识别对象,要求将其中的各个单词识别出来,而其中的关键则为无符号数的识别,它不仅包括了一般情况下的整数和小数,还有以E为底数的指数运算,其中关于词法分析的无符号数的识别过程流程图如下:GOTO 1:(完整word版)编译原理词法分析程序实现实验报告GOTO 2:三、源程序代码部分#include <stdio.h>#include<stdlib.h>#include <math.h>#define MAX 100#define UNSIGNEDNUMBER 1#define PLUS 2#define SUBTRACT 3#define MULTIPLY 4#define DIVIDE 5#define LEFTBRACKET 6#define RIGHTBRACKET 7#define INEFFICACIOUSLABEL 8#define FINISH 111int count=0;int Class;void StoreType();int Type[100];char Store[20]={'\0'};void ShowStrFile();//已经将要识别的字符串存在文件a中void Output(int a,char *p1,char *p2);//字符的输出过程int Sign(char *p);//'+''-''*''/'整体识别过程int UnsignedNum(char *p);//是否适合合法的正整数0~9int LegalCharacter(char *p);//是否是合法的字符:Sign(p)||UnsignedNum(p)||'E'||'.' void DistinguishSign(char *p);//'+''-''*''/'具体识别过程void TypyDistinguish();//字符的识别过程void ShowType();//将类别码存储在Type[100]中,为语法分析做准备void ShowStrFile()//已经将要识别的字符串存在文件a中{FILE *fp_s;char ch;if((fp_s=fopen("a.txt","r"))==NULL){printf("The FILE cannot open!");exit(0);}elsech=fgetc(fp_s);while(ch!=EOF){putchar(ch);ch=fgetc(fp_s);}printf("\n");}void StoreStr()//将文件中的字符串存储到数组Store[i] {FILE *fp=fopen("a.txt","r");char str;int i=0;while(!feof(fp)){fscanf(fp,"%c",&str);if(str=='?'){Store[i]='\0';break;}Store[i]=str;i++;}Store[i]='\0';}void ShowStore(){int i;for (i=0;Store[i]!='\0';i++)printf("%c",Store[i]);printf("\n");}void Output(int a,char *p1,char *p2){printf("%3s\t%d\t%s\t","CLASS",a,"VALUE");while(p1<=p2){printf("%c",*p1);p1++;}printf("\n");}int Sign(char *p){char ch=*p;if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch==')') return 1;elsereturn 0;}int UnsignedNum(char *p){char ch=*p;if('0'<=ch&&ch<='9')return 1;elsereturn 0;}int LegalCharacter(char *p){char ch=*p;if(Sign(p)||UnsignedNum(p)||ch=='E'||ch=='.')。
词法分析报告
编译原理实验报告实验一词法分析程序的设计与实现指导教师:姓名:学号:班级:一、实验目的基本掌握计算机语言的词法分析程序的开发方法。
二、实验内容编制一个能够分析三种整数、标识符、主要运算符和主要关键字的词法分析程序。
三、实验要求1.根据以下的正规式,编制正规文法,画出状态图;标识符<字母>(<字母>|<数字字符>)*十进制整数0 | (1|2|3|4|5|6|7|8|9) (0|1|2|3|4|5|6|7|8|9)*八进制整数0 (0|1|2|3|4|5|6|7) (0|1|2|3|4|5|6|7)*十六进制整数0 (x|X) (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 do2.根据状态图,设计词法分析函数int scan( ),完成以下功能:(1)从输入流(键盘或文件)读入数据,分析出一个单词。
(2)返回单词种别(用整数表示),(3)返回单词属性(不同的属性可以放在不同的全局变量中)。
3.编写测试程序,循环调用函数scan( ),每次调用,获得一个单词的信息。
在测试程序中,打印输出单词种别、属性(注意:不要在词法分析函数scan 中打印输出!)。
四、实验环境微型计算机。
Windows 操作系统/Linux 操作系统。
编程语言:C/C++/Java/C#。
建议使用Visual C++/Netbeans/Eclipse 集成开发环境。
五、实验步骤1. 根据状态图,设计词法分析算法2. 设计函数scan( ),实现该算法3. 编制测试程序(在本试验中,可以是主函数main( ) )。
4. 调试程序:输入一组单词,检查输出结果。
六、状态图七. 测试数据:0 92+data> 0x3f00 while八.测试结果九,思考题1.词法分析能否采用空格来区分单词?答:不能,因为比如abc+bcd中没有空格,但这是三个单词。
实验编译原理词法分析程序设计方案
实验1-3 《编译原理》S语言词法分析程序设计方案一、实验目的了解词法分析程序的两种设计方法之一:根据状态转换图直接编程的方式;二、实验内容1.根据状态转换图直接编程编写一个词法分析程序,它从左到右逐个字符的对源程序进行扫描,产生一个个的单词的二元式,形成二元式(记号)流文件输出。
在此,词法分析程序作为单独的一遍,如下图所示。
词法分析程序二元式文件源程序具体任务有:(1)组织源程序的输入(2)拼出单词并查找其类别编号,形成二元式输出,得到单词流文件(3)删除注释、空格和无用符号(4)发现并定位词法错误,需要输出错误的位置在源程序中的第几行。
将错误信息输出到屏幕上。
(5)对于普通标识符和常量,分别建立标识符表和常量表(使用线性表存储),当遇到一个标识符或常量时,查找标识符表或常量表,若存在,则返回位置,否则返回0并且填写符号表或常量表。
标识符表结构:变量名,类型(整型、实型、字符型),分配的数据区地址注:词法分析阶段只填写变量名,其它部分在语法分析、语义分析、代码生成等阶段逐步填入。
常量表结构:常量名,常量值三、实验要求1.能对任何S语言源程序进行分析在运行词法分析程序时,应该用问答形式输入要被分析的S源语言程序的文件名,然后对该程序完成词法分析任务。
2.能检查并处理某些词法分析错误词法分析程序能给出的错误信息包括:总的出错个数,每个错误所在的行号,错误的编号及错误信息。
本实验要求处理以下两种错误(编号分别为1,2):1:非法字符:单词表中不存在的字符处理为非法字符,处理方式是删除该字符,给出错误信息,“某某字符非法”。
2:源程序文件结束而注释未结束。
注释格式为:/* …… */四、保留字和特殊符号表141318171615121110单词代码.单词的构词规则:字母=[A-Za-z]数字=[0-9]标识符=(字母|_)(字母|数字)*=数字(数字)*(.数字|?)+数字四、S语言表达式和语句说明1.算术表达式:+、-、*、/、%2.关系运算符:>、>=、<、<=、==、!=3.赋值运算符:=,+=、-=、*=、/=、%=4.变量说明:类型标识符变量名表;5.类型标识符:int char float6.If语句:if 表达式then 语句 [else 语句]7.For语句:for(表达式1;表达式2;表达式3)语句 8.While语句:while 表达式 do 语句9.S语言程序:由函数构成,函数不能嵌套定义。
实验一 词法分析程序的设计与实现(C语言)
实验一 词法分析程序的设计与实现(C 语言)一、实验目的通过C 语言词法分析程序的实现理解编译程序过程中对单词的分析过程。
二、实验重难点DFA 自动机的数据结构表示,程序流程图,词法分析程序实现三、实验内容与要求实验内容:1. 设计存储DFA 自动机的数据结构2.绘制程序流程图3. 词法分析程序设计四、实验学时2课时五、实验设备与环境C 语言编译环境六、根据实验过程填写下列内容1.DFA 自动机的状态转换图和数据结构设计。
a /b2. 程序流程图(见附页)3. 代码#include<stdio.h>int f(int x,char e){ int df[4][2]={{2,3},{4,3},{2,4},{4,4}};U a a a S b Q bV bint i;if(e=='a')i=df[x][1];if(e=='b')i=df[x][2];return(i);}void main(){ int S=1,U=2,V=3,Q=4;int k=S;char c;printf("请输入字符,按#结束:\n");c=getchar();while(c!='#'){k=f(k,c);c=getchar();}if(k==Q) printf("你输入的字符串能被DFA所识别\n");else printf("你输入的字符串能被DFA所识别\n");}4.测试数据及结果分析(结果见附页)分析:从实验的结果可以看出上面程序代码基本上可以实现所给DFA的要求,但是有关实验的可读性和功能方面还有待进一步改进。
程序流程图教师评语:是否完成实验程序的预备设计? 是: 不是: 程序能否正常运行? 是: 不是: 有无测试数据及结果分析 是: 不是: 是否在本次规定时间完成所有项目? 是: 不是: 实验成绩等级: 教师签名:N0:时间:开始初始化输入句子判断是否退出标志判断是否被接受?接受不接受输出错误位置NY NY结束。
编译原理课程设计报告-词法分析器
一.课程设计题目:词法分析器的实现二.课程设计成员三.课程设计内容和要求设计一个程序,调试、编译,实现词法分析的功能,识别各单词或字符所属类别,并显示在屏幕上。
词法分析器:逐个读入源程序字符并按照构词规则切分成一系列单词。
单词是语言中具有独立意义的最小单位,包括保留字、标识符、运算符、标点符号和常量等。
词法分析是编译过程中的一个阶段,在语法分析前进行。
也可以和语法分析结合在一起作为一遍,由语法分析程序调用词法分析程序来获得当前单词供语法分析使用。
要求:通过词法分析器能够实现以下五种类型如单词等的识别。
(1)关键字"begin","end","if","then","else","while","write","r ead"等,"do", "call","const","char","until","procedure","repeat"等(2)运算符:"+","-","*","/","="等(3)界符:"{","}","[","]",";",",",".","(",")",":"等(4)标识符(5)常量四.操作要求首先建立一个或多个文档,此处新建了两个文档,例:07196133.txt文本文档和zhaoxiaodong.txt文本文档,以供选择,各文本文档中都输入有不同的内容,运行程序,出现提示,输入文本文档的名称,即可对文本文档中的内容进行分析,并把分析结果输出显示在屏幕上。
词法分析程序的设计原则单词的描述技术识别机制及词法
词法分析程序的设计原则,单词的描述技 术,识别机制及词法分析程序的自动构造 原理。
• 单词的描述工具 • 单词的识别系统 • 设计词法分析程序,实现词法分析程序的自动构造
回顾 什麽是词法分析程序
实现词法分析(lexical analysis)的程序
– 逐个读入源程序字符并按照构词规则切分成 一系列单词。 单词是语言中具有独立意 义的最小单位,包括保留字、标识符、运算 符、标点符号和常量等。 词法分析是编译过程中的一个阶段,在语法 分析前进行 。也可以和语法分析结合在一起 作为一遍,由语法分析程序调用词法分析程 序来获得当前单词供语法分析使用。
例3.2
={d,,e,+,-},
则上的正规式 d(dd )(e(+- )dd )表示的是
无符号数的集合。其中d为0~9的数字。
程序设计语言的单词都能用正规式 来定义.
有穷自动机
有穷自动机(也称有限自动机)作为一种识别装 置,它能准确地识别正规集,即识别正规式所 表示的集合.应用有穷自动机这个理论,为词法 分析程序的自动构造寻找有效的方法和工具。 有穷自动机分为两类:确定的有穷自动机 (Deterministic Finite Automata)和不确定的有 穷自动机(Nondeterministic Finite Automata) 。
词法分析工作从语法分析工作独立出来的 原因:
– 简化设计 – 改进编译效率 – 增加编译系统的可移植性
• 单词的描述工具-正规表达式 • 单词的识别系统-有穷自动机 • 设计词法分析程序,实现词法分析程序的自动构造
令={a,b}, 上的正规式和相应的正规 集的例子
a ab ab (ab)(ab) a (ab)
实验一手工编写简易词法分析程序
编译原理实验报告日期:班级:题目:组员: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、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
单词的词法分析程序设计
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.只考虑是否为单字符运算、限界符,若是,写输出文件
6 程序框图如下
7 程序结果如下(源程序见磁盘)
8实验感想
词法分析是编译的第一个阶段,它的主要任务是从左至右扫描整个程序的每个字符,将源程序变换为单词序列,以其内部的表示形式提供给语法分析的各阶段。
而做这个实验是使用的是c语言,并没有使用自动生成的词法分析器LEX,但是在做这个实验的时候参考了相关的书籍之后,使用文件打开,并保存输出结果的方式,这样比较能够使程序的通用性加强,同时作为刚开始接触到编译的前端的我,发现了自己还有许多的不足之处。
为了以后的语法分析能够结构更加的明晰,那么就必须认真的研读老师所给的相关资料,同时要学会分析较完整定义的相关文法,使之更为直接明了。
这个实验主要花费的时间,并不是在于词法分析即源文件中的scan扫描程序阶段,而是在设置文件的出错以及输出,输入阶段,这也说明在原来学习文件调用打开的时候并没有很熟练的运用文件之间的调用的相关操作,这也提醒我在今后学习语言的过程中要细致,要实践。