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

合集下载

词法分析程序实验报告

词法分析程序实验报告

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

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

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

(一)实验内容(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语句的条件,解决了此问题。

c词法分析器实验报告

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)、标识符、数字及数种符号(+、-、*、/、(、)、:、=、:=、#、>、、=、;)。

返回并打印各类字符所对应的种类编码及该字符所组成的二元组。

(完整版)C语言词法分析器实验报告汇总

(完整版)C语言词法分析器实验报告汇总

计算机科学与工程系编译原理课程设计实验报告扫描数字: 是f 判别为自减符Ch 是否为‘-'判别为”-> ”预读ch预读ch判别为负号 回退3Ch 为数字或‘预读ch扫描引号:扫描单词:实验步骤:1、准备:用TC、VC++等开发工具;2、对本实验的任务进行分析,确定实现功能的函数;3、写好程序,仔细修改函数;4、上机操作:输入源程序,修改、调试,运行。

5、写好试验报告。

实验调试过程及测试结果代^码******************************/#in clude<stdio.h> #in clude<stdlib.h> #in elude <ctype.h> #in clude<stri ng.h> void mai n()FILE *fp,*fp1;int guanjz(char ch1[]);〃关键字和标识符判断int hanjsq=1;〃行计数器,保存行号char ch,infile[15],outfile[15];〃定义输入和输出文件名prin tf("*****************E nter the infilename*****************sca nf("%s",i nfile);// 输入需要扫描的文件名printf( Enter the outfile n ame******************\n");scan f("%s",outfile);// 输入需要另存为的文件名if((fp = fope n(i nfile,"r")) == NULL)// {prin tf("ca nnot ope n file\n");exit(0);}if((fp1 = fope n(outfile,"w")) == NULL)// 打开需要扫描的文件打开需要存入的文件/*******************************{printf("cannot open file'n"); exit(O); }printf("\n******************************************************** printf( "******************************************************* printf("\n******************************************************** printf( "******************************************************* fprin tf(fp1,"*******************************************************fprin tf(fp1, while(!feof(fp)) {ch=fgetc(fp); if(ch==1O)hanjsq++;if(isalpha(ch) || ch=='_')〃 如果第一个字符为字母或下划线则判断为标识符{int i=0; char ch1[30];〃 假疋母个标识付取长为ch1[i++]=ch;〃将ch 保存到ch1[0]中并使i 自加1while(!feof(fp)) {ch=fgetc(fp);if(ch==1O)hanjsq++;〃 如果ch 为换行符,则行计数器自加 1if(isalpha(ch) || isdigit(ch) || ch=='')扫描头文件单词及保留字*********************printf("* 》开始进行词法分析 《*\ n");printf (”行号 字符串 种别码\n");fprin tf(fp1,"行号 字符串 种别码\n"); **\ n");{fseek(fp,-1,1);//fp 回退 1ch1[i]='\0';〃 把结束标志放到 ch1[i]中作为单词结束标志prin tf("li ne %d:%s%d\n",hanjsq,ch1,guanjz(ch1));〃以字符串形式输fprin tf(fp1,"li ne %d: %s%d\n" ,hanjsq,ch1,guanjz(ch1));break; }} if(!isalpha(ch) && !isdigit(ch) && ch!='_' && ch!='.') {//如果ch 不为字母、数字、下划线和点时判断其为标识符ch1[i]='\0'; prin tf("li ne %d: fprin tf(fp1,"li ne %d:%s{//如果ch 为字母、数字或下划线就把ch 放到ch1[i]中并使i 自加1ch1[i++]=ch; }if(ch=='.')〃 如果ch 为小数点则判断是否为头文件{if((ch=fgetc(fp))=='h')〃如果小数点后一位为 h 则判定其为头文件{if(ch==10)hanjsq++; chi[i++]='.'; chi[i++]='h'; ch1[i]='\0';〃 把结束标志放到 chi[i]中作为单词结束标志prin tf("li ne %d: %s83\n",hanjsq,ch1);〃以字符串形式输出 ch1fprin tf(fp1,"li ne %d: %s83\n",hanjsq,ch1);break;else//如果小数点后一位不是h 则判定其为标识符出chi%s%d\n",hanjsq,ch1,guanjz(ch1)); %d\n ”,hanjsq,ch1,guanjz(ch1));if(isdigit(ch) || ch=='-')〃如果ch 为数字或'-'if(isdigit(ch))//如果ch 为数字prin tf("li ne %d:%c",hanjsq,ch);while(!feof(fp))if(isdigit(ch) || ch=='.')prin tf("%c",ch); fprin tf(fp1,"%c",ch);else//否则视为数字结束printf (” fprin tf(fp1,"ch='O :〃 置ch 为0,以免影响下面误判并顺利退出扫描数字 break;break;/************************j 扫描数*************************/fprintf(fp1,"line %d: %c",hanjsq,ch);ch=fgetc(fp);〃预读一位如果 ch 为数字和点则循环输出46\n");46\n");fseek(fp,-1,1);〃回退一位if(ch=='-')〃如果ch 为'-'ch=fgetc(fp);〃 预读一位if (ch=='-')〃 如果ch 还是为'-'则判断为自减符'--' {prin tf("li ne %d: fprintf(fp1,"line %d: }if(isdigit(ch))〃 如果ch 为数字则可能为减号或负号{fseek(fp,-3,1);〃 回退 3 为判断ch=fgetc(fp); if(isdigit(ch))〃如果ch 为数字则判断'-'为减号ch=fgetc(fp); prin tf("li ne %d:%cfprin tf(fp1,"li ne %d: }else //否则判断'-'为负号 {ch=fgetc(fp); prin tf("li ne %d: fprin tf(fp1,"li ne %d: while(!feof(fp)) {ch=fgetc(fp);〃79\n" ,hanjsq,ch);%c 79\n",hanjsq,ch);80\n",hanjsq);80\n",hanjsq);如果ch 为'>',则判断为结构体运算符’->'{prin tf("li ne %d:->fprin tf(fp1,"li ne %d:->81\ n",hanjsq);81\ n",hanjsq);预读一位如果 %c",hanjsq,ch);%c",hanjsq,ch);ch 为数字和点则循环输出if(ch=='>')〃 }if(isdigit(ch) || ch=='.') {prin tf("%c",ch);fprin tf(fp1,"%c",ch);}扫描注释**********************else//否则视为数字结束{printf(”46\n");fprin tf(fp1," 46\n");fseek(fp,-1,1);// 回退1break;}}}if(ch=='/')〃如果ch为'/'则可能为注释{ch=fgetc(fp);〃读下一个字符if(ch==10)hanjsq++;if(ch=='/')〃如果该字符也为'/'则判断为注释一行{while(fgetc(fp)!=10);if(ch==10)hanjsq++;〃直到遇到换行符出现才认为注释结束}if(ch=='*')〃如果该字符为'*'则判断为注释多行{//直到出现’*/' 才认为注释结束while(!feof(fp)) {ch=fgetc(fp); if(ch==10)hanjsq++; if(ch=='*')〃 出现'*'{//且接着出现'/' if((ch=fgetc(fp))=='/')break;while(!feof(fp))else// 否则原样输出'/'prin tf("li ne %d: fprintf(fp1,"line %d:83\n",hanjsq);83\n",hanjsq);fseek(fp,-1,1);〃 回退1break;/***********************扫描引号 ************************/ if(ch==””)〃出现引号int i=0;prin tf("li ne %d:%cfprin tf(fp1,"li ne %d: %c 82\n",hanjsq,ch);82\n",hanjsq,ch);prin tf("li ne %d: ",hanjsq);fprin tf(fp1,"li ne %d:",hanjsq);{//先整体输出引号内所有字符并定为第99类ch=fgetc(fp);i++;〃用于积累回退长度 if(ch==10)hanjsq++; if(ch!=””) {if(ch!=32) {prin tf("%c",ch); fprin tf(fp1,"%c",ch); } }else break;} printf (” fprin tf(fp1," fseek(fp,-i,1);// for(;i>0;i--) {ch=fgetc(fp);if(ch==92)// 如果ch 为'\'则可能为转义字符 {char ch5[13]={"abfntv\\?'\"0"}; // 转义字符集ch=fgetc(fp);// 预读一位 for(int k=0;k<12;k++) {//如果为转义字符则输出if(ch==ch5[k]) {99\n");99\n");回退到引号开始printf(”line %d: \\%c%d\n" ,hanjsq,ch,k+33);fprin tf(fp1," li ne %d: \\%c }}if(ch=='d' && isdigit(fgetc(fp)) && isdigit(fgetc(fp)))〃{fseek(fp,-2,1);prin tf(" line %d: %c%cfprin tf(fp1," line %d: %c%c }if(ch=='x' && isdigit(fgetc(fp)) && isdigit(fgetc(fp)))//{fseek(fp,-2,1);prin tf(" line %d: %c%cfprin tf(fp1," line %d: %c%c }}if(ch=='%')〃如果为'%'则可能为%s%c%d%d\n",hanjsq,ch,k+33);任意字符转换为三位八进制44\n",hanjsq,fgetc(fp),fgetc(fp));44\n “,hanjsq,fgetc(fp),fgetc(fp));任意字符转换为二位十六进制45\n",hanjsq,fgetc(fp),fgetc(fp));45\n",hanjsq,fgetc(fp),fgetc(fp));{ch=fgetc(fp);char bfh[4]={"dcs"};for(i=0;i<3;i++){if(bfh[i]==ch){prin tf(" line %d: %%%c fprin tf(fp1," line %d: %%%c 83\n",hanjsq,ch);83\n",hanjsq,ch);}}}}描其他符^号 ********************/if(!isdigit(ch) && !isalpha(ch) && ch!='_' && ch!=”” && ch!='/')char ch2[14]={"#()[]{}'*:~%A"};〃for(i nt i=0;i<13;i++) {//判断单个符号if(ch==ch2[i])for(i nt j=0;j<8;j++) {//判断双符号if(ch==ch3[j])ch=fgetc(fp);//预读一位//if(ch==10)hanjsq++; if(ch==ch4[j]){//且ch 与ch4第j 个匹配,则表示 ch3[j]与ch4[j]if(ch=='<' && ch3[j]=='<')〃prin tf("li ne %d:%c%c%d\n",hanjsq,ch3[j],ch4[j],i+69);fprin tf(fp1,"li ne %d:%c%c%d\n",hanjsq,ch3[j],ch4[j],i+69);/*********************char ch3[9]={"+?=|&!<>"};// 定义部分单符号或双符号(前半部分)集 char ch4[9]={"+==|&==="};//定义部分双符号(后半部分)定义部分单符号集prin tf("li ne %d: %c%d\n" ,hanjsq,ch,i+48);fprintf(fp1,"line %d:%c%d\n",hanjsq,ch,i+48);{//如果ch 与ch3中第j个字符匹配 连起来为一个双符号判断'<<'符prin tf("li ne %d:fprin tf(fp1,"li ne %d:}if(ch=='>' &&ch3[j]=='>')〃{prin tf("li ne %d:fprin tf(fp1,"li ne %d:}else//否则表示ch3[j]{prin tf("li ne %d:fprin tf(fp1,"li ne %d:fseek(fp,-1,1);}}}}<<<<判断'>>'符>>>>为单符号,不是双符号的%c%c77\n",hanjsq);77\n",hanjsq);78\n",hanjsq);78\n",hanjsq);部分%d\n",hanjsq,ch3[j],j+61);%d\n" ,hanjsq,ch3[j],j+61)****************************************************************************************** printf( **\n");prin tf("* 》词法分析结束prin tf("* 》分析结果保存在文件%$中prin tf("* 》欢迎下次使用,谢谢!《*\n"); 《*\ n",outfile);《*\n");printf( **\n");fprin tf(fp1, **\ n");fprin tf(fp1,"*》词法分析结束《*\n");fprin tf(fp1,"*》欢迎下次使用,谢谢! 《*\n");-21-**\ n");in t guanjz(char ch1[])〃 关键字和标识符判断{char ch2[32][9]={"auto","double","i nt","struct","break","else","lo ng","switch","case","e num","register","typedef","char","extern","return","u nio n","co nst","float","short", "un sig ned","co nti nue","for","sig ned","void","default","goto","sizeof', "volatile","do","while","static","if"};〃for(int i=0;i<32;i++){//逐个比对如果为关键字则返回类别i+1if(!strcmp(ch1,ch2[i]))return i+1;return 47;//否则返回一般标识符类竝船悅Q )動勒卜1 Inc 1: u 4Sline 12 iniclude 4?1 ine 1* <b'fline 1 =. Ili B3lino is >hVlliw 2s U 4Rlima 2s inaludo 47a I M 2? <67 line 2s atAlib.hlinfi 2: > GS line 3; voidline main<17 line 3: <J. inc 3 = > ba line 3: S3 1 inc Ss riLE47 1 Irte 5:lime S ; __ s4?test・曹■:M 曹Entei' t hs outf ile ri 之盯日****^***-¥******<^^ cf F MQI , txt a t ■ w a w at it at ■ at ituif at it at U tguit at ■ • ac n unit ar ・ a t ariMiM at MTM a t :M at ■ u at 心 开史舱行词法分析 <* 讪:"Ik 1: 血1: line 1: Ike]: H UE 2: Iine2: line 2: lines : !k2: line 3: line 3: line 5; line 3: lineS: lint 5: J5QE 5:inclu tstdin hCaiLFIL E丰ft:■:•S3=;阴i 7占fl定义关键字集-22 -:B 豪溥■ ar 河*"百■苜筒n w i {耳鼻p n t 尸广 『卄戸1 nt- _i I n Finp 卄 可・w 耳黑図耳溥■ ar ・鼻*E E 戸F trst«t 具t■ if 耳材imcirHirjtKjnf i fK^nrBl* Th& outf lie 寺暮打補整并*需斗弭書!**祥略再整番 cffXQ-tXt at ir uif at ■ u u KM at ■・ at MENU at ■ U M ~W ;M a t WM a t aa ・:■■■!< IT ar ~K af M E :I m a t at nwu at心开给进行词法分析 3 =!K X KM X MM X X MJ4 K M M X KM X K M X MMX M M M MM M X K M X <M MM MM MMX KKXXMM X MM K MMK K liine line 丄±n& line lino 1 irie linn llnft line liri@ Urie line line 丄inc line linn line line n include stdllo .li includostdlib.lh uo id Piaui PILE 48 4? G7 83 bS 1? 67 68 24 4?印呼 bU 53 4? -1? Line 2C 4Gi Limo 2^鼻llna 26 cnimt 47Line 2& >Line 27 9 JlE & E Line 27 if3Z line 27 C 49 Lime H7 st>£rii^ 47 line 2? C 51 Line 2? 1 47 Line 27 J ^2 Lime 2? 71 Lino 2? ■ «3Jifle 7.7=Livw 2? i 55 Lino 2? > saline 27 55Line 27 > 50 Lino 28 printf 47 1 Ine 2» C 49 Line 20 ii S2Lino 纫 xd\n1血2& + 61 lint 2& T alint 2&■ccmtrlint 26 1 ) 50 line A else6血27 if $IT f X49 1血H Etring Ji 血H [ 51]ine 牙 1 1 rlillE H ] 血H LIM 二line 卵 -1遊H1遊2T)血2TJ 1]inc 2T )line 28 printf 眄 line 28 ■:191U23 ifI LDE 28册-23 -liit 31: liiE 31:y Ike y c-uritrirqiue printFine 3U:<V Igf PF FInCKdXnNdine SI R *\n+ +++c a unt分析结果保总结:lhe加line 29: 1血亚line 3:lii诃;line SO;lbue 50:\be30:line 30:line:fl:Hie 50:luie 馬:血数lhs33!line J3:):rintf(*rfrrfinlMtnHJ\p卄i:wqJIq:4r»-I—ru=rfc-pFlL.■i^u-In—r^vFhdfLJ.rkj"rnuriui指导教师签名:2011年4月12日星期二。

实验一词法分析器实验报告示例

实验一词法分析器实验报告示例

词法分析器实验报告一.需求分析1.C语言关键字的子集,以文件形式保存,待判断的C语言语句以文件形式保存。

2.关键字文件包括标识符、基本字、常数、运算符和界符以及相应的种别码。

3.在计算机终端顺次输出各词法单位的种别码和值。

若为标识符,其值为该标识符在标识符表中的位置;若为常数,其值为该常数在常数表中的位置;其余值为-1。

非法输入单词的种别码为-1,值为-2。

4.“单词”定义:C语言中最小的语法单位。

“标识符”定义:用户自定义的标志符。

5.测试数据:文本文件为unknowedword.text二.概要设计1.单词种别码设计如表一所示:A标识符及关键字如图一所示:图一.标识符状态转换图B实数如图二所示:图二.实数状态转换图C图三.运算符状态转换图D其它与运算符雷同,此处略3. 数据结构know[N] 用来存放构成单词符号的字符串;unknow[N]用来存放待辨别的字符串;chartab[T][N] 用来存放识别出的标识符;keytab[M][N] 用来存放从文件中读入的基本字;consttab[T] 用来存放识别出的实数。

以上均设为全局变量。

4.基本操作Getchar()初始条件:unknow中读入了一串待辨别的字符串。

操作结果:从unknow读入一个字符到ch中,指向unknow的指针加1。

Getbc()初始条件:unknow中读入了一串待辨别的字符串。

操作结果:从unknow中读入不是空格的下一个字符。

Concat()初始条件:know中为字母且ch中为字母,或know中为数字(包括小数点)ch中也为数字。

操作结果:将ch中的字符连接到know中。

Isletter()初始条件:ch中已经读入了一个新的字符。

操作结果:判断ch中的字符是否字母。

Isdigit()初始条件:ch中已经读入了一个新的字符。

操作结果:判断ch中的字符是否数字。

Keyword()初始条件:已判断出know中的字符串为标识符。

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

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

计算机科学与工程系编译原理课程设计实验报告姓名:__ ******__ 学号_ *******__ 年级专业及班级___08计算机科学与技术成绩扫描引号:扫描单词:扫描其他字符:实验环境:需要TC、VC++ 6.0等开发工具作为本次试验的环境。

fprintf(fp1,"*********************************************************\n");}int guanjz(char ch1[])//关键字和标识符判断{char ch2[32][9]={"auto","double","int","struct","break","else","long","switch","case","enum", "register","typedef","char","extern","return","union","const","float","short","unsigned","continue","for","signed","void","default","goto","sizeof","volatile","do","while","static","if"};//定义关键字集for(int i=0;i<32;i++){//逐个比对如果为关键字则返回类别i+1if(!strcmp(ch1,ch2[i]))return i+1;}return 47;//否则返回一般标识符类}总结:指导教师签名:2011年4月12日星期二。

