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;//否则返回一般标识符类}。

词法分析器实验报告

词法分析器实验报告

词法分析器实验报告⼀、实验⽬的通过设计⼀个词法分析程序,对词法进⾏分析,加强对词法的理解,掌握对程序设计语⾔的分解和理解。

⼆、实验内容和要求在原程序中输⼊源代码对字符串表⽰的源程序从左到右进⾏扫描和分解根据词法规则识别出⼀个⼀个具有独⽴意义的单词符号以供语法分析之⽤发现词法错误,则返回出错信息在源程序中,⾃动识别单词,把单词分为五种,并输出对应的单词种别码。

1. 识别关键字:main if int for while do return break continue,该类的单词码为1.2. 识别标识符:表⽰各种名字,如变量名、数组名、函数名等,如char ch, int syn, token,sum,该类的单词码为2.3. 运算符:+、-、*、/、=、>、<、>=、<=、!=4. 分隔符:,、;、{、}、(、)5. 常数,例:123各种单词符号对应的种别码。

输出形式:⼆元式– (单词种别,单词⾃⾝的值)单词种别,表明单词的种类,语法分析需要的重要信息– 整数码关键字、运算符、界符:⼀符⼀码标识符:10, 常数:11单词⾃⾝的值– 标识符token、常数sum– 关键字、运算符、界符token三、实验⽅法、步骤及结果测试1.源程序#include <stdio.h>#include <string.h>char string[80],simbol[8],ch;int wordID,index,m,n,sum;char *rwtab[6]={"begin","if","then","while","do","end"};void scaner(void);main(){int index=0;printf("请输⼊代码,并以串#号键结束:\n");do{scanf("%c",&ch);string[index++]=ch;}while(ch!='#');index=0;do{scaner();switch(wordID)case11:printf("( %-10d%5d )\n",sum,wordID);break;case -1:printf("错误\n");return0;break;default:printf("( %-10s%5d )\n",simbol,wordID);break;}}while(wordID!=0);return0;}void scaner(void){sum=0;for(m=0;m<8;m++)simbol[m++]= NULL;ch=string[index++];m=0;while((ch=='')||(ch=='\n'))ch=string[index++];if(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A')))//判断输⼊的字符是否为英⽂字母 {while(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))||((ch>='0')&&(ch<='9'))){simbol[m++]=ch;ch=string[index++];}index--;wordID=10;for(n=0;n<6;n++)if(strcmp(simbol,rwtab[n])==0){wordID=n+1;break;}}else if((ch>='0')&&(ch<='9'))//判断输⼊的字符是否为数字{while((ch>='0')&&(ch<='9')){sum=sum*10+ch-'0';ch=string[index++];}index--;wordID=11;}else{switch(ch)//通过循环判断输⼊的字符是否为运算符{case'<':simbol[m++]=ch;ch=string[index++];if(ch=='='){wordID=22;simbol[m++]=ch;}else{wordID=20;index--;}break;case'>':simbol[m++]=ch;ch=string[index++];if(ch=='='){wordID=24;simbol[m++]=ch;else{wordID=23;index--;}break;case'+':simbol[m++]=ch;ch=string[index++];if(ch=='+'){wordID=17;simbol[m++]=ch;}else{wordID=13;index--;}break;case'-':simbol[m++]=ch;ch=string[index++];if(ch=='-'){wordID=29;simbol[m++]=ch;}else{wordID=14;index--;}break;case'!':ch=string[index++];if(ch=='='){wordID=21;simbol[m++]=ch;}else{wordID=31;index--;}break;case'=':simbol[m++]=ch;ch=string[index++];if(ch=='='){wordID=25;simbol[m++]=ch;}else{wordID=18;index--;}break;case'*':wordID=15;simbol[m++]=ch;break;case'/':wordID=16;simbol[m++]=ch;break;case'('://判断输⼊的字符是否为分隔符 wordID=27;simbol[m++]=ch;break;case')':wordID=28;simbol[m++]=ch;break;case'{':wordID=5;simbol[m++]=ch;break;case'}':wordID=6;simbol[m++]=ch;break;case';':wordID=26;simbol[m++]=ch;break;case'\"':wordID=30;simbol[m++]=ch;break;case'#':wordID=0;simbol[m++]=ch;break;case':':wordID=17;simbol[m++]=ch;break;default:wordID=-1;break;}}simbol[m++]='\0'; }四.运⾏结果及分析。

