实验3__识别无符号数的词法分析器设计实现c++
- 格式:doc
- 大小:279.00 KB
- 文档页数:12
> C语言词法分析器设计与实现C语言词法分析器的设计与实现一.实验目的1.强化对系统软件综合工程实现能力、规划能力的训练;2.加强对词法分析原理、方法和基本实现技术的理解;二.实验内容用C语言(或 C++ )作为宿主语言完成:其中具体要求:1.使用DFA实现词法分析器的设计;2.实现对C源程序中注释的过滤;3.利用两对半缓冲区从文件中逐一读取单词;4.词法分析结果属性字流存放在独立文件中;5.统计源程序每行单词的个数和整个源文件单词个数;6.具有报告词法错误和出错位置(源程序行号和该行字符)的功能;7.屏幕输出属性字流,每次显示10行,按ESC可中途退出,每行有统计信息,最后有词法分析的全部信息,包括各种属性单词的个数。
三.实验验收与评分要求1.编写C语言词法分析器的源程序并调试通过;2.通过测试程序的验收 (测试程序名称:Test-Lexcial);3.提交简明扼要的书面实验报告。
内容包括:FA设计;源程序主要函数功能;主要数据结构设计。
四. 验收测试用例1. 测试用例一:统一验收测试用例;#include<stdio.h>#include<string.h>char buf[100],str[15];int countdef=0;FILE *fpmiddle;struct define{char with[30];char des[30];char filename[15];}def[30];char* getFileName(){int i=0,k=0;for(i=0;buf[i]!='<'&&i<30&&buf[i]!='\0';i++);i++;while(buf[i]!='>'&&i<30&&buf[i]!='\0')str[k++]=buf[i++];str[k]='\0';puts(str);return str;}long readline(FILE *fpt){if(fgets(buf,100,fpt)==NULL){puts(buf);printf("readline error or reach file end!\n");return 0;}puts(buf);return (long)(strlen(buf)+1);}void writeline(){fprintf(fpmiddle,"%s",buf);}void processDefine(char *filename){int i=8,j=0;while((def[countdef].des[i-8]=buf[i])!=' ') i++;def[countdef].des[i-8]='\0';while((def[countdef].with[j]=buf[i])!='\0'){i++;j++;}def[countdef].with[j-1]='\0';strcpy(def[countdef].filename,filename);countdef++;}long comment(FILE *fpt){char prechar=buf[0],ch='*';int i=0,j=0;for(i=0;buf[i]!='\0'&&!(buf[i]=='/'&&buf[i+1]=='*');i++) ;j=i;buf[i]='\0';if(i==strlen(buf)) return 0L;do{prechar=ch;if((ch=fgetc(fpt))==EOF){printf(" in comment, end");exit(0);}i++;}while(!(prechar=='*'&&ch=='/'));return (long)(i-j+1);}isin(char *p){int i=0,j=0,temp=0;while(temp!=strlen(buf)){while(buf[i]!='\0'&&buf[i]!=p[0])i++;temp=i;while(buf[i]==p[j]&&p[j]!='\0'&&buf[i]!='\0'){i++;j++;}if((i-temp)==strlen(p)) return temp;i=temp+1;j=0;}return -1;}void includeAndDefine(FILE *fpt){void add(char*);void replace(char*);while(readline(fpt)){if(isin("#include")>=0)add(getFileName());else if(isin("#define")>=0)processDefine(str);else{fseek(fpt,comment(fpt),1);replace(str);writeline();}}}void add(char *filename){void replace(char*);FILE *fpp;if((fpp=fopen(filename,"r"))==NULL){printf("file %s not found or open error!",filename);exit(0);}fseek(fpp,-readline(fpp),1);if(isin("#include")<0&&isin("#define")<0)while(readline(fpp)){fseek(fpp,comment(fpp),1);replace(filename);writeline();}elseincludeAndDefine(fpp);fclose(fpp);}void replace(char *filename){int i=0,start=0;for(i=0;i<countdef;i++)if(!strcmp(def[i].filename,filename))break;if(i>=countdef||(start=isin(def[i].des))==-1) return;else{int lenOfWith=strlen(def[i].with);int lenOfDes=strlen(def[i].des);if(lenOfDes>=lenOfWith){int k,j;for(k=start; k<start+lenOfWith; k++)buf[k]=def[i].with[k-start];for(j=(start+lenOfWith); j<start+lenOfDes; j++) buf[j]=' ';}else{int offset=lenOfWith-lenOfDes;int k,j;for(k=offset+strlen(buf);k>start;k--)buf[k]=buf[k-offset];for(j=start;j<start+lenOfWith;j++)buf[j]=def[i].with[j-start];}}}2. 自己编写的C语言词法分析器源码。
c词法分析器实验报告篇一:词法分析器设计实验报告计算机与信息学院(信息工程系)编译原理实验报告专业班级课程教学班任课教实验指导教师实验地点XX ~XX学年第一学期实验一词法分析器设计一、实验目的通过本实验的编程实践,使学生了解词法分析的任务,掌握词法分析程序设计的原理和构造方法,使学生对编译的基本概念、原理和方法有完整的和清楚的理解,并能正确地、熟练地运用。
二、实验内容用 VC++/VB/JAVA 语言实现对 C 语言子集的源程序进行词法分析。
通过输入源程序从左到右对字符串进行扫描和分解,依次输出各个单词的内部编码及单词符号自身值;若遇到错误则显示“Error”,然后跳过错误部分继续显示;同时进行标识符登记符号表的管理。
以下是实现词法分析设计的主要工作:(1)从源程序文件中读入字符。
(2 (3 (4(属性值——token 的机内表示)(5)如果发现错误则报告出错 7(6三、实验流程图四、实验步骤12、编制好源程序后,设计若干用例对系统进行全面的上机测试,并通过所设计的词法分析程序;直至能够得到完全满意的结果。
3、书写实验报告;实验报告正文的内容:五、实验结果篇二:C语言词法分析器实验报告计算机科学与工程系编译原理课程设计实验报告姓名:__ ******__ 学号_ *******__ 年级专业及班级___08计算机科学与技术成绩- 1 -- 2 -- 3 -- 4 -- 5 -篇三:词法分析器实验报告实验报告实验题目:词法分析器院系班级:计科系0901班姓名学号: XX210603实验时间:XX-10-21设计。
编制并调试一个词法分析程序,加深对词法分析原理的理解。
实验要求设计出一个简单的词法分析程序,能够识别关键字(包含begin、if、end、 while、else、 then)、标识符、数字及数种符号(+、-、*、/、(、)、:、=、:=、#、>、、=、;)。
返回并打印各类字符所对应的种类编码及该字符所组成的二元组。
无符号数的词法分析程序一、实验课程的性质、目的和任务1.培养学生初步掌握编译原理实验的技能。
2.验证所学理论、巩固所学知识并加深理解。
3.对学生进行实验研究的基本训练。
二、实验内容掌握词法分析的基本思想,并用高级语言编写无符号数的词法分析程序。
三、实验要求从键盘上输入一串字符(包括字母、数字等),最后以“;”结束,编写程序识别出其中的无符号数。
四、无符号数语法规则<无符号数>→<无符号实数>│<无符号整数><无符号实数>→<无符号整数>.<数字串>[E<比例因子>]│<无符号整数>E<比例因子><比例因子>→<有符号整数><有符号整数>→[+│-]<无符号整数><无符号整数>→<数字串><数字串>→<数字>{<数字>}<数字>→0 1 2 3 (9)五、实验流程图六、实验源代码#include<stdio.h>#include<stdlib.h>#include <errno.h>#include<ctype.h>#include<math.h>#define N 50char UnsignedNumber[N] ;/*用来储存提取出来的无符号数字符串*/ /*识别已经提取出来的无符号数字符串*/void ReadUnsignedNumber(){int w=0 ;int p=0 ;int j=0 ;int i=0 ;short e=1 ;short d=0 ;double DataValue ;while(isdigit(UnsignedNumber[i])){d=UnsignedNumber[i]-48 ;w=w*10+d ;i++ ;}if(UnsignedNumber[i]=='.'){i++ ;while(isdigit(UnsignedNumber[i])){d=UnsignedNumber[i]-48 ;w=w*10+d ;j++ ;i++ ;}if(UnsignedNumber[i]=='\0'){DataValue=w*pow(10,e*p-j) ;printf("The value of %s is %f\n",UnsignedNumber,DataV alue) ;}else if(UnsignedNumber[i]=='e'||UnsignedNumber[i]=='E'){i++ ;if(UnsignedNumber[i]=='-'){e=-1 ;i++ ;}else if(UnsignedNumber[i]=='+'){i++;}do{d=UnsignedNumber[i]-48 ;p=p*10+d ;i++ ;}while(isdigit(UnsignedNumber[i]));DataValue=w*pow(10,e*p-j) ;printf("The value of %s is %f\n",UnsignedNumber,DataV alue) ;}}else if(UnsignedNumber[i]=='e'||UnsignedNumber[i]=='E'){ i++ ;if(UnsignedNumber[i]=='-'){e=-1 ;i++ ;}else if(UnsignedNumber[i]=='+'){i++;}do{d=UnsignedNumber[i]-48 ;p=p*10+d ;i++;}while(isdigit(UnsignedNumber[i])) ;DataValue=w*pow(10,e*p-j) ;printf("The value of %s is %f\n",UnsignedNumber,DataV alue) ; }else{DataValue=w ;printf("The value of %s is %f\n",UnsignedNumber,DataV alue) ;}if (errno == ERANGE){printf("Overflow condition occurred!\n");}}int main(){char ch ;int i ;int flag=0 ;printf("Please input the data with ';' to end!\n") ;ch=getchar() ;/*扫描输入的字符串,从中提取无符号数字符串*/while(ch!=';'){i=0 ;while(!isdigit(ch)){if(ch==';'){break ;}ch=getchar() ;}while(isdigit(ch)){UnsignedNumber[i]=ch ;i++ ;ch=getchar() ;}if(ch=='.'){UnsignedNumber[i]=ch ;i++ ;ch=getchar() ;while(isdigit(ch)){UnsignedNumber[i]=ch ;i++ ;ch=getchar() ;}if(ch=='e'||ch=='E'){UnsignedNumber[i]=ch ;i++ ;ch=getchar() ;if(!isdigit(ch)){if(ch=='+'||ch=='-'){UnsignedNumber[i]=ch ;i++ ;ch=getchar();if(!isdigit(ch)){i-- ;UnsignedNumber[i]='\0' ;}else{do{UnsignedNumber[i]=ch ;i++ ;ch=getchar() ;}while(isdigit(ch)) ;if(ch=='.'){printf("The data you input is wrong!\n") ;exit(1) ;}else{UnsignedNumber[i]='\0' ;}}}else{i-- ;UnsignedNumber[i]='\0' ;}}else{do{UnsignedNumber[i]=ch ;i++ ;ch=getchar() ;}while(isdigit(ch)) ;if(ch=='.'){printf("The data you input is wrong!\n") ;exit(1) ;}else{UnsignedNumber[i]='\0' ;}}}else{UnsignedNumber[i]='\0' ;}}else if(ch=='e'||ch=='E'){UnsignedNumber[i]=ch ;i++ ;ch=getchar() ;if(!isdigit(ch)){if(ch=='+'||ch=='-'){UnsignedNumber[i]=ch ;i++ ;ch=getchar();if(!isdigit(ch)){i-- ;UnsignedNumber[i]='\0' ;}else{do{UnsignedNumber[i]=ch ;i++ ;ch=getchar() ;}while(isdigit(ch)) ;if(ch=='.'){printf("The data you input is wrong!\n") ;exit(1) ;}else{UnsignedNumber[i]='\0' ;}}}else{UnsignedNumber[i]='\0' ;}}else{do{UnsignedNumber[i]=ch ;i++ ;ch=getchar() ;}while(isdigit(ch)) ;if(ch=='.'){printf("The data you input is wrong!\n") ;exit(1) ;}else{UnsignedNumber[i]='\0' ;}}}else{UnsignedNumber[i]='\0' ;}if(i!=0){ReadUnsignedNumber() ;flag=1 ;}if(flag==0){printf("Sorry!There is no unsigned number in your data!\n") ;}}return 0 ;}七、实验结果。
实验三识别无符号数的词法分析器程序设计一、实验目的与要求通过编写并上机调试一个词法分析程序,掌握在对程序设计语言的源程序进行扫描的过程中,将源程序分解成各类单词的词法分析方法。
二、实验重难点DFA无符号数的词法分析器编码实现三、实验内容与要求1.阅读实验案例,明确实验要求和程序实现方案;2.参考实验案例,完善该无符号数的词法分析器设计程序。
四、实验学时2课时五、实验设备与环境C语言编译环境六、实验案例1.无符号数的词法分析器原理(1)正规式表示:Unsigned digital: d…d…d…dESd…d, it includes four regular expressions: dd* 如:5 56 567d*.dd* 如:.5 5.6 5.67d*ESdd* 如:E5 E+56 5E-67d*.dd*ESdd* 如:.5E5 5.65E+56 5.4E-67whileV T={0, ···,9, ·,+,-,E}d =0|1| ···|9S = +|-|ε(2)NFA表示:(3)经过NFA转DFA和DFA的化简后得到无符号数的DFA表示:2.设计要求选取无符号数的算术四则运算中的各类单词为识别对象,要求将其中的各个单词识别出来。
输入:由无符号数和+,-,*,/, ( , ) 构成的算术表达式,如1.5E+2-100。
输出:对识别出的每一单词均单行输出其类别码。
3 (对应-)1 (对应100)3、程序源代码:1.cp p4、运行结果:测试用例1:0.23E-12-E12结论:(1)案例中的程序只给出了A到B\C及其后续通路的程序,没有给出A到D及其后续通路的程序。
因此不能识别E12是一个无符号数。
测试用例2:0.23E*12/a(0.23E-12)结论:(2)案例中的程序只给出了若输入的字符串符合无符号数的DFA语法规则,将该无符号数识别出来,并没有给出当输入的字符串不符合无符号数的DFA语法规则时,如何处理。
编译原理无符号数识别程序设计1.实验目的设计无符号数识别程序2.实验要求无符号数的有穷自动机的实现3.实验环境VC++6.04.实验原理1、无符号数的BNF描述如下:0.<无符号数> → d <余留无符号数> | . <十进制数> | e <指数部分>1.<余留无符号数> → d <余留无符号数> | . <十进制数> | e <指数部分> | ε2.<十进制小数> → d <余留十进制小数>3.<余留十进制小数> e <指数部分> | d <余留十进制小数> | ε4.<指数部分> → d <余留整指数> | + <整指数> | - <整指数> 5.<整指数> → d <余留整指数>6.<余留整指数> → d <余留整指数> | ε2、将G[<无符号数>]文法转换成有穷自动机。
3、构造状态矩阵;将有穷自动机的状S1 S2 ……Sn及输入的字a1 a2 ……am 构成一个n*m的矩阵。
1、状态矩阵设计出一个词法分析程序识别无符号数。
2、扫描无符号数,根据文法给出无符号数出错的位置。
3、工具:C语言或其它高级语言4、实践时间:8学时无符号数的有穷自动机实现的思想用0-----表示无符号数;用1-----表示余留无符号数;用2----表示十进制小数;用3-----表示余留十进制小数;用4-----表示指数部分;用5-----表示整指数;用6-----表示余留整指数。
输入无符号数序列,从左到右扫描,遇到“#”号结束扫描。
设一个字符数组,接收输入的无符号数,对输入的无符号数逐一进行分析,用一个中间变量接收当前字符。
当前字符值发生错误时,输出错误信息;当前字符值正确时,分析下一个字符,反复判断,直至分析完毕。
词法分析器设计一、问题描述处理c语言源程序,过滤掉无用符号,判断源程序中单词的合法性,并分解出正确的单词,以二元组形式存放在文件中。
二、实验思路1、本实验思路很简单,就是逐个匹配测试文件的每个字符与程序中所标识的符号,总共分为几个比较模块,先是字母数字模块,可以识别出C语言程序中保留字,标识符和数字,其次是运算符和界符模块,可以识别出运算符和界符,最后一个模块就是未标识的符号,此时程序会报错,然后依次循环,直到文件结束。
2、采用结构体来存储符号的类型和符号本身:struct point{ char *kind;char value[10];};另外采用C语言文件指针和相关函数处理待测试文件以及测试结果文件。
3、程序中的函数名指示含义:keyword----保留字,Identifier---标识符,Digit---数字,CaculatorIdentifier---运算符,PatitionIdentifier---界符4、程序中所定义的符号采用char类型,只能对C语言中最常见的单字符的符号进行定义,如‘+’,‘<’,而对于“<=”,”>=”及“++”,“--”则不能处理。
因此本程序并不能实现对所有符号的归类。
三、实验代码#include <stdio.h>#include <string.h>char keywordtable[30][10]= {"int","char","float","double","signed","unsigned", "if","else","break","while","return","switch", "case","continue","for","default","void","const", "static","long","struct","auto","register","typedef", "enum","extern","short","goto","sizeof","do",};char caculatetable[15]={'+','-','*','/','%','(',')','=','>','<','#'};char partitiontable[10]={',',';','.',' ','{','}','"','[',']'};struct point{ char *kind;char value[10];};int IsLetter(char ch){ if(ch>='A'&&ch<='Z'||ch>='a'&&ch<='z') return 1;else return 0;}int IsDigit(char ch){if(ch>='0'&&ch<='9') return 1;else return 0;}int Reserve(char strToken[30]){for(int i=0;i<30;i++)if(strcmp(keywordtable[i],strToken)==0) return 1;return 0;}void operate(FILE *fp,struct point a){fp=fopen("d:测试结果.txt","a+");fprintf(fp,"< %s , %s >\n",a.kind,a.value);fclose(fp);}void Retract(FILE *fp)//顺序读写{ fseek(fp,-1L,1);}void Print(struct point a){ printf("< %s, \"%s\" >\n",a.kind,a.value);}int IsCaculator(char ch){int i;for(i=0;i<15;i++)if(caculatetable[i]==ch) return 1;return 0;}int IsPatition(char ch){ int i;for(i=0;i<10;i++)if(partitiontable[i]==ch) return 1;return 0;}int IsSpecial(char ch){if(ch=='+'||ch=='-'||ch=='/'||ch=='%'||ch=='>'||ch=='<'||ch=='*'||ch=='=') return 1;return 0;}int main(){int code;struct point result;char strToken[30];char ch;char *p;FILE *fp,*fq;fp=fopen("d:测试文件.txt","r");if(fp==NULL){ printf("file does not exit!!");return -1;}while(1){p=strToken;ch=fgetc(fp);if(feof(fp))//输入输出函数,检查文件是否结束,如结束,则返回非零值,否则返回0 break;if(ch==' ') continue;if(IsLetter(ch)){while(IsLetter(ch)||IsDigit(ch)){*p=ch;p++;*p='\0';ch=fgetc(fp);if(feof(fp))return -1;}Retract(fp);//顺序读取code=Reserve(strToken);if(code==1){ result.kind="keyword";//保留字strcpy(result.value,strToken);operate(fq,result);Print(result);}else{ result.kind="Identifier";//标识符strcpy(result.value,strToken);operate(fq,result);Print(result);}}else if(IsDigit(ch)){while(IsDigit(ch)){ *p=ch;p++;*p='\0';ch=fgetc(fp);if(feof(fp)) return -1;}Retract(fp);result.kind="Digit";//数字strcpy(result.value,strToken);operate(fq,result);Print(result);}else if(IsPatition(ch)||IsCaculator(ch)){ if(IsPatition(ch)){ result.kind="PatitionIdentifier";//界符*p=ch;p++;*p='\0';strcpy(result.value,strToken);operate(fq,result);Print(result);}if(IsCaculator(ch)){char ch2;ch2=fgetc(fp);if(!IsCaculator(ch2)) Retract(fp);result.kind="CaculatorIdentifier";//运算符*p=ch;p++;*p='\0';if(IsSpecial(ch)&&ch2=='='){ *p=ch2;p++;*p='\0';}if((ch=='>'||ch=='<'||ch=='+'||ch=='-')&&ch2==ch){ *p=ch2;p++;*p='\0';}strcpy(result.value,strToken);operate(fq,result);Print(result);}}else{ if(ch=='\n') continue;result.kind="Error!!";//其他未声明的均报错strcpy(result.value,strToken);operate(fq,result);//输出到测试结果文件printf("Error occurs! at %c\n",ch);}}return 1;}四、实验结果图1 实验结果测试文件:图2 测试文件测试结果文件:图3 测试结果文件五、实验总结本实验写的较为简单,只是表示了一些最常见的C语言符号,像是保留字,英文字母,数字,算术运算符和几个关系运算符,另外还有一些常见界符,如‘,’,‘;’,‘[’,‘]’,因为定义符号时采用char,这只适用单个字符的符号,而之后并没有再声明其他带有多个符号的符号,也就没有采用string类型或char[][]数组类型,所以像是测试文件中的注释符‘/*’,该程序就识别不出来,会提示报错;另外本实验在辨别符号时,采用穷举,没有用什么特别快捷的搜索方法,对一些较为简单的C语言程序,还是能识别出的。
词法分析c实现一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。
二、实验要求2.1 待分析的简单的词法(1)关键字:begin if then while do end所有的关键字都是小写。
(2)运算符和界符:= + - * / < <= <> > >= = ; ( ) #(3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:ID = letter (letter | digit)*NUM = digit digit*(4)空格有空白、制表符和换行符组成。
空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。
2.2 各种单词符号对应的种别码:输入:所给文法的源程序字符串。
输出:二元组(syn,token或sum)构成的序列。
其中:syn为单词种别码;token为存放的单词自身字符串;sum为整型常数。
例如:对源程序begin x:=9: if x>9 then x:=2*x+1/3; end #的源文件,经过词法分析后输出如下序列:(1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)……三、词法分析程序的C语言程序源代码:#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"};scaner();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();}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;ch=prog[p++];if(ch=='-'){ syn=29;token[m++]=ch;}else{ syn=14;p--;}break;case '!':ch=prog[p++];if(ch=='='){ syn=21;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;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;case '#': syn=0;token[m++]=ch;break;case ':':syn=17;token[m++]=ch;break;default: syn=-1;break;}token[m++]='\0';}四、结果分析:输入begin x:=9: if x>9 then x:=2*x+1/3; end # 后经词法分析输出如下序列:(begin 1)(x 10)(:17)(= 18)(9 11)(;26)(if 2)……如图5-1所示:。
词法分析器实验报告词法分析器实验报告一、引言词法分析器是编译器中的重要组成部分,它负责将源代码分解成一个个的词法单元,为之后的语法分析提供基础。
本实验旨在设计和实现一个简单的词法分析器,以深入理解其工作原理和实现过程。
二、实验目标本实验的目标是设计和实现一个能够对C语言代码进行词法分析的程序。
该程序能够将源代码分解成关键字、标识符、常量、运算符等各种词法单元,并输出其对应的词法类别。
三、实验方法1. 设计词法规则:根据C语言的词法规则,设计相应的正则表达式来描述各种词法单元的模式。
2. 实现词法分析器:利用编程语言(如Python)实现词法分析器,将源代码作为输入,根据词法规则将其分解成各种词法单元,并输出其类别。
3. 测试和调试:编写测试用例,对词法分析器进行测试和调试,确保其能够正确地识别和输出各种词法单元。
四、实验过程1. 设计词法规则:根据C语言的词法规则,我们需要设计正则表达式来描述各种词法单元的模式。
例如,关键字可以使用'|'操作符将所有关键字列举出来,标识符可以使用[a-zA-Z_][a-zA-Z0-9_]*的模式来匹配,常量可以使用[0-9]+的模式来匹配等等。
2. 实现词法分析器:我们选择使用Python来实现词法分析器。
首先,我们需要读取源代码文件,并将其按行分解。
然后,针对每一行的代码,我们使用正则表达式进行匹配,以识别各种词法单元。
最后,我们将识别出的词法单元输出到一个结果文件中。
3. 测试和调试:我们编写了一系列的测试用例,包括各种不同的C语言代码片段,以测试词法分析器的正确性和鲁棒性。
通过逐个测试用例的运行结果,我们可以发现和解决词法分析器中的问题,并进行相应的调试。
五、实验结果经过多次测试和调试,我们的词法分析器能够正确地将C语言代码分解成各种词法单元,并输出其对应的类别。
例如,对于输入的代码片段:```cint main() {int a = 10;printf("Hello, world!\n");return 0;}```我们的词法分析器将输出以下结果:```关键字:int标识符:main运算符:(运算符:)运算符:{关键字:int标识符:a运算符:=常量:10运算符:;标识符:printf运算符:(常量:"Hello, world!\n"运算符:)运算符:;关键字:return常量:0运算符:;```可以看到,词法分析器能够正确地将代码分解成各种词法单元,并输出其对应的类别。
实验一识别无符号数的词法分析器设计实现学院:计算机学院班级:学号:一、实验目的与要求通过编写并上机调试一个词法分析程序,掌握在对程序设计语言的源程序进行扫描的过程中,将其分解成各类单词的词法分析方法。
二、实验内容选取无符号数的算术四则运算中的各类单词为识别对象,要求将其中的各个单词识别出来。
输入:由无符号数和+,-,*,/, ( , ) 构成的算术表达式,如1.5E+2-100。
输出:对识别出的每一单词均单行输出其类别码(无符号数的值暂不要求计算)。
如1 (对应1.5E+2)3 (对应-)1 (对应100)三、程序源代码:#include<iostream>using namespace std;#define M 101 //最多可输入的字符数#define UNSIGNEDNUMBER 1 //无符号数#define PLUS 2 //加号#define SUBTRACT 3 //减号#define MULTIPL Y 4 //乘号#define DIVIDE 5 //除号#define LEFTBRACKET 6 //左括号#define RIGHTBRACKET 7 //右括号class AccidenceAnalysis //定义词法分析器类{private:char testStr[M],*p; //私有数据public:AccidenceAnalysis(); //构造函数void InputStr(); //输入函数void Output(int a,char *p1,char *p2); //输出函数int IsAcceptantCharacter(char *p); //判断输入字符是否属于字符集int IsOperator(char *p); //判断字符是否是字符集[+,-,*,/,(,)]中的字符int IsUnsignedNum(char *p); //判断字符是否是0--9的整数void AbnormityExamine(char a[]);void IdentifyOperator(char *p); //识别字符集[+,-,*,/,(,)]中的字符void AssortIdentify(); //对输入字符分类识别};AccidenceAnalysis::AccidenceAnalysis(){int i;for(i=0;i<M;i++)testStr[i]='\0';p=&testStr[0]; //指针P指向字符数组首元素}void AccidenceAnalysis::InputStr(){cout<<"\t请按要求输入您要分析的语句,所输字符应在要求范围(不超过"<<M<<")之内,并按回车键运行:";char ch;int i=0;while((ch=cin.get())!='\n'){testStr[i]=ch;i++;}AbnormityExamine(testStr);}void AccidenceAnalysis::AbnormityExamine(char a[]){int j=0;char *ptr1,*ptr2;ptr1=a;ptr2=a;while(*ptr2!='\0'){j++;if(!IsAcceptantCharacter(ptr2)){cout<<"\t您输入的第"<<j<<"个字符"<<*ptr2<<" 不可以被此程序识别!"\ <<" 将被跳过."<<endl;ptr2++;continue;}else{*ptr1=*ptr2;ptr1++;ptr2++;}}while(ptr1<=ptr2){*ptr1='\0';ptr1++;}}void AccidenceAnalysis::Output(int a,char *p1,char *p2) {cout<<"\t类别码:"<<a<<" 单词值:";while(p1<=p2){cout<<*p1;p1++;}cout<<endl;}int AccidenceAnalysis::IsOperator(char *p){char ch=*p;if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch==')') return 1;elsereturn 0;}int AccidenceAnalysis::IsUnsignedNum(char *p){char ch=*p;if('0'<=ch&&ch<='9')return 1;elsereturn 0;}int AccidenceAnalysis::IsAcceptantCharacter(char *p) {。
词法分析程序的设计与实现方法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,进入错误处理状态。
实验三识别无符号数的词法分析器程序设计一、实验目的与要求通过编写并上机调试一个词法分析程序,掌握在对程序设计语言的源程序进行扫描的过程中,将源程序分解成各类单词的词法分析方法。
二、实验重难点DFA无符号数的词法分析器编码实现三、实验内容与要求1.阅读实验案例,明确实验要求和程序实现方案;2.参考实验案例,完善该无符号数的词法分析器设计程序。
四、实验学时2课时五、实验设备与环境C语言编译环境六、实验案例1.无符号数的词法分析器原理(1)正规式表示:Unsigned digital: d…d…d…dESd…d, it includes four regular expressions: dd* 如:5 56 567d*.dd* 如:.5 5.6 5.67d*ESdd* 如:E5 E+56 5E-67d*.dd*ESdd* 如:.5E5 5.65E+56 5.4E-67whileV T={0, ···,9, ·,+,-,E}d =0|1| ···|9S = +|-|ε(2)NFA表示:(3)经过NFA转DFA和DFA的化简后得到无符号数的DFA表示:2.设计要求选取无符号数的算术四则运算中的各类单词为识别对象,要求将其中的各个单词识别出来。
输入:由无符号数和+,-,*,/, ( , ) 构成的算术表达式,如1.5E+2-100。
如1 (对应1.5E+2)3 (对应-)1 (对应100)3、程序源代码:1.cp p4、运行结果:测试用例1:0.23E-12-E12结论:(1)案例中的程序只给出了A到B\C及其后续通路的程序,没有给出A到D及其后续通路的程序。
因此不能识别E12是一个无符号数。
测试用例2:0.23E*12/a(0.23E-12)结论:(2)案例中的程序只给出了若输入的字符串符合无符号数的DFA语法规则,将该无符号数识别出来,并没有给出当输入的字符串不符合无符号数的DFA语法规则时,如何处理。
请将案例程序按下表规则补充完整。
错误提示有两层含义,一个是输入字符不属于输入字母表,一个是输入字符正确但不合语法规则,这两种错误都应该予以检测并给出相应的处理。
但案例程序只检测了第一种错误。
七、无符号数的词法分析器设计的完善1.设计要求,对案例程序的BUG进行完善:(1)案例中的程序只给出了A到B\C及其后续通路的程序,没有给出A到D及其后续通路的程序,请将A到D及其后续通路的程序给出。
(2)案例中只给出了若输入的字符串符合无符号数的DFA语法规则,将该无符号数识别出来,并没有给出当输入的字符串不符合无符号数的DFA语法规则时如何处理。
请将案2.词法分析程序(c++语言版,保持良好的缩进关系,主函数不能改,只能改AssortIdentify()、Output()函数等相应的函数):#include<iostream>using namespace std;#define M 101 //最多可输入的字符数#define UNSIGNEDNUMBER 1 //无符号数#define PLUS 2 //加号#define SUBTRACT 3 //减号#define MULTIPLY 4 //乘号#define DIVIDE 5 //除号#define LEFTBRACKET 6 //左括号#define RIGHTBRACKET 7 //右括号#define ILLEGAL 8 //非法的字符串class AccidenceAnalysis //定义词法分析器类{private:char testStr[M],*p; //私有数据public:AccidenceAnalysis(); //构造函数,功能一般是对类做初始化void InputStr(); //输入函数void Output(int a,char *p1,char *p2); //输出函数int IsAcceptantCharacter(char *p); //判断输入字符是否属于字符集int IsOperator(char *p); //判断字符是否是字符集[+,-,*,/,(,)]中的字符int IsUnsignedNum(char *p); //判断字符是否是0--9的整数void AbnormityExamine(char a[]); //异常检测函数void IdentifyOperator(char *p);//识别字符集[+,-,*,/,(,)]中的字符void AssortIdentify(); //对输入字符分类识别};AccidenceAnalysis::AccidenceAnalysis(){int i;for(i=0;i<M;i++)testStr[i]='\0';// \0是C++中字符串的结尾标志,存储在字符串的结尾。
p=&testStr[0]; //指针P指向字符数组首元素}void AccidenceAnalysis::InputStr(){cout<<"\t请按要求输入您要分析的语句,所输字符应在要求范围(不超过"<<M<<")之内,并按回车键运行:";char ch;int i=0;while((ch=cin.get())!='\n') // cin.get()是保留回车在输入流队列中的.而cin是丢弃回车的.{testStr[i]=ch;i++;}AbnormityExamine(testStr);}void AccidenceAnalysis::AbnormityExamine(char a[]){int j=0;char *ptr1,*ptr2;ptr1=a;//指向字符串数组aptr2=a;while(*ptr2!='\0'){j++;if(!IsAcceptantCharacter(ptr2)){cout<<"\t您输入的第"<<j<<"个字符 "<<*ptr2<<" 不可以被此程序识别!"\ <<" 将被跳过."<<endl;ptr2++;continue; //结束本次循环,继续下次循环,并且进行条件判断;}else{*ptr1=*ptr2;ptr1++;ptr2++;}}while(ptr1<=ptr2){*ptr1='\0';ptr1++;}}void AccidenceAnalysis::Output(int a,char *p1,char *p2){ if(a!=ILLEGAL){cout<<"\t类别码:"<<a<<" 单词值:";while(p1<=p2){cout<<*p1;p1++;}} else{cout<<"\t类别码:"<<a<<"非法的字符串:";while(p1<=p2){cout<<*p1;p1++;}cout<<endl;}}int AccidenceAnalysis::IsOperator(char *p){char ch=*p;if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch==')') return 1;elsereturn 0;}int AccidenceAnalysis::IsUnsignedNum(char *p){char ch=*p;if('0'<=ch&&ch<='9')return 1;elsereturn 0;}int AccidenceAnalysis::IsAcceptantCharacter(char *p){char ch=*p;if(IsOperator(p)||IsUnsignedNum(p)||ch=='E'||ch=='.') return 1;else return 0;}void AccidenceAnalysis::IdentifyOperator(char *p){char ch=*p;switch(ch){case '+':Output(PLUS,p,p);break;case '-':Output(SUBTRACT,p,p);break;case '*':Output(MULTIPLY,p,p);break;case '/':Output(DIVIDE,p,p);break;case '(':Output(LEFTBRACKET,p,p);break;case ')':Output(RIGHTBRACKET,p,p);break;default:break;}}void AccidenceAnalysis::AssortIdentify(){while(*p!='\0'){ //从DFA的初始状态出发进行分类识别if(IsOperator(p))//情况1:从状态A出发,判断输入是否为符号,如果是,则不是无符号数,而是运算符,调用运算符识别函数IdentifyOperator(char *p)识别运算符。
{IdentifyOperator(p++);continue;}else if(IsUnsignedNum(p)||*p=='.')//情况2:从状态A出发,判断输入是否为为数字或者'.'{char *p1=p; //拼数,从指针p1到指针p之间的所有的字符串if(IsUnsignedNum(p)) //情况2.1:从状态A出发,如果输入为数字,到达状态B{while(IsUnsignedNum(p)) //情况2.1.1:B之后如果输入为数字,且后面都是数字,则到达终态B,可以判定为无符号数。
p++;if(*p=='\0'){Output(UNSIGNEDNUMBER,p1,--p); //拼数,从指针p1到指针p之间的所有的字符串p++;continue;}else if(*p=='E') //情况2.1.2:B之后如果输入E,到达状态D,需要进一步判断。