词法分析器实验报告

词法分析器实验报告

词法分析器实验报告词法分析器实验报告词法分析器设计一、实验目的:对C语言的一个子集设计并实现一个简单的词法分析器,掌握利用状态转换图设计词法分析器的基本方法。

利用该词法分析器完成对源程序字符串的词法分析。

输出形式是源程序的单词符号二元式的代码,并保存到文件中。

二、实验内容:1. 设计原理词法分析的任务:从左至右逐个字符地对源程序进行扫描,产生一个个单词符号。

理论基础:有限自动机、正规文法、正规式词法分析器(Lexical Analyzer) 又称扫描器(Scanner):执行词法分析的程序2. 词法分析器的功能和输出形式功能:输入源程序、输出单词符号程序语言的单词符号一般分为以下五种:关键字、标识符、常数、运算符,界符3. 输出的单词符号的表示形式:单词种别用整数编码,关键字一字一种,标识符统归为一种,常数一种,各种符号各一种。

4. 词法分析器的结构单词符号5. 状态转换图实现三、程序设计1.总体模块设计/*用来存储目标文件名*/string file_name;/*提取文本文件中的信息。

*/string GetText();/*获得一个单词符号,从位置i开始查找。

并且有一个引用参数j,用来返回这个单词最后一个字符在str的位置。

*/string GetWord(string str,int i,int& j);/*这个函数用来除去字符串中连续的空格和换行int DeleteNull(string str,int i);/*判断i当前所指的字符是否为一个分界符,是的话返回真,反之假*/bool IsBoundary(string str,int i);/*判断i当前所指的字符是否为一个运算符,是的话返回真,反之假*/bool IsOperation(string str,int i);/*此函数将一个pair数组输出到一个文件中*/void OutFile(vector<pair > v);</pair/*此函数接受一个字符串数组,对它进行词法分析,返回一个pair型数组*/vector<pair > analyst(vector vec);</pair/*此函数判断传递的参数是否为关键字,是的话,返回真,反之返回假*/ bool IsKey(string str);2.各模块设计(1).首先根据上面单词符号表及ID和NUM的正规定义式,构造出状态转换图;(2).定义相关的变量和数据结构。

