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词法分析器实验报告篇一:词法分析器设计实验报告计算机与信息学院(信息工程系)编译原理实验报告专业班级课程教学班任课教实验指导教师实验地点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语言词法分析器实验报告汇总
计算机科学与工程系编译原理课程设计实验报告扫描数字: 是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语言词法分析器实验报告
计算机科学与工程系编译原理课程设计实验报告姓名:__ ******__ 学号_ *******__ 年级专业及班级___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. 词法规则设计:在开始实验之前,我们首先需要设计词法规则,即定义源代码中的合法词法单元。
例如,对于一门类C的语言,我们可以定义关键字(如if、while、int等)、标识符、运算符(如+、-、*等)、分隔符(如()、{}等)等。
2. 有限自动机(DFA)的设计:基于词法规则,我们可以设计一个有限自动机,用于识别和分析源代码中的词法单元。
有限自动机是一个状态转换图,其中每个状态代表一种词法单元,而边表示输入字符的转换关系。
3. 实现代码:根据有限自动机的设计,我们可以使用编程语言(如Python、C++等)实现词法分析器的代码。
代码的主要功能包括读取源代码文件、逐个字符进行词法分析、识别和输出词法单元。
实验过程:1. 词法规则设计:我们以一门简单的算术表达式语言为例,设计了以下词法规则:- 数字:由0-9组成的整数或浮点数。
- 运算符:包括+、-、*、/等。
- 分隔符:包括括号()和逗号,。
- 标识符:以字母开头,由字母和数字组成的字符串。
2. 有限自动机(DFA)的设计:我们基于词法规则,设计了一个简单的有限自动机。
该自动机包含以下状态:- 初始状态:用于读取和识别源代码中的字符。
- 数字状态:用于识别和输出数字。
- 运算符状态:用于识别和输出运算符。
- 分隔符状态:用于识别和输出分隔符。
- 标识符状态:用于识别和输出标识符。
3. 实现代码:我们使用Python编程语言实现了词法分析器的代码。
代码主要包括以下功能:- 读取源代码文件。
- 逐个字符进行词法分析,根据有限自动机的设计进行状态转换。
- 识别和输出词法单元。
实验结果:我们对几个测试样例进行了词法分析,并对结果进行了评估。
词法分析器实验报告_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、程序源代码:#include "fstream.h"#include "iostream.h"#include "string.h"#include "ctype.h"char ch ; // 存放当前的输入字符int lineno = 1; // 记录当前的行号void main()//主函数{void Reserve(ifstream&);ifstream fin("input.txt",ios::nocreate); //用ifstream的对象fin打开input文件,文件不存在时,不创建if (fin.fail()) cout << "找不到文件" << endl;Reserve(fin);fin.close();//fout.close();// ferr.close();}int judge(char *string) // 判断是否为关键字{char *keywords[1000]={"if","int","else","for","while","do","return","break","continue"};//关键字表,按相应类型号排序for(int i = 0;i <= 8;i++) //遍历keywords数组{if (!strcmp(string,*(keywords+i))){return 1; //是关键字,返回对应的类型值}}return 0; //不是关键字,返回0}void Reserve(ifstream &fin) //词法分析程序,用引用传递参数{char temp[100]; // 临时存放已读入但无法判断类型的字符int j = 0;int value_judge ;//存放函数judge的返回值while (fin.get(ch)){if (ch == '\n') {lineno += 1; }else if (ch == '\t'||ch == ' ') {} //排除制表、空格字符else if (isalpha(ch)) //当前输入符为字母{while (isalpha(ch)||isdigit(ch)){temp[j] = ch;j++;fin.get(ch);}temp[j] = '\0'; //标志字符串结束j = 0;if (value_judge = judge(temp)) // 判断是否为关键字{cout << "(1, "<< "\""<<temp<<"\")" << endl;}else cout << "(2, "<< "\""<<temp<<"\")" << endl;fin.seekg(-1,ios::cur); //回退1个字符}else if (isdigit(ch)){while (isdigit(ch)){temp[j] = ch;j++;fin.get(ch);}temp[j] = '\0'; //标志字符串结束j = 0;cout << "(3, "<< "\""<<temp<<"\")" << endl;fin.seekg(-1,ios::cur); //回退一个字符}//+、-、*、/、=、>、<、>=、<=、<>else if (ch == '+') cout << "(4, "<< "\"+\")" << endl;else if (ch == '-') cout << "(4, "<< "\"-\")" << endl;else if (ch == '*') cout << "(4, "<< "\"*\")" << endl;else if (ch == '/') cout << "(4, "<< "\"/\")" << endl;else if (ch == '=') cout << "(4, "<< "\"=\")" << endl;else if (ch == '>') cout << "(4, "<< "\">\")" << endl;else if (ch == '<') cout << "(4, "<< "\"<\")" << endl;else if (ch == '>=') cout << "(4, "<< "\">=\")" << endl;else if (ch == '<=') cout << "(4, "<< "\"<=\")" << endl;else if (ch == '<>') cout << "(4, "<< "\"<>\")" << endl;//,、;、{、}、(、)else if (ch == ',') cout << "(5, "<< "\",\")" << endl;else if (ch == ';') cout << "(5, "<< "\";\")" << endl;else if (ch == '(') cout << "(5, "<< "\"(\")" << endl;else if (ch == ')') cout << "(5, "<< "\")\")" << endl;else if (ch == '{') cout << "(5, "<< "\"{\")" << endl;else if (ch == '}') cout << "(5, "<< "\"}\")" << endl;ch = '\0';}}2、程序设计截图3、程序运行结果截图。
实验一、词法分析器(含源代码)
词法分析器实验报告一、实验目的及要求本次实验通过用C语言设计、编制、调试一个词法分析子程序,识别单词,实现一个C语言词法分析器,经过此过程可以加深对编译器解析单词流的过程的了解。
运行环境:硬件:windows xp软件:visual c++6.0二、实验步骤1.查询资料,了解词法分析器的工作过程与原理。
2.分析题目,整理出基本设计思路。
3.实践编码,将设计思想转换用c语言编码实现,编译运行。
4.测试功能,多次设置包含不同字符,关键字的待解析文件,仔细察看运行结果,检测该分析器的分析结果是否正确。
通过最终的测试发现问题,逐渐完善代码中设置的分析对象与关键字表,拓宽分析范围提高分析能力。
三、实验内容本实验中将c语言单词符号分成了四类:关键字key(特别的将main说明为主函数)、普通标示符、常数和界符。
将关键字初始化在一个字符型指针数组*key[]中,将界符分别由程序中的case列出。
在词法分析过程中,关键字表和case列出的界符的内容是固定不变的(由程序中的初始化确定),因此,从源文件字符串中识别出现的关键字,界符只能从其中选取。
标识符、常数是在分析过程中不断形成的。
对于一个具体源程序而言,在扫描字符串时识别出一个单词,若这个单词的类型是关键字、普通标示符、常数或界符中之一,那么就将此单词以文字说明的形式输出.每次调用词法分析程序,它均能自动继续扫描下去,形成下一个单词,直到整个源程序全部扫描完毕,从而形成相应的单词串。
输出形式例如:void $关键字流程图 、程序流程图:开始 输入源文件路径路径是否有效是初始化文件指针否将字符加入字符数组Word[]是空格,空白或换行吗是字母吗是数字吗否否是界符吗否打开源文件跳过该字符是是文件结束?否将字符加入字符数组Word[]否将字符加入字符数组Word[]是指向下一字符识别指针内容指向下一字符是字母惑数字吗是将word 与关键字表key 进行匹配否匹配?是输出word 为关键字输出word 为普通标示符否将字符加入字符数组Word[]指向下一字符输出word 为常数识别指针内容回退是数字吗是否输出word 为界符指向下一字符结束是输出Word 内容为不可识别将字符加入字符数组Word[]程序:#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语言的一些基本知识,特别是对文件,字符串进行基本操作的方法。
词法分析器实验报告
词法分析器实验报告一、实验目的本实验旨在通过构建一个简单的词法分析器来加深对编译原理中词法分析的理解,并掌握基本的词法分析算法和程序设计技巧。
二、实验环境操作系统:Windows 10编程语言:C/C++开发环境:Visual Studio 2019三、实验内容1. 设计并实现一个词法分析器,要求具备以下功能:(1)能够识别并区分关键字、标识符、字符常量、字符串常量、整型常量和浮点型常量等基本单词;(2)能够跳过注释、空格、制表符和换行符等无用字符;(3)能够给出错误提示并指明错误所在位置。
2. 对设计的词法分析器进行测试,并记录测试结果,分析测试结果的正确性和效率。
四、实验方法1. 分析待处理的源程序,并确定需要识别的词法单元;2. 设计状态转换图或状态转换表,并将其转化为程序代码;3. 开发测试程序,对所设计的词法分析器进行测试。
五、实验结果1. 实现的词法分析器程序可以正确识别出源程序中的各个单词,并能够跳过无用字符;2. 在测试过程中发现了一些错误,比如未能正确识别一些特殊情况下的单词,或者给出了错误的错误提示等。
经过修改后,程序可以正确识别这些情况,并给出正确的错误提示信息;3. 程序的效率较高,能够在短时间内对源程序进行词法分析。
六、实验体会通过本次实验,我对编译原理中词法分析的概念、算法和程序设计技巧有了更加深入的了解和掌握。
在实践中,我遇到了许多问题,比如如何设计状态转换图,如何正确识别一些特殊的单词等。
这些问题一一解决后,我对词法分析有了更加深刻的理解。
通过本次实验,我还深刻体会到了编译器设计过程中的思维方式和技术要求。
编译器是计算机科学中的一项重要技术,对于提高程序运行效率、保证程序安全性、增强程序可读性和扩展程序功能等都有重要作用。
因此,编译原理作为计算机科学的重要组成部分,对于我以后的学习和研究具有重要意义。
词法分析实验报告
词法分析实验报告Last revision on 21 December 2020编译原理实验一姓名:朱彦荣学号:专业:软件工程2实验题目:词法分析完成语言:C/C++上级系统:VC++日期:2015/11/7词法分析设计题目:手工设计c语言的词法分析器(可以是c语言的子集)设计内容:处理c语言源程序,过滤掉无用符号,判断源程序中单词的合法性,并分解出正确的单词,以二元组形式存放在文件中。
设计目的:了解高级语言单词的分类,了解状态图以及如何表示并识别单词规则,掌握状态图到识别程序的编程。
结果要求:课程设计报告。
完成日期:第十五周提交报告一.分析要想手工设计词法分析器,实现C语言子集的识别,就要明白什么是词法分析器,它的功能是什么。
词法分析是编译程序进行编译时第一个要进行的任务,主要是对源程序进行编译预处理(去除注释、无用的回车换行找到包含的文件等)之后,对整个源程序进行分解,分解成一个个单词,这些单词有且只有五类,分别是标识符、保留字、常数、运算符、界符。
以便为下面的语法分析和语义分析做准备。
可以说词法分析面向的对象是单个的字符,目的是把它们组成有效的单词(字符串);而语法的分析则是利用词法分析的结果作为输入来分析是否符合语法规则并且进行语法制导下的语义分析,最后产生四元组(中间代码),进行优化(可有可无)之后最终生成目标代码。
可见词法分析是所有后续工作的基础,如果这一步出错,比如明明是‘<=’却被拆分成‘<’和‘=’就会对下文造成不可挽回的影响。
因此,在进行词法分析的时候一定要定义好这五种符号的集合。
下面是我构造的一个C语言子集。
第一类:标识符 letter(letter | digit)* 无穷集第二类:常数 (digit)+ 无穷集第三类:保留字(32)auto break case char const continuedefault do double else enum externfloat for goto if int longregister return short signed sizeof staticstruct switch typedef union unsigned voidvolatile while第四类:界符‘/*’、‘.<while,32><+,33><-,34><*,35></,36><<,37><<=,38><>,39><>=,40><=,41><==,42><!=,43><;,44><(,45><),46><^,47><,,48><",49><',50><#,51><&,52><&&,53><|,54><||,55><%,56><~,57><<<,58>左移<>>,59>右移<[,60><],61><{,62><},63><\,64><.,65><,66><:,67><!,68>"[","]","{","}"<常数99 ,数值><标识符100 ,标识符指针>上述二元组中左边是单词的符号,右边为其种别码,其中常数和标识符有点特别,因为是无穷集合,因此常数用自身来表示,种别码为99,标识符用标识符符号表的指针表示(当然也可用自身显示,比较容易观察),种别码100。
构造词法分析器实习报告
班级:06级计算机1班学号:姓名:成绩:教学实习题目:构造词法分析器一、教学实习目的《编译原理》课程设计是计算机应用专业的主要实践性教学环节,在学习了《编译原理》及专业基础课的基础上,设计一个实际的程序语言编译系统,可以加深对程序语言结构和机器处理方式的理解,初步掌握高级语言到机器指令的基本转换方法,提高进行工程设计的基本技能及分析解决实际问题的能力,为毕业设计和以后的工程实践打下良好的基础。
二、教学实习要求根据课本p43页的图3.3构造词法分析器。
要求输入源数据文件,能够得出词法分析的结果,并显示出来,包括显示分离出来的单词符号、它们的助记符和内码值以及种类(如常数、字母、保留字及运算符、界符等)。
三、教学实习步骤3.1程序设计说明3.1.1需求分析词法分析是编译过程的第一个阶段,他的任务是输入源程序,对构成源程序的字符串进行扫描和分解,识别出一个个的单词符号,如基本字(begin、end、if、for、while等),标识符、常数、算符和界符(标点符号、左右括号等等)。
单词符号是语言的基本组成成分,是人们理解和编写程序的基本要素。
对于词法分析器,它的功能是输入源程序,输出单词符号。
程序语言的单词符号一般有以下几种:(1)保留字,是程序语言定义的具有固定意义的标识符。
(2)标识符,是用来表示各种名字,如变量名,数组名,过程名等等。
(3)常数,一般有整型,实型,布尔型,文字型等等。
(4)运算符,如+、—、*、/等等。
(5)界符,如逗号,分号,括号等等。
在词法分析器中要求输出的单词符号以二元式的形式给出:(单词种别,单词符号的属性值),单词种别常常用助记符来表示,单词符号的属性值则用内码来表示。
3.1.2详细设计首先给出词法分析器的结构图。
从图中可以看出:词法分析器工作的第一步是输入源程序文本。
输入串一般是放在一个缓冲区中,在很多情况下,把输入串处理一下,对单词符号的识别工作是比较方便的。
预处理可以剔除一些无意义的符号,如注释、多个空白符等等。
词法分析器报告
编译原理实验报告实验题目:词法分析器构造
指导教师:杨建
XX:杨先宇
班级:计13-4
学号:
实验成绩:
fclose(fp);
}
system("pause");
exit(0);
}
问题及处理1、源文件在输入时如果发生错误,系统会直接退出黑屏。
不能处理,加入预处理
后错误报警,这样就可以正确识别输入源程序文件。
2goto语句要特别注意加以分析。
3预处理文件可以直接调用节约时间,或者解决方法是建立一个菜单选项,可以跳过预处理直接进行词法分析
4程序执行时输出界面要保持准确性输入,以免手误导致程序出错。
实验结果运行程序,显示初始功能菜单:
选择功能1,输入源文件路径,对其进行词法分析:
按任意键继续是调用了系统功能函数system("pause");
按任意键之后:
实验心得词法分析在编译原理课上老师强调了许多,但是编译原理相对较难理解我在课上认真听了老师讲课,但是课下也看了书,觉得理解太难,通过实验认真查资料以及了。
词法分析器实验报告_5
一、实验目的1.1总体目的1.1.1 掌握词法分析的基本原理;1.1.2.理解词法分析在编译程序过程中的作用;1.1.3.熟悉关键字表等相关的数据结构与单词的分类方法.1.1.4.加深对编译原理的理解,掌握词法分析器的实现方法和技术,同时,将JA V A 的理论知识结合实际,锻炼编程技术,强调良好的程序设计风格。
1.2程序目的利用JAVA语言针对C语言编制一个一遍扫描的编译程序。
从文件中识别出各个单词, 识别出所取的单词的类型, 并且对代码中的词法错误进行提示。
二、实验内容根据编译原理中的词法分析原理, 利用Java语言针对C语言编写一个词法分析程序: 输入: 打开一个C语言程序的源代码文件, 将其读入程序输入框。
处理: 对输入框中的代码进行词法分析,分离出关键字、标识符、数值、运算符和界符。
输出:在词法分析结果表中输出每个单词所在行号、类型以及它所对应的编码。
其中, 编码是自定义的,一种类型对应一组编码。
词法分析结果显示在词法分析错误信息栏, 提示错误个数、错误所在行号, 并对某些词法错误原因进行说明。
三、实验需求针对C语言程序代码进行词法分析器, 从指定文件中读入预分析的源程序, 从左至右扫描源程序的字符串, 按照词法规则(正则文法规则)识别出一个个正确的单词, 并转换成该单词相应的二元式(种别码、属性值)以便之后进行语法分析使用。
同时, 按照给定的规则, 识别出单词符号作为输出, 发现其中的语法错误, 不同类别的字符通过相应的函数模块来分析识别, 使程序能够正确识别文法所规定的任何组织形式的字符组合, 将所有的分析状态显示在词法分析器中。
最后在错误分析栏中显示该文件中C语言代码的词法错误个数、错误所在行, 并对错误原因进行说明。
四、主要数据结构介绍4.1关键字编码4.2标识符统一编码1004.3数值统一编码2004.4界符编码4.5运算符编码4.6全局变量含义int row: 语法错误出现的所在列数int line: 语法错误出现的所在行数int err: 语法错误的个数int begin: 当前程序扫描在字符串中的开始位置int end: 当前程序扫描在字符串中的结束位置4.7局部变量定义int i: 选择第i 个字符进行检测 int state: 单词类型判断标志 int N: 文件长度char c: 当前遍历的字符 string str: 输入字符串 int flag: 退出标志五、主要模块算法介绍5.1总体流程介绍说明: state 为输入字符状态标志, 根据输入字符不同类型选择不同处理。
计算机编译原理---词法分析器实验报告
编译原理实验报告书词法分析器目录1、摘要: (2)2、实验目的: (2)3、任务概述 (3)4、实验依据的原理 (3)5、程序设计思想 (5)6、实验结果分析 (7)7、总结 (9)1、摘要:本实验用C/C++高级语言编写词法分析程序,通过课堂上对词法分析器相关的背景知识的足够了解,清晰词法分析的过程,在脑海中形成词法分析的一般方案,根据方案一步步所要实现的目的,形成对词法分析器程序的模块划分和整体规划,最终实现一个词法分析器。
具体要求能够通过扫描源程序分析出单词符号,将相应字符流转换成内码。
2、实验目的:通过设计、调试词法分析程序,实现从源程序中分出各种单词的方法;熟悉词法分析程序所用的工具自动机,进一步理解自动机理论。
掌握文法转换成自动机的技术及有穷自动机实现的方法。
确定词法分析器的输出形式及标识符与关键字的区分方法。
加深对课堂教学的理解;提高词法分析方法的时间能力。
通过本实验,掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的方法以及掌握词法分析的实现方法,并可以成功的上机调试编出词法分析程序。
3、任务概述用C/C++实现对Pascal的子集程序设计语言的词法识别程序。
词法分析程序的主要工作为:(1)从源程序文件中读入字符。
(2)统计行数和列数用于错误单词的定位。
(3)删除空格类字符,包括回车、制表符空格。
(4)按拼写单词,并用(内码,属性)二元式表示。
(5)根据需要是否填写标识符表供以后各阶段使用。
4、实验依据的原理(1)词法分析器工作流程图图1 词法分析器工作流程图实现流程:从左至右逐个字符地对源程序进行扫描,产生一个个的单词符号,把作为字符串的源程序改造成为单词符号串的中间程序。
词法分析的功能是输入源程序,输出单词符号。
所依据的理论基础有有限自动机、正规式、正规文法。
(2)词法分析器的功能是输入源程序,输出单词符号,单词符号是一个程序语言的基本语法符号,一般分为五种:关键字、标识符、常数、运算符、界符五大类。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 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!六、实验总结:这个程序主要参考书上关于词法分析器的设计。