词法分析器实验报告

词法分析器实验报告

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

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

二、实验目标本实验的目标是设计和实现一个能够对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语言的一些基本知识,特别是对文件,字符串进行基本操作的方法。

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

C语言词法分析器构造实验报告02计算机(2)2002374203 冯绍欣一、题目要求:完成一个C语言的词法分析器的构造。

此词法分析器能识别附值语句、循环语句、条件语句、并能处理注释。

二、设计方案:这个词法分析器分析的主要关键字有:main, int, float, char, if, else, for, while, do, switch, case, break; default。

选择要分析的c文件,首先对其去掉注释和与空格处理,再根据字符的不同类型分析。

1、全局数据结构:字符数组set[ ]:存放从文件中读到的所有字符;str[ ]:存放经过注释处理和预空格处理的字符;strtoken[ ]:存放当前分析的字符;结构体KEYTABLE:存放关键字及其标号;全局字符变量ch:当前读入字符;全局整型变量sr, to:数组str, strtoken 的指针。

2、以层次图形式描述模块的组成及调用关系3、主要函数的设计要求(功能、参数、返回值):openfile:打开文件;GetChar:将下一个输入字符读到ch中,搜索指示器前移一字符位置;GetBC:检查ch中的字符是否为空白。

若是,则调用GetChar直至ch中进入一个非空白字符;Concat:将ch中的字符连接到strtoken之后;IsLetter 和IsDigit:布尔函数过程,分别判断ch中的字符是否为字母和数字;Reserve:整型函数过程,对strtoken中的字符串查找关键字表,若是关键字则返回编码,否则返回-1;Retract:将搜索指示器回调一个字符位置,将ch置为空白字符;reflesh:刷新,把strtoken数组置为空;prearrange1:将注释部分置为空格;prearrange2:预处理空格,去掉多余空格;analysis:词法分析;main:主函数。