词法分析器实验报告

词法分析器实验报告词法分析器实验报告一、引言词法分析器是编译器中的重要组成部分,它负责将源代码分解成一个个的词法单元,为之后的语法分析提供基础。

本实验旨在设计和实现一个简单的词法分析器,以深入理解其工作原理和实现过程。

二、实验目标本实验的目标是设计和实现一个能够对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运算符:;```可以看到,词法分析器能够正确地将代码分解成各种词法单元,并输出其对应的类别。

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

词法分析器实验报告一、实验目的及要求本次实验通过用C语言设计、编制、调试一个词法分析子程序,识别单词,实现一个C语言词法分析器,经过此过程可以加深对编译器解析单词流的过程的了解。

运行环境:硬件:windows xp软件:visual c++6.0二、实验步骤1.查询资料,了解词法分析器的工作过程与原理。

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

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

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

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

三、实验内容本实验中将c语言单词符号分成了四类:关键字key(特别的将main说明为主函数)、普通标示符、常数和界符。

将关键字初始化在一个字符型指针数组*key[]中,将界符分别由程序中的case列出。

在词法分析过程中,关键字表和case列出的界符的内容是固定不变的(由程序中的初始化确定),因此,从源文件字符串中识别出现的关键字,界符只能从其中选取。

标识符、常数是在分析过程中不断形成的。

对于一个具体源程序而言,在扫描字符串时识别出一个单词,若这个单词的类型是关键字、普通标示符、常数或界符中之一,那么就将此单词以文字说明的形式输出.每次调用词法分析程序,它均能自动继续扫描下去,形成下一个单词,直到整个源程序全部扫描完毕,从而形成相应的单词串。

输出形式例如:void $关键字流程图、程序流程图:程序:#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;return 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("%s\t$普通标识符\n\n",Word);//不是关键字else if(c==2) printf("%s\t$主函数\n\n",Word);else printf("%s\t$关键字\n\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("%s\t$无符号实数\n\n",Word);}else //开始判断的字符不是字母也不是数字{Word[0]=ch;switch(ch){case'[':case']':case'(':case')':case'{':case'}':case',':case'"':case';':printf("%s\t$界符\n\n",Word); break;case'+':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("%s\t$运算符\n\n",Word);//运算符“+=”}else if(ch=='+'){printf("%s\t$运算符\n\n",Word); //判断结果为“++”}else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word); //判断结果为“+”}break;case'-':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("%s\t$运算符\n\n",Word); }else if(ch=='-'){printf("%s\t$运算符\n\n",Word); //判断结果为“--”}else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word); //判断结果为“-”}break;case'*':case'/':case'!':case'=':ch=fgetc(fp);if(ch=='='){printf("%s\t$运算符\n\n",Word);}else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word);}break;case'<':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("%s\t$运算符\n\n",Word); //判断结果为运算符“<=”}else if(ch=='<'){printf("%s\t$运算符\n\n",Word); //判断结果为“<<”}else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word); //判断结果为“<”}break;case'>':ch=fgetc(fp);Word[1]=ch;if(ch=='=') printf("%s\t$运算符\n\n",Word);else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word);}break;case'%':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("%s\t$运算符\n\n",Word);}if(IsAlpha(ch)) printf("%s\t$类型标识符\n\n",Word);else {fseek(fp,-1,1);printf("%s\t$取余运算符\n\n",Word);}break;default:printf("无法识别字符!\n\n"); break;}}}main(){char in_fn[30]; //文件路径FILE *fp;printf("\n请输入源文件名(包括路径和后缀名):");while(1){gets(in_fn);//scanf("%s",in_fn);if((fp=fopen(in_fn,"r"))!=NULL) break; //读取文件内容,并返回文件指针,该指针指向文件的第一个字符else printf("文件路径错误!请重新输入:");}printf("\n******************* 词法分析结果如下 *******************\n");do{ch=fgetc(fp);if(ch=='#') break; //文件以#结尾,作为扫描结束条件else if(ch==' '||ch=='\t'||ch=='\n'){} //忽略空格,空白,和换行else{fseek(fp,-1,1); //回退一个字节开始识别单词流scanner(fp);}}while(ch!='#');return(0);}4.实验结果解析源文件:void main(){int a=3;a+=b;printf("%d",a);return;}#解析结果:5.实验总结分析通过本次实验,让再次浏览了有关c语言的一些基本知识,特别是对文件,字符串进行基本操作的方法。

编译原理实验报告——词法分析器(内含源代码)

编译原理实验(一)——词法分析器一.实验描述运行环境:vc++2008对某特定语言A ,构造其词法规则。

该语言的单词符号包括:12状态转换图3程序流程:词法分析作成一个子程序,由另一个主程序调用,每次调用返回一个单词对应的二元组,输出标识符表、常数表由主程序来完成。

二.实验目的通过动手实践,使学生对构造编译系统的基本理论、编译程序的基本结构有更为深入的理解和掌握;使学生掌握编译程序设计的基本方法和步骤;能够设计实现编译系统的重要环节。

同时增强编写和调试程序的能力。

三.实验任务编制程序实现要求的功能,并能完成对测试样例程序的分析。

四.实验原理char set[1000],str[500],strtaken[20];//set[]存储代码,strtaken[]存储当前字符char sign[50][10],constant[50][10];//存储标识符和常量定义了一个Analyzer类class Analyzer{public:Analyzer(); //构造函数 ~Analyzer(); //析构函数int IsLetter(char ch); //判断是否是字母,是则返回 1,否则返回 0。

int IsDigit(char ch); //判断是否为数字,是则返回 1,否则返回 0。

void GetChar(char *ch); //将下一个输入字符读到ch中。

void GetBC(char *ch); //检查ch中的字符是否为空白,若是,则调用GetChar直至ch进入一个非空白字符。

void Concat(char *strTaken, char *ch); //将ch中的字符连接到strToken之后。

int Reserve(char *strTaken); //对strTaken中的字符串查找保留字表,若是一个保留字返回它的数码,否则返回0。

void Retract(char *ch) ; //将搜索指针器回调一个字符位置,将ch置为空白字符。

词法分析器实验报告_4

实验一词法分析1.实验要求(1)从源程序文件中读取有效字符和并将其转换成二元组内部表示形式输出。

(2)掌握词法分析的实现方法。

(3)实验时间4学时。

(4)实验完成后,要上交实验报告(包括源程序清单)。

2.实验内容2.1主程序设计考虑:主程序的说明部分为各种表格和变量安排空间(关键字和特殊符号表)。

id 和ci 数组分别存放标识符和常数;还有一些为造表填表设置的变量。

主程序的工作部分建议设计成便于调试的循环结构。

每个循环处理一个单词;接收键盘上送来的一个单词;调用词法分析过程;输出每个单词的内部码(种别编码,属性值)。

2.2词法分析过程考虑该过程根据输入单词的第一个有效字符(有时还需读第二个字符),判断单词种别,产生种别编码。

对于标识符和常数,需分别与标识符表和常数表中已登记的元素相比较,如表中已有该元素,则记录其在表中的位置,如未出现过,将标识符按顺序填入数组id 中,将常数存入数组中ci 中,并记录其在表中的位置。

注:所有识别出的单词都用二元组表示。

第一个表示单词的种别编码。

例如:关键字的t=1;标识符的t=2;常数t=3;运算符t=4;界符t=5。

第二个为该单词在各自表中的指针或内部码值(常数表和标识符表是在编译过程中建立起来的。

其i 值是根据它们在源程序中出现的顺序确定的)。

将词法分析程序设计成独立一遍扫描源程序的结构。

其主流程图如下:图1 词法分析程序流程图程序源代码:#include<stdio.h>#include<stdlib.h>#include<string.h>char *keychar[14]={"int","char","float","void","const","if", "else","do","while","scanf","printf","return","main","read"};//关键字表,全局变量(种别编码为1)char *operatchar[18]={"+","-","*","/","%","=","==",">","<","!=",">=","<=","&&","||","!","<>","++","--"};//运算符表,全局变量(种别编码为2)char *boundschar[8]={"(",")","{","}",";",",","\"","'"};//保留字表,全局变量(种别编码为3)char *markchar[40];//标示符数组(种别编码为4)int markc=0;//记录已经记录的标示符的个数char *conster[40];//常数数组(种别编码为5)int markn=0;//记录已经记录的常数的个数char tempchar[40];//临时用来存放读入的字符int already=0;//全局变量,记录从文件中读出字符的个数char Read()//从文件中读出一个字符{FILE * fcode;char temp;if((fcode=fopen("code.txt","r"))==NULL){printf("无法打开此文件!\n");exit(0);}fseek(fcode,already*sizeof(char),0);//将文件位置移动到标记位置while(!feof(fcode)){already++;temp=fgetc(fcode);if(feof(fcode)){fclose(fcode);exit(0);}fclose(fcode);return temp;}}void ShowCode()//显示文件中的代码{printf("文件中的代码为:\n\n");FILE * fcode;if((fcode=fopen("code.txt","r"))==NULL){printf("无法打开此文件!\n");exit(0);}rewind(fcode);while(!feof(fcode)){putchar(fgetc(fcode));}putchar('\n');fclose(fcode);}void FirstLetter()//处理当程序的首字符为字母时的情况{void Judge();int i=1;char tempch;tempch=Read();while (((tempch>='A'&&tempch<='Z')||(tempch>='a'&&tempch<='z')) ||tempch>='0'&&tempch<='9'){tempchar[i]=tempch;tempch=Read();i++;}if (tempch!=' '){already--;//读出的文件的位置退1}printf("读出的字符为:%s\n",tempchar);int flag=0;for (int j=0;j<14;j++){if (!(strcmp(keychar[j],tempchar)))//若该字符串为关键字{printf("该字符为关键字,二元组为:");printf("<%s,->\n\n",tempchar);flag=1;break;}}if (flag==0)//若字符串为标示符{int flag1=0;char *p;for (int k=0;k<markc;k++)//查找标示符表,是否已存在该标示符{if (!(strcmp(markchar[k],tempchar))){p=markchar[k];flag1=1;break;}if (flag1==0){markchar[markc]=(char*)malloc(strlen(tempchar));strcpy(markchar[markc],tempchar);p=markchar[markc];markc++;}printf("该字符为标示符,二元组为:");printf("<2,%d>\n\n",p);}int l0=strlen(tempchar);for (int l=0;l<l0;l++)//将临时字符数组清零{tempchar[l]='\0';}Judge();}void FirstNum()//处理当程序的首字符为数字时的情况{void Judge();char *p;int i=1;char tempch;tempch=Read();while ((tempch>='0'&&tempch<='9')||tempch=='.'){tempchar[i]=tempch;tempch=Read();i++;}if (tempch!=' '){already--;//读出的文件的位置退1}int flag=0;printf("读出的字符为:%s\n",tempchar);for (int j=0;j<markn;j++){if (!strcmp(conster[j],tempchar)){p=conster[j];flag=1;break;}if (flag==0){conster[markn]=(char*)malloc(strlen(tempchar));strcpy(conster[markn],tempchar);p=conster[markn];markn++;}printf("该字符为常数,二元组为:");printf("<3,%d>\n\n",p);int l0=strlen(tempchar);for (int l=0;l<l0;l++)//将临时字符数组清零{tempchar[l]='\0';}Judge();}void FirstBound()//处理处理当程序的首字符为界符时的情况{void Judge();int i=0;printf("读出的字符为:%s\n",tempchar);printf("该字符为界符,二元组为:");printf("<%s,->\n\n",tempchar);if(tempchar[0]=='"'){do{i++;tempchar[i]=Read();} while (tempchar[i]!='"');if (tempchar[i-1]!='\\'){char*temp1=(char*)malloc(i*sizeof(char));int n=0;for (int j=0;j<i-1;++j){*(temp1+j)=tempchar[j+1];n++;}temp1[i-1]='\0';printf("读出的字符为:%s\n",temp1);conster[markn]=(char*)malloc((i-1)*sizeof(char));strcpy(conster[markn],temp1);char*p=conster[markn];markn++;printf("该字符为常量,二元组为:<3,%d>\n\n",p);free(temp1);}printf("读出的字符为:%c\n",tempchar[i]);printf("该字符为界符,二元组为:<%c,->\n\n",tempchar[i]);}for (int j=0;j<=i;j++){tempchar[j]='\0';}Judge();}void Firstoperat()//处理处理当程序的首字符为界符时的情况{void Judge();tempchar[1]=Read();int flag=0;for (int i=0;i<18;i++){if(!strcmp(tempchar,operatchar[i])){printf("读出的字符为:%s\n",operatchar[i]);printf("该字符为运算符,二元组为:<%s,->\n\n",operatchar[i]);tempchar[1]='\0';flag=1;break;}}if (flag==0){already--;tempchar[1]='\0';for (int i=0;i<18;i++){if (!strcmp(tempchar,operatchar[i])){printf("读出的字符为:%s\n",operatchar[i]);printf("该字符为运算符,二元组为:<%s,->\n\n",operatchar[i]);flag=2;break;}if (flag==0){printf("读出的字符为:%s\n",tempchar);printf("警告!该字符无法识别!\n\n");}}tempchar[0]='\0';Judge();}void Judge() //用来判断第一个读入的字符是数字,字母或者其他字符{do{tempchar[0]=Read();}while ((tempchar[0]==' ')||(tempchar[0]=='\n'));//判断字符类型,并作出处理if ((tempchar[0]>='A'&&tempchar[0]<='Z')||(tempchar[0]>='a'&&tempchar[0]<='z')){FirstLetter();}else if (tempchar[0]>='0'&&tempchar[0]<='9'){FirstNum();}elseif(tempchar[0]=='('||tempchar[0]==')'||tempchar[0]=='{'||tempchar[0]=='}'||tempchar[0]==';'||tempchar[0]==',' ||tempchar[0]=='"'||tempchar[0]=='\''){FirstBound();}else{Firstoperat();}}void main(){ShowCode();Judge();}实验心得:通过此次上机实验,是我掌握了词法分析器的实现过程,以前只是在课堂上学习词法分析器的理论,通过实践,也真正了解到了它的原理,为以后的语法分析打下基础,同时也熟悉了C语言,夯实了C语言的功底!。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

计算机科学与工程系
编译原理课程设计实验报告姓名:__ ******__ 学号_ *******__ 年级专业及班级___08计算机科学与技术成绩
扫描引号:
扫描单词:
扫描其他字符:
实验环境:需要TC、VC++ 6.0等开发工具作为本次试验的环境。

fprintf(fp1,"*********************************************************\n");
}
int guanjz(char ch1[])//关键字和标识符判断
{
char ch2[32][9]={"auto","double","int","struct","break","else","long","switch","case","enum", "register","typedef","char","extern","return","union","const","float","short",
"unsigned","continue","for","signed","void","default","goto","sizeof",
"volatile","do","while","static","if"};//定义关键字集
for(int i=0;i<32;i++)
{//逐个比对如果为关键字则返回类别i+1
if(!strcmp(ch1,ch2[i]))return i+1;
}
return 47;//否则返回一般标识符类
}。

相关文档
最新文档