4、状态转换图:字符a包括:= , & , | , + , --字符b包括:-- , < , > , | , *字符c包括:, , : , ( , ) , { , } , [ , ] , ! ,# , % , ” , / , * , + , -- , > , <, .三、源代码如下:#include <stdio.h>#include <string.h>char set[1000],str[500],strtoken[20];char sign[50][10],constant[50][10];char ch;int sr,to,id=0,st=0;typedef struct keytable /*放置关键字*/{char name[20];int kind;}KEYTABLE;KEYTABLE keyword[]={ /*设置关键字*/{"main",0},{"int",1},{"float",2},{"char",3},{"if",4},{"else",5},{"for",6},{"while",7},{"do",8},{"switch",9},{"case",10},{"break",11},{"default",12},};openfile() /*打开文件*/{FILE *fp;char a,filename[10];int n=0;printf("Input the filename:");gets(filename);if((fp=fopen(filename,"r"))==NULL){printf("cannot open file.\n");exit(0);}elsewhile(!feof(fp)) /*文件不结束,则循环*/{a=getc(fp); /*getc函数带回一个字符,赋给a*/set[n]=a; /*文件的每一个字符都放入set[]数组中*/n++;}fclose(fp); /*关闭文件*/set[n-1]='\0';printf("\n\n-------------------Source Code--------------------------\n\n");puts(set);printf("\n--------------------------------------------------------\n");}reflesh() /*清空strtoken数组*/{to=0; /*全局变量to是strtoken的指示器*/strcpy(strtoken," ");}prearrange1() /*预处理程序1*/{int i,a,b,n=0;do{if(set[n]=='/' && set[n+1]=='*'){a=n; /*记录第一个注释符的位置*/while(!(set[n]=='*' && set[n+1]=='/'))n++;b=n+1; /*记录第二个注释符的位置*/for(i=a;i<=b;i++) /**/set[i]=' '; /*把注释的内容换成空格,等待第二步预处理*/ }n++;}while(set[n]!='\0');}prearrange2() /*预处理程序2*/{int j=0;sr=0; /*全局变量sr是str[]的指示器*/do{if(set[j]==' ' || set[j]=='\n'){while(set[j]==' ' || set[j]=='\n') /*扫描到有连续的空格或换行符*/j++;str[sr]=' '; /*用一个空格代替扫描到的连续空格和换行符放入str[]*/sr++;}else{str[sr]=set[j]; /*若当前字符不为空格或换行符就直接放入str[]*/sr++;j++;}}while(set[j]!='\0');str[sr]='\0';}char GetChar() /*把字符读入全局变量ch中,指示器sr前移*/{ch=str[sr];sr++;return(str[sr-1]);}void GetBC() /*开始读入符号,直至第一个不为空格*/{while(ch==' '){ch=GetChar();}}Concat() /*把ch中的字符放入strtoken[]*/{strtoken[to]=ch;to++; /*全局变量to是strtoken的指示器*/strtoken[to]='\0';}int IsLetter() /*判断是否为字母*/{if((ch>=65 && ch<=90)||(ch>=97 && ch<=122))return(1);else return(0);}int IsDigit() /*判断是否为数字*/{if(ch>=48 && ch<=57)return(1);else return(0);}int Reserve() /*对strtoken中的字符串查找保留字表,若是则返回它的编码,否则返回-1*/ {int i,k=0;for(i=0;i<=20;i++){if(strcmp(strtoken,keyword[i].name)==0){ k=1;return(keyword[i].kind);}}if(k!=1)return(-1);}void Retract() /*指示器sr回调一个字符位置,把ch置为空*/{sr--;}int InsertId(){int i,k;for(i=0;i<id;i++){k=strcmp(strtoken,sign[i]);if(k==0)return(i);}strcpy(sign[id],strtoken); /*插入标识符*/id++;return(id-1);}int InsertConst(){int i,k;for(i=0;i<st;i++){k=strcmp(strtoken,constant[i]);if(k==0)return(i);}strcpy(constant[st],strtoken); /*插入常数*/st++;return(st-1);}void analysis(){int value;reflesh(); /*清空strtoken数组*/prearrange1(); /*预处理,使注释内容换成单个空格,放回set[]中*/prearrange2(); /*预处理,使set[]中连续的空格置换成单个空格,并把set[]的内容放到str[]中*/GetChar();GetBC(); /*读取第一个字符*/while(ch!='\0') /*当不等于结束符,继续执行*/{if(IsLetter()){while(IsLetter() || IsDigit()) /*若第一个是字符,继续读取,直到出现空格*/{Concat();GetChar();}Retract(); /*指示器sr回调一个字符位置,把ch置为空*/value=Reserve(); /*对strtoken中的字符串查找保留字表,若是则返回它的编码,否则返回-1*/ if(value==-1) /*如果返回值是-1,那就是变量,把它输出*/{InsertId(); /*插入标识符*/printf("\n%s",strtoken);getch();}else /*否则就是关键字,也输出*/{printf("\n%s",strtoken);getch();}reflesh();}else if(IsDigit()){while(IsDigit()) /*否则,若第一个是数字,继续读取,知道出现空格*/{Concat();GetChar();}Retract();InsertConst(); /*插入常数*/printf("\n%s",strtoken);getch();reflesh();}elseswitch(ch) /*否则,若是下面的符号,就直接把它输出*/{case ',':case ';':case '(':case ')':case '{':case '}':case '[':case ']':case '!':case '#':case '%':case '"':case '/':case '*':Concat();printf("\n'%s'",strtoken);getch();reflesh();break;default:if(ch=='=' || ch=='&' || ch=='|' || ch=='+' || ch=='-') /*如果是这些符号,继续读取下一个*/ {Concat(); /*判断是否为==,&&,||,++,--的情况*/GetChar();if(ch==strtoken[0])Concat();elseRetract();printf("\n'%s'",strtoken);getch();reflesh();break;}else if(ch=='+' || ch=='-' || ch=='<' || ch=='>' || ch=='!' || ch=='*'){Concat(); /*判断是否为+=,-=,<=,>=,!=,*=的情况*/GetChar();if(ch=='=')Concat();elseRetract();printf("\n'%s'",strtoken);getch();reflesh();break;}else{printf("Error!");getch();break;}}GetChar();GetBC();}}main(){clrscr();openfile();analysis();printf(“analysis is over!”);}五、测试结果:1、分析文件test1.c中的程序:Input the filename:test.c*****************Original Code************************/* HELLO.C -- Hello, world */#include "stdio.h"#include "conio.h"main(){printf("Hello, world\n");getch();}*****************************************************'#'include'"'stdio'.'h'"''#'include'"'conio'.'h'"'main'('')''{'printf'(''"'Hello','worldError!n'"'')'';'getch'('')'';''}'Analysis is over!六、实验总结:这个程序主要参考书上关于词法分析器的设计。

相关文档
最新文档