词法分析的设计与实现

合集下载

词法分析程序实验报告

词法分析程序实验报告

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

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

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

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

中南大学编译原理实验报告

中南大学编译原理实验报告

中南大学编译原理实验报告班级:计科1205姓名:***学号:**********实验一词法分析程序设计与实现一、实验目的加深对词法分析器的工作过程的理解;加强对词法分析方法的掌握;能够采用一种编程语言实现简单的词法分析程序;能够使用自己编写的分析程序对简单的程序段进行词法分析。

二、实验内容自定义一种程序设计语言,或者选择已有的一种高级语言,编制它的词法分析程序。

词法分析程序的实现可以采用任何一种编程语言和编程工具。

从输入的源程序中,识别出各个具有独立意义的单词,即关键字、标识符、常数、运算符、界符。

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

(遇到错误时可显示“Error”,然后跳过错误部分继续显示)三、实验要求:1.对单词的构词规则有明确的定义;2.编写的分析程序能够正确识别源程序中的单词符号;3.识别出的单词以<种别码,值>的形式保存在符号表中,正确设计和维护符号表;4.对于源程序中的词法错误,能够做出简单的错误处理,给出简单的错误提示,保证顺利完成整个源程序的词法分析;四、实验步骤1.定义目标语言的可用符号表和构词规则;2.依次读入源程序符号,对源程序进行单词切分和识别,直到源程序结束;3.对正确的单词,按照它的种别以<种别码,值>的形式保存在符号表中;4.对不正确的单词,做出错误处理。

五、设计思路和实现过程本实验是词法分析器,我是用的是MFC实现的,我的设计思路就是按照书上提示的算法,先将几个词法分析器所需的基本函数用C++的形式实现,然后使用循环语句读入输入串的每一个字符,然后用if…else…语句实现,具体判断方式如下:1、如果读入的是字母,那么继续读入,知道读入的字符不是字母或者数字为止,对照标识符表,如果是标识符,则显示该串及对应标识符;如果不是,则显示该串和“$ID”;2、如果读入的是数字,则继续读入,知道不是数字为止,并显示该串和“$INT”;3、如果读入的是“=”,“+”,";",“(”,")","{","}",则分别输出该串和“$ASSIGN”,"$PLUS","$SEMICOLON","$LPAR","$RPAR","$LBRACE","$RBRACE";4、如果读入的是“*”,那么继续读入,如果下一个是“*”,则输出该串和"$POWER";否则输出该串和"$STAR",并将指针回退;5、如果独到输入串末尾,则退出。

编译原理实验报告

编译原理实验报告

编译原理实验报告一、实验目的本次编译原理实验的主要目的是通过实践加深对编译原理中词法分析、语法分析、语义分析和代码生成等关键环节的理解,并提高实际动手能力和问题解决能力。

二、实验环境本次实验使用的编程语言为 C/C++,开发工具为 Visual Studio 2019,操作系统为 Windows 10。

三、实验内容(一)词法分析器的设计与实现词法分析是编译过程的第一个阶段,其任务是从输入的源程序中识别出一个个具有独立意义的单词符号。

在本次实验中,我们使用有限自动机的理论来设计词法分析器。

首先,我们定义了单词的种类,包括关键字、标识符、常量、运算符和分隔符等。

然后,根据这些定义,构建了相应的状态转换图,并将其转换为程序代码。

在实现过程中,我们使用了字符扫描和状态转移的方法,逐步读取输入的字符,判断其所属的单词类型,并将其输出。

(二)语法分析器的设计与实现语法分析是编译过程的核心环节之一,其任务是在词法分析的基础上,根据给定的语法规则,判断输入的单词序列是否构成一个合法的句子。

在本次实验中,我们采用了自顶向下的递归下降分析法来实现语法分析器。

首先,我们根据给定的语法规则,编写了相应的递归函数。

每个函数对应一种语法结构,通过对输入单词的判断和递归调用,来确定语法的正确性。

在实现过程中,我们遇到了一些语法歧义的问题,通过仔细分析语法规则和调整函数的实现逻辑,最终解决了这些问题。

(三)语义分析与中间代码生成语义分析的任务是对语法分析所产生的语法树进行语义检查,并生成中间代码。

在本次实验中,我们使用了四元式作为中间代码的表示形式。

在语义分析过程中,我们检查了变量的定义和使用是否合法,类型是否匹配等问题。

同时,根据语法树的结构,生成相应的四元式中间代码。

(四)代码优化代码优化的目的是提高生成代码的质量和效率。

在本次实验中,我们实现了一些基本的代码优化算法,如常量折叠、公共子表达式消除等。

通过对中间代码进行分析和转换,减少了代码的冗余和计算量,提高了代码的执行效率。

词法分析器的实现与设计

词法分析器的实现与设计

题目:词法分析器的设计与实现一、引言................................ 错误!未定义书签。

二、词法分析器的设计 (3)2.1词的内部定义 (3)2.2词法分析器的任务及功能 (3)32.2.2 功能: (4)2.3单词符号对应的种别码: (4)三、词法分析器的实现 (5)3.1主程序示意图: (5)3.2函数定义说明 (6)3.3程序设计实现及功能说明 (6)错误!未定义书签。

77四、词法分析程序的C语言源代码: (7)五、结果分析: (12)摘要:词法分析是中文信息处理中的一项基础性工作。

词法分析结果的好坏将直接影响中文信息处理上层应用的效果。

通过权威的评测和实际应用表明,IRLAS是一个高精度、高质量的、高可靠性的词法分析系统。

众所周知,切分歧义和未登录词识别是中文分词中的两大难点。

理解词法分析在编译程序中的作用,加深对有穷自动机模型的理解,掌握词法分析程序的实现方法和技术,用c语言对一个简单语言的子集编制一个一遍扫描的编译程序,以加深对编译原理的理解,掌握编译程序的实现方法和技术。

Abstract:lexical analysis is a basic task in Chinese information processing. The results of lexical analysis will directly affect the effectiveness of the application of Chinese information processing. The evaluation and practical application show that IRLAS is a high precision, high quality and high reliability lexical analysis system. It is well known that segmentation ambiguity and unknown word recognition are the two major difficulties in Chinese word segmentation. The understanding of lexical analyse the program at compile, deepen of finite automata model for understanding, master lexical analysis program implementation method and technology, using C language subset of a simple language compilation of a scanned again compiler, to deepen to compile the principle solution, master compiler implementation method and technology.关键词:词法分析器?扫描器?单词符号?预处理Keywords: lexical analyzer word symbol pretreatment scanner一、引言运用C语言设计词法分析器,由指定文件读入预分析的源程序,经过词法分析器的分析,将结果写入指定文件。

北邮-编译原理-词法分析

北邮-编译原理-词法分析

实验报告编译原理与技术ytinrete程序设计1题目:词法分析程序的设计与实现。

实验内容:设计并实现C语言的词法分析程序,要求如下。

(1)、可以识别出用C语言编写的源程序中的每个单词符号,并以记号的形式输出每个单词符号。

(2)、可以识别并读取源程序中的注释。

(3)、可以统计源程序汇总的语句行数、单词个数和字符个数,其中标点和空格不计算为单词,并输出统计结果(4)、检查源程序中存在的错误,并可以报告错误所在的行列位置。

(5)、发现源程序中存在的错误后,进行适当的恢复,使词法分析可以继续进行,通过一次词法分析处理,可以检查并报告源程序中存在的所有错误。

|实验要求:方法1:采用C/C++作为实现语言,手工编写词法分析程序。

方法2:通过编写LEX源程序,利用LEX软件工具自动生成词法分析程序。

算法思路:首先通过遍历,统计行号和字符数,并记录所有的注释。

其次,再次读取,利用一个字符数组作为buffer保存一行的数据,在对其中的数据进行处理,完成之后再读下一行,跳过注释。

对于整行数据的处理,依靠空格将其分成单个单词再具体处理。

对于查错问题实在是一个难题,只能根据一些规则判定有错并记录。

&程序源代码:==*p || 'E'==*p || 'e'==*p)//小数和指数形式{(1,*p);p++;while(isdigit(*p)){(1,*p);p++;}}{sum_word++;(temp_word);cout<<endl<<"第"<<sum_word<<"个单词:"<<" 无符号数:" <<temp_word<<endl;}}elseif('#'==*p)//预处理文件特殊处理{while('\0'!=*p){(1,*p);》p++;}//p指向换行,完成直接退出(temp_word);}elseif('"'==*p)//字符串{();p++;while('"'!=*p)<{(1,*p);p++;}p++;sum_word++;cout<<endl<<"第"<<sum_word<<"个单词:"<<" 字符串:" <<temp_word<<endl;}elseif('+'==*p)//处理符号{。

词法分析器实验报告

词法分析器实验报告

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

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

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

编译原理词法分析,语法分析实验报告

编译原理词法分析,语法分析实验报告

编译原理实验报告一.LL(1)文法分析1.设计要求(1)对输入文法,它能判断是否为LL(1)文法,若是,则转(2);否则报错并终止;(2)输入已知文法,由程序自动生成它的LL(1)分析表;(3)对于给定的输入串,应能判断识别该串是否为给定文法的句型。

2.分析该程序可分为如下几步:(1)读入文法(2)判断正误(3)若无误,判断是否为LL(1)文法(4)若是,构造分析表;(5)由总控算法判断输入符号串是否为该文法的句型。

3.流程图开始读入文法有效?是是LL(1)文法?是判断句型报错结束4.源程序/*******************************************语法分析程序作者:xxx学号:xxx********************************************/#include<stdlib.h>#include<stdio.h>#include<string.h>/*******************************************/int count=0; /*分解的产生式的个数*/int number; /*所有终结符和非终结符的总数*/char start; /*开始符号*/char termin[50]; /*终结符号*/char non_ter[50]; /*非终结符号*/char v[50]; /*所有符号*/char left[50]; /*左部*/char right[50][50]; /*右部*/char first[50][50],follow[50][50]; /*各产生式右部的FIRST和左部的FOLLOW集合*/ char first1[50][50]; /*所有单个符号的FIRST集合*/char select[50][50]; /*各单个产生式的SELECT集合*/char f[50],F[50]; /*记录各符号的FIRST和FOLLOW是否已求过*/char empty[20]; /*记录可直接推出^的符号*/char TEMP[50]; /*求FOLLOW时存放某一符号串的FIRST集合*/int validity=1; /*表示输入文法是否有效*/int ll=1; /*表示输入文法是否为LL(1)文法*/int M[20][20]; /*分析表*/char choose; /*用户输入时使用*/char empt[20]; /*求_emp()时使用*/char fo[20]; /*求FOLLOW集合时使用*//*******************************************判断一个字符是否在指定字符串中********************************************/int in(char c,char *p){int i;if(strlen(p)==0)return(0);for(i=0;;i++){if(p[i]==c)return(1); /*若在,返回1*/if(i==strlen(p))return(0); /*若不在,返回0*/}}/*******************************************得到一个不是非终结符的符号********************************************/char c(){char c='A';while(in(c,non_ter)==1)c++;return(c);}/*******************************************分解含有左递归的产生式********************************************/void recur(char *point){ /*完整的产生式在point[]中*/int j,m=0,n=3,k;char temp[20],ch;ch=c(); /*得到一个非终结符*/k=strlen(non_ter);non_ter[k]=ch;non_ter[k+1]='\0';for(j=0;j<=strlen(point)-1;j++){if(point[n]==point[0]){ /*如果‘|’后的首符号和左部相同*/ for(j=n+1;j<=strlen(point)-1;j++){while(point[j]!='|'&&point[j]!='\0')temp[m++]=point[j++];left[count]=ch;memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';m=0;count++;if(point[j]=='|'){n=j+1;break;}}}else{ /*如果‘|’后的首符号和左部不同*/ left[count]=ch;right[count][0]='^';right[count][1]='\0';count++;for(j=n;j<=strlen(point)-1;j++){if(point[j]!='|')temp[m++]=point[j];else{left[count]=point[0];memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';printf(" count=%d ",count);m=0;count++;}}left[count]=point[0];memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';count++;m=0;}}}/*******************************************分解不含有左递归的产生式********************************************/void non_re(char *point){int m=0,j;char temp[20];for(j=3;j<=strlen(point)-1;j++){if(point[j]!='|')temp[m++]=point[j];else{left[count]=point[0];memcpy(right[count],temp,m);right[count][m]='\0';m=0;count++;}}left[count]=point[0];memcpy(right[count],temp,m);right[count][m]='\0';count++;m=0;}/*******************************************读入一个文法********************************************/ char grammer(char *t,char *n,char *left,char right[50][50]) {char vn[50],vt[50];char s;char p[50][50];int i,j,k;printf("\n请输入文法的非终结符号串:");scanf("%s",vn);getchar();i=strlen(vn);memcpy(n,vn,i);n[i]='\0';printf("请输入文法的终结符号串:");scanf("%s",vt);getchar();i=strlen(vt);memcpy(t,vt,i);t[i]='\0';printf("请输入文法的开始符号:");scanf("%c",&s);getchar();printf("请输入文法产生式的条数:");scanf("%d",&i);getchar();for(j=1;j<=i;j++){printf("请输入文法的第%d条(共%d条)产生式:",j,i);scanf("%s",p[j-1]);getchar();}for(j=0;j<=i-1;j++)if(p[j][1]!='-'||p[j][2]!='>'){ printf("\ninput error!");validity=0;return('\0');} /*检测输入错误*/for(k=0;k<=i-1;k++){ /*分解输入的各产生式*/if(p[k][3]==p[k][0])recur(p[k]);elsenon_re(p[k]);}return(s);}/*******************************************将单个符号或符号串并入另一符号串********************************************/void merge(char *d,char *s,int type){ /*d是目标符号串,s是源串,type=1,源串中的‘^ ’一并并入目串;type=2,源串中的‘^ ’不并入目串*/int i,j;for(i=0;i<=strlen(s)-1;i++){if(type==2&&s[i]=='^');else{for(j=0;;j++){if(j<strlen(d)&&s[i]==d[j])break;if(j==strlen(d)){d[j]=s[i];d[j+1]='\0';}}}}}/*******************************************求所有能直接推出^的符号********************************************/void emp(char c){ /*即求所有由‘^ ’推出的符号*/ char temp[10];int i;for(i=0;i<=count-1;i++){if(right[i][0]==c&&strlen(right[i])==1){temp[0]=left[i];temp[1]='\0';merge(empty,temp,1);emp(left[i]);}}}/*******************************************求某一符号能否推出‘^ ’********************************************/int _emp(char c){ /*若能推出,返回1;否则,返回0*/ int i,j,k,result=1,mark=0;char temp[20];temp[0]=c;temp[1]='\0';merge(empt,temp,1);if(in(c,empty)==1)return(1);for(i=0;;i++){if(i==count)return(0);if(left[i]==c) /*找一个左部为c的产生式*/{j=strlen(right[i]); /*j为右部的长度*/if(j==1&&in(right[i][0],empty)==1)else if(j==1&&in(right[i][0],termin)==1)return(0);else{for(k=0;k<=j-1;k++)if(in(right[i][k],empt)==1)mark=1;if(mark==1)continue;else{for(k=0;k<=j-1;k++){result*=_emp(right[i][k]);temp[0]=right[i][k];temp[1]='\0';merge(empt,temp,1);}}}if(result==0&&i<count)continue;else if(result==1&&i<count)return(1);}}}/*******************************************判断读入的文法是否正确********************************************/int judge(){int i,j;for(i=0;i<=count-1;i++){if(in(left[i],non_ter)==0){ /*若左部不在非终结符中,报错*/ printf("\nerror1!");validity=0;return(0);}for(j=0;j<=strlen(right[i])-1;j++){if(in(right[i][j],non_ter)==0&&in(right[i][j],termin)==0&&right[i][j]!='^'){ /*若右部某一符号不在非终结符、终结符中且不为‘^ ’,报错*/ printf("\nerror2!");validity=0;return(0);}}}return(1);}/*******************************************求单个符号的FIRST********************************************/void first2(int i){ /*i为符号在所有输入符号中的序号*/char c,temp[20];int j,k,m;c=v[i];char ch='^';emp(ch);if(in(c,termin)==1) /*若为终结符*/{first1[i][0]=c;first1[i][1]='\0';}else if(in(c,non_ter)==1) /*若为非终结符*/{for(j=0;j<=count-1;j++){if(left[j]==c){if(in(right[j][0],termin)==1||right[j][0]=='^'){temp[0]=right[j][0];temp[1]='\0';merge(first1[i],temp,1);}else if(in(right[j][0],non_ter)==1){if(right[j][0]==c)continue;for(k=0;;k++)if(v[k]==right[j][0])break;if(f[k]=='0'){first2(k);f[k]='1';}merge(first1[i],first1[k],2);for(k=0;k<=strlen(right[j])-1;k++){empt[0]='\0';if(_emp(right[j][k])==1&&k<strlen(right[j])-1){for(m=0;;m++)if(v[m]==right[j][k+1])break;if(f[m]=='0'){first2(m);f[m]='1';}merge(first1[i],first1[m],2);}else if(_emp(right[j][k])==1&&k==strlen(right[j])-1){temp[0]='^';temp[1]='\0';merge(first1[i],temp,1);}elsebreak;}}}}}f[i]='1';}/*******************************************求各产生式右部的FIRST********************************************/void FIRST(int i,char *p){int length;int j,k,m;char temp[20];length=strlen(p);if(length==1) /*如果右部为单个符号*/ {if(p[0]=='^'){if(i>=0){first[i][0]='^';first[i][1]='\0';}else{TEMP[0]='^';TEMP[1]='\0';}}else{for(j=0;;j++)if(v[j]==p[0])break;if(i>=0){memcpy(first[i],first1[j],strlen(first1[j]));first[i][strlen(first1[j])]='\0';}else{memcpy(TEMP,first1[j],strlen(first1[j]));TEMP[strlen(first1[j])]='\0';}}}else /*如果右部为符号串*/{for(j=0;;j++)if(v[j]==p[0])break;if(i>=0)merge(first[i],first1[j],2);elsemerge(TEMP,first1[j],2);for(k=0;k<=length-1;k++){empt[0]='\0';if(_emp(p[k])==1&&k<length-1){for(m=0;;m++)if(v[m]==right[i][k+1])break;if(i>=0)merge(first[i],first1[m],2);elsemerge(TEMP,first1[m],2);}else if(_emp(p[k])==1&&k==length-1){temp[0]='^';temp[1]='\0';if(i>=0)merge(first[i],temp,1);elsemerge(TEMP,temp,1);}else if(_emp(p[k])==0)break;}}}/*******************************************求各产生式左部的FOLLOW********************************************/ void FOLLOW(int i){int j,k,m,n,result=1;char c,temp[20];c=non_ter[i]; /*c为待求的非终结符*/ temp[0]=c;temp[1]='\0';merge(fo,temp,1);if(c==start){ /*若为开始符号*/temp[0]='#';temp[1]='\0';merge(follow[i],temp,1);}for(j=0;j<=count-1;j++){if(in(c,right[j])==1) /*找一个右部含有c的产生式*/{for(k=0;;k++)if(right[j][k]==c)break; /*k为c在该产生式右部的序号*/for(m=0;;m++)if(v[m]==left[j])break; /*m为产生式左部非终结符在所有符号中的序号*/ if(k==strlen(right[j])-1){ /*如果c在产生式右部的最后*/if(in(v[m],fo)==1){merge(follow[i],follow[m],1);continue;}if(F[m]=='0'){FOLLOW(m);F[m]='1';}merge(follow[i],follow[m],1);}else{ /*如果c不在产生式右部的最后*/for(n=k+1;n<=strlen(right[j])-1;n++){empt[0]='\0';result*=_emp(right[j][n]);}if(result==1){ /*如果右部c后面的符号串能推出^*/if(in(v[m],fo)==1){ /*避免循环递归*/merge(follow[i],follow[m],1);continue;}if(F[m]=='0'){FOLLOW(m);F[m]='1';}merge(follow[i],follow[m],1);}for(n=k+1;n<=strlen(right[j])-1;n++)temp[n-k-1]=right[j][n];temp[strlen(right[j])-k-1]='\0';FIRST(-1,temp);merge(follow[i],TEMP,2);}}}F[i]='1';}/*******************************************判断读入文法是否为一个LL(1)文法********************************************/int ll1(){int i,j,length,result=1;char temp[50];for(j=0;j<=49;j++){ /*初始化*/first[j][0]='\0';follow[j][0]='\0';first1[j][0]='\0';select[j][0]='\0';TEMP[j]='\0';temp[j]='\0';f[j]='0';F[j]='0';}for(j=0;j<=strlen(v)-1;j++)first2(j); /*求单个符号的FIRST集合*/ printf("\nfirst1:");for(j=0;j<=strlen(v)-1;j++)printf("%c:%s ",v[j],first1[j]);printf("\nempty:%s",empty);printf("\n:::\n_emp:");for(j=0;j<=strlen(v)-1;j++)printf("%d ",_emp(v[j]));for(i=0;i<=count-1;i++)FIRST(i,right[i]); /*求FIRST*/printf("\n");for(j=0;j<=strlen(non_ter)-1;j++){ /*求FOLLOW*/if(fo[j]==0){fo[0]='\0';FOLLOW(j);}}printf("\nfirst:");for(i=0;i<=count-1;i++)printf("%s ",first[i]);printf("\nfollow:");for(i=0;i<=strlen(non_ter)-1;i++)printf("%s ",follow[i]);for(i=0;i<=count-1;i++){ /*求每一产生式的SELECT集合*/ memcpy(select[i],first[i],strlen(first[i]));select[i][strlen(first[i])]='\0';for(j=0;j<=strlen(right[i])-1;j++)result*=_emp(right[i][j]);if(strlen(right[i])==1&&right[i][0]=='^')result=1;if(result==1){for(j=0;;j++)if(v[j]==left[i])break;merge(select[i],follow[j],1);}}printf("\nselect:");for(i=0;i<=count-1;i++)printf("%s ",select[i]);memcpy(temp,select[0],strlen(select[0]));temp[strlen(select[0])]='\0';for(i=1;i<=count-1;i++){ /*判断输入文法是否为LL(1)文法*/ length=strlen(temp);if(left[i]==left[i-1]){merge(temp,select[i],1);if(strlen(temp)<length+strlen(select[i]))return(0);}else{temp[0]='\0';memcpy(temp,select[i],strlen(select[i]));temp[strlen(select[i])]='\0';}}return(1);}/*******************************************构造分析表M********************************************/void MM(){int i,j,k,m;for(i=0;i<=19;i++)for(j=0;j<=19;j++)M[i][j]=-1;i=strlen(termin);termin[i]='#'; /*将#加入终结符数组*/termin[i+1]='\0';for(i=0;i<=count-1;i++){for(m=0;;m++)if(non_ter[m]==left[i])break; /*m为产生式左部非终结符的序号*/for(j=0;j<=strlen(select[i])-1;j++){if(in(select[i][j],termin)==1){for(k=0;;k++)if(termin[k]==select[i][j])break; /*k为产生式右部终结符的序号*/ M[m][k]=i;}}}}/*******************************************总控算法********************************************/void syntax(){int i,j,k,m,n,p,q;char ch;char S[50],str[50];printf("请输入该文法的句型:");scanf("%s",str);getchar();i=strlen(str);str[i]='#';str[i+1]='\0';S[0]='#';S[1]=start;S[2]='\0';j=0;ch=str[j];while(1){if(in(S[strlen(S)-1],termin)==1){if(S[strlen(S)-1]!=ch){printf("\n该符号串不是文法的句型!");return;}else if(S[strlen(S)-1]=='#'){printf("\n该符号串是文法的句型.");return;}else{S[strlen(S)-1]='\0';j++;ch=str[j];}}else{for(i=0;;i++)if(non_ter[i]==S[strlen(S)-1])break;for(k=0;;k++){if(termin[k]==ch)break;if(k==strlen(termin)){printf("\n词法错误!");return;}}if(M[i][k]==-1){printf("\n语法错误!");return;}else{m=M[i][k];if(right[m][0]=='^')S[strlen(S)-1]='\0';else{p=strlen(S)-1;q=p;for(n=strlen(right[m])-1;n>=0;n--)S[p++]=right[m][n];S[q+strlen(right[m])]='\0';}}}printf("\nS:%s str:",S);for(p=j;p<=strlen(str)-1;p++)printf("%c",str[p]);printf(" ");}}/*******************************************一个用户调用函数********************************************/void menu(){syntax();printf("\n是否继续?(y or n):");scanf("%c",&choose);getchar();while(choose=='y'){menu();}}/*******************************************主函数********************************************/void main(){int i,j;start=grammer(termin,non_ter,left,right); /*读入一个文法*/ printf("count=%d",count);printf("\nstart:%c",start);strcpy(v,non_ter);strcat(v,termin);printf("\nv:%s",v);printf("\nnon_ter:%s",non_ter);printf("\ntermin:%s",termin);printf("\nright:");for(i=0;i<=count-1;i++)printf("%s ",right[i]);printf("\nleft:");for(i=0;i<=count-1;i++)printf("%c ",left[i]);if(validity==1)validity=judge();printf("\nvalidity=%d",validity);if(validity==1){printf("\n文法有效");ll=ll1();printf("\nll=%d",ll);if(ll==0)printf("\n该文法不是一个LL1文法!");else{MM();printf("\n");for(i=0;i<=19;i++)for(j=0;j<=19;j++)if(M[i][j]>=0)printf("M[%d][%d]=%d ",i,j,M[i][j]);printf("\n");menu();}}}5.执行结果(1)输入一个文法(2)输入一个符号串(3)再次输入一个符号串,然后退出程序二.词法分析一、问题描述识别简单语言的单词符号识别简单语言的基本字、标识符、无符号整数、运算符和界符。

词法分析程序的设计与实现

词法分析程序的设计与实现

词法分析程序的设计与实现方法1:采用C作为实现语言,手工编制一.文法及状态转换图1.语言说明:C语言有以下记号及单词:(1)标识符:以字母开头的、后跟字母或数字组成的符号串。

(2)关键字:标识符集合的子集,该语言定义的关键字有32个,即auto,break,case,char,const,continue,default,do,double,else,enum, extern,float,for,goto,if,int,long,register,return,short,signed,static, sizeof,struct,switch,typedef ,union,unsigned ,void, volatile和while。

(3)无符号数:即常数。

(4)关系运算符:<,<=,==,>,>=,!=。

(5)逻辑运算符:&&、||、!。

(6)赋值号:=。

(7)标点符号:+、++、-、--、*、:、;、(、)、?、/、%、#、&、|、“”、,、.、{}、[]、_、^等(8)注释标记:以“/*”开始,以“*/”结束。

(9)单词符号间的分隔符:空格。

2.记号的正规文法:仅给出各种单词符号的文法产生式(1)标识符的文法id->letter ridrid->ε|letter rid|digit rid(2)无符号整数的文法digits->digit remainderremainder->ε|digit remainder(3)无符号数的文法num->digit num1num1->digit num1|. num2|E num4|εnum2->digit num3num3->digit num3|E num4|εnum4->+digits|-digits|digit num5digits->digit num5num5->digit num5|ε(4)关系运算符的文法relop-> <|<=|==|>|>=|!=(5)赋值号的文法assign_op->=(6)标点符号的文法special_symbol->+|-|*|%|#|^|(|)|{|}|[|]|:|;|”|?|/|,|.& (7)逻辑运算符的文法logic->&&| || | !(8)注释头符号的文法note->/starstar->*3.状态转换图其中,状态0是初始状态,若此时读入的符号是字母,则转换到状态1,进入标识符识别过程;如果读入的是数字,则转换到状态2,进入无符号数识别过程;……;若读入的符号是/,转换到状态11,再读入下一个符号,如果读入的符号是*,则转换到状态12,进入注释处理状态;如果在状态0读入的符号不是语言所定义的单词符号的开始字符,则转换到状态13,进入错误处理状态。

词法分析器的实验报告

词法分析器的实验报告

词法分析器的实验报告词法分析器的实验报告引言:词法分析器是编译原理中的重要组成部分,它负责将源代码中的字符序列转换为有意义的词法单元,为后续的语法分析提供基础。

本实验旨在设计和实现一个简单的词法分析器,并对其进行测试和评估。

实验设计:1. 词法规则设计:在开始实验之前,我们首先需要设计词法规则,即定义源代码中的合法词法单元。

例如,对于一门类C的语言,我们可以定义关键字(如if、while、int等)、标识符、运算符(如+、-、*等)、分隔符(如()、{}等)等。

2. 有限自动机(DFA)的设计:基于词法规则,我们可以设计一个有限自动机,用于识别和分析源代码中的词法单元。

有限自动机是一个状态转换图,其中每个状态代表一种词法单元,而边表示输入字符的转换关系。

3. 实现代码:根据有限自动机的设计,我们可以使用编程语言(如Python、C++等)实现词法分析器的代码。

代码的主要功能包括读取源代码文件、逐个字符进行词法分析、识别和输出词法单元。

实验过程:1. 词法规则设计:我们以一门简单的算术表达式语言为例,设计了以下词法规则:- 数字:由0-9组成的整数或浮点数。

- 运算符:包括+、-、*、/等。

- 分隔符:包括括号()和逗号,。

- 标识符:以字母开头,由字母和数字组成的字符串。

2. 有限自动机(DFA)的设计:我们基于词法规则,设计了一个简单的有限自动机。

该自动机包含以下状态:- 初始状态:用于读取和识别源代码中的字符。

- 数字状态:用于识别和输出数字。

- 运算符状态:用于识别和输出运算符。

- 分隔符状态:用于识别和输出分隔符。

- 标识符状态:用于识别和输出标识符。

3. 实现代码:我们使用Python编程语言实现了词法分析器的代码。

代码主要包括以下功能:- 读取源代码文件。

- 逐个字符进行词法分析,根据有限自动机的设计进行状态转换。

- 识别和输出词法单元。

实验结果:我们对几个测试样例进行了词法分析,并对结果进行了评估。

(完整word版)编译原理词法分析程序实现实验报告

(完整word版)编译原理词法分析程序实现实验报告

(完整word版)编译原理词法分析程序实现实验报告实验一词法分析程序实现一、实验内容选取无符号数的算术四则运算中的各类单词为识别对象,要求将其中的各个单词识别出来。

输入:由无符号数和+,-,*,/, ( , ) 构成的算术表达式,如1.5E+2-100。

输出:对识别出的每一单词均单行输出其类别码(无符号数的值暂不要求计算)。

二、设计部分因为需要选取无符号数的算术四则运算中的各类单词为识别对象,要求将其中的各个单词识别出来,而其中的关键则为无符号数的识别,它不仅包括了一般情况下的整数和小数,还有以E为底数的指数运算,其中关于词法分析的无符号数的识别过程流程图如下:GOTO 1:(完整word版)编译原理词法分析程序实现实验报告GOTO 2:三、源程序代码部分#include <stdio.h>#include<stdlib.h>#include <math.h>#define MAX 100#define UNSIGNEDNUMBER 1#define PLUS 2#define SUBTRACT 3#define MULTIPLY 4#define DIVIDE 5#define LEFTBRACKET 6#define RIGHTBRACKET 7#define INEFFICACIOUSLABEL 8#define FINISH 111int count=0;int Class;void StoreType();int Type[100];char Store[20]={'\0'};void ShowStrFile();//已经将要识别的字符串存在文件a中void Output(int a,char *p1,char *p2);//字符的输出过程int Sign(char *p);//'+''-''*''/'整体识别过程int UnsignedNum(char *p);//是否适合合法的正整数0~9int LegalCharacter(char *p);//是否是合法的字符:Sign(p)||UnsignedNum(p)||'E'||'.' void DistinguishSign(char *p);//'+''-''*''/'具体识别过程void TypyDistinguish();//字符的识别过程void ShowType();//将类别码存储在Type[100]中,为语法分析做准备void ShowStrFile()//已经将要识别的字符串存在文件a中{FILE *fp_s;char ch;if((fp_s=fopen("a.txt","r"))==NULL){printf("The FILE cannot open!");exit(0);}elsech=fgetc(fp_s);while(ch!=EOF){putchar(ch);ch=fgetc(fp_s);}printf("\n");}void StoreStr()//将文件中的字符串存储到数组Store[i] {FILE *fp=fopen("a.txt","r");char str;int i=0;while(!feof(fp)){fscanf(fp,"%c",&str);if(str=='?'){Store[i]='\0';break;}Store[i]=str;i++;}Store[i]='\0';}void ShowStore(){int i;for (i=0;Store[i]!='\0';i++)printf("%c",Store[i]);printf("\n");}void Output(int a,char *p1,char *p2){printf("%3s\t%d\t%s\t","CLASS",a,"VALUE");while(p1<=p2){printf("%c",*p1);p1++;}printf("\n");}int Sign(char *p){char ch=*p;if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch==')') return 1;elsereturn 0;}int UnsignedNum(char *p){char ch=*p;if('0'<=ch&&ch<='9')return 1;elsereturn 0;}int LegalCharacter(char *p){char ch=*p;if(Sign(p)||UnsignedNum(p)||ch=='E'||ch=='.')。

词法分析器的设计与实现

词法分析器的设计与实现

词法分析器的设计与实现
1.定义词法规则:根据编程语言的语法规范,定义不同的词法规则,
如关键字、标识符、操作符、常量等。

每个词法规则由一个正则表达式或
有限自动机来描述。

2.构建有限自动机:根据词法规则,构建一个有限自动机(DFA)来
识别词法单元。

有限自动机是一种形式化模型,用于在输入字符序列上进
行状态转换。

3.实现状态转换函数:根据有限自动机的定义,实现状态转换函数。

状态转换函数接受一个输入字符,并返回当前状态和输出的词法单元。

4.实现输入缓冲区:为了方便词法分析器的实现,通常需要实现一个
输入缓冲区,用于存储源代码,并提供一些读取字符的函数。

5. 实现词法分析器:将前面实现的状态转换函数和输入缓冲区结合
起来,实现一个完整的词法分析器。

词法分析器可以使用迭代器模式,每
次调用next(函数来获取下一个词法单元。

6.处理错误情况:在词法分析过程中,可能会遇到一些错误情况,如
未定义的词法单元、不符合语法规范的词法单元等。

词法分析器需要能够
检测并处理这些错误情况。

7.构建测试用例:为了验证词法分析器的正确性,需要构建测试用例,包括各种不同的源代码片段,并验证分析结果是否符合预期。

8.进行性能优化:词法分析是编译器中的一个耗时操作,因此可以进
行一些性能优化,如使用缓存机制、减少状态转换次数等。

以上是词法分析器的设计与实现的一般步骤,具体实现过程可能因编程语言和编译器的不同而有所差异。

词法分析器的实现与设计

词法分析器的实现与设计

词法分析器的实现与设计
1. 确定待分析的源代码的字符集和词法规则:首先,确定源代码所
使用的字符集,例如ASCII或Unicode。

然后,根据编程语言的语法规则,确定各种词法单元(如关键字、标识符、操作符、常量等)的识别规则。

2.设计识别词法单元的算法:根据词法规则,设计算法来识别每个词
法单元。

通常,这涉及到使用正则表达式或有限自动机(DFA)来进行模
式匹配。

3. 实现词法分析器:使用选定的编程语言实现词法分析器。

词法分
析器可以使用手写的代码实现,也可以使用工具(如Lex、Flex等)来自
动生成。

4.构建词法分析器的输入和输出接口:词法分析器通常需要从输入流
中读取源代码,并将识别出的词法单元输出到输出流中。

因此,需要设计
适当的输入和输出接口。

5.测试和调试词法分析器:编写测试用例,用不同类型的代码对词法
分析器进行测试,以确保它能正确地识别各种词法单元。

在测试过程中,
需要检查词法分析器的输出是否符合预期的结果。

6.集成到编译器中:将词法分析器集成到编译器的其他部分中,例如
语法分析器、语义分析器等。

这需要定义合适的接口,并确保各个部分之
间的协调工作。

总结起来,词法分析器的设计和实现包括选择字符集和词法规则、设
计识别算法、实现词法分析器、构建输入和输出接口、测试和调试以及集
成到编译器中。

这些步骤需要综合考虑编程语言的特点、词法规则的复杂
性和性能需求等因素。

实现词法分析实验报告

实现词法分析实验报告

实现词法分析实验报告一、实验目的本次实验的目的是通过编写代码实现一个简单的词法分析器,可以对一段输入的代码进行词法分析,识别出其中的各种标识符、关键字、常数和运算符等。

二、实验原理词法分析是编译过程中的第一个阶段,它负责将源代码按照规定的规则划分为一个个的单词(Token),每个单词代表一个最基本的语法单元。

在词法分析中,我们通过预先定义好的正则表达式规则来描述各个单词类型,并自动从源代码中提取出这些单词。

本次实验采用基于正则表达式的文法描述方式,针对不同的单词类型,使用不同的正则表达式来匹配。

通过遍历源代码字符串,逐一尝试匹配各个正则表达式,从而实现对单词的划分。

在匹配过程中,我们使用一个状态机来记录当前的匹配状态,以便处理不同的情况。

三、实验过程1. 定义Token的数据结构,包括单词类型和单词值两个字段。

使用枚举类型来表示所有的单词类型,如关键字、标识符、常数等。

2. 编写正则表达式的匹配函数,用于判断给定的字符串是否符合某个模式。

在这个函数中,使用系统提供的正则表达式库或者手动实现正则表达式匹配算法。

3. 设计一个状态机,用于记录当前匹配的状态。

状态机的状态包括开始、正在匹配、匹配成功和匹配失败等。

在状态机中,根据当前字符和当前状态进行不同的处理。

4. 在状态机中,当一个完整的Token被匹配出时,根据其类型和值创建一个Token对象,并将其添加到Token列表中。

5. 将源代码字符串按照换行符划分成多行,逐行进行处理。

对于每一行,调用状态机进行匹配,将得到的Token添加到Token列表中。

6. 输出Token列表,观察结果。

四、实验结果经过实验,我们成功实现了一个简单的词法分析器。

通过对输入的代码进行词法分析,我们可以得到每个单词的类型和值。

在本次实验中,我们测试了一段C语言代码,并成功提取出其中的关键字、标识符、常数和运算符等。

五、实验总结本次实验让我初步了解了词法分析的原理和过程。

词法分析设计实验报告(附代码)

词法分析设计实验报告(附代码)

实验一词法分析设计实验学时:4实验类型:综合实验要求:必修一、实验目的通过本实验的编程实践,使学生了解词法分析的任务,掌握词法分析程序设计的原理和构造方法,使学生对编译的基本概念、原理和方法有完整的和清楚的理解,并能正确地、熟练地运用。

二、实验内容用VC++/VB/JAVA语言实现对C语言子集的源程序进行词法分析。

通过输入源程序从左到右对字符串进行扫描和分解,依次输出各个单词的内部编码及单词符号自身值;若遇到错误则显示“Error”,然后跳过错误部分继续显示;同时进行标识符登记符号表的管理。

以下是实现词法分析设计的主要工作:(1)从源程序文件中读入字符。

(2)统计行数和列数用于错误单词的定位。

(3)删除空格类字符,包括回车、制表符空格。

(4)按拼写单词,并用(内码,属性)二元式表示。

(属性值——token的机内表示)(5)如果发现错误则报告出错(6)根据需要是否填写标识符表供以后各阶段使用。

单词的基本分类:◆关键字:由程序语言定义的具有固定意义的标识符。

也称为保留字例如if、 for、while、printf ;单词种别码为1。

◆标识符:用以表示各种名字,如变量名、数组名、函数名;◆常数:任何数值常数。

如 125, 1,0.5,3.1416;◆运算符:+、-、*、/;◆关系运算符: <、<=、= 、>、>=、<>;◆分界符:;、,、(、)、[、];三、实验要求1、编程时注意编程风格:空行的使用、注释的使用、缩进的使用等。

2、将标识符填写的相应符号表须提供给编译程序的以后各阶段使用。

3、根据测试数据进行测试。

测试实例应包括以下三个部分:◆全部合法的输入。

◆各种组合的非法输入。

◆由记号组成的句子。

4、词法分析程序设计要求输出形式:例:输入VC++语言的实例程序:If i=0 then n++;a﹤= 3b %);输出形式为:单词二元序列类型位置(行,列)(单词种别,单词属性)for (1,for ) 关键字(1,1)i ( 6,i ) 标识符(1,2)= ( 4,= ) 关系运算符(1,3)0 ( 5,0 ) 常数(1,4)then ( 1,then) 关键字(1,5)n (6,n ) 标识符(1,6)++ Error Error (1,7); ( 2, ; ) 分界符(1,8)a (6,a ) 标识符(2,1)﹤= (4,<= ) 关系运算符(2,2)3b Error Error (2,4)% Error Error (2,4)) ( 2, ) ) 分界符(2,5); ( 2, ; ) 分界符(2,6)实验报告正文:◆功能描述:该程序具有词法分析功能,即面对一段程序源代码,通过该程序,能检查出源代码是否由词法错误。

实验一 词法分析程序的设计与实现(C语言)

实验一 词法分析程序的设计与实现(C语言)

实验一 词法分析程序的设计与实现(C 语言)一、实验目的通过C 语言词法分析程序的实现理解编译程序过程中对单词的分析过程。

二、实验重难点DFA 自动机的数据结构表示,程序流程图,词法分析程序实现三、实验内容与要求实验内容:1. 设计存储DFA 自动机的数据结构2.绘制程序流程图3. 词法分析程序设计四、实验学时2课时五、实验设备与环境C 语言编译环境六、根据实验过程填写下列内容1.DFA 自动机的状态转换图和数据结构设计。

a /b2. 程序流程图(见附页)3. 代码#include<stdio.h>int f(int x,char e){ int df[4][2]={{2,3},{4,3},{2,4},{4,4}};U a a a S b Q bV bint i;if(e=='a')i=df[x][1];if(e=='b')i=df[x][2];return(i);}void main(){ int S=1,U=2,V=3,Q=4;int k=S;char c;printf("请输入字符,按#结束:\n");c=getchar();while(c!='#'){k=f(k,c);c=getchar();}if(k==Q) printf("你输入的字符串能被DFA所识别\n");else printf("你输入的字符串能被DFA所识别\n");}4.测试数据及结果分析(结果见附页)分析:从实验的结果可以看出上面程序代码基本上可以实现所给DFA的要求,但是有关实验的可读性和功能方面还有待进一步改进。

程序流程图教师评语:是否完成实验程序的预备设计? 是: 不是: 程序能否正常运行? 是: 不是: 有无测试数据及结果分析 是: 不是: 是否在本次规定时间完成所有项目? 是: 不是: 实验成绩等级: 教师签名:N0:时间:开始初始化输入句子判断是否退出标志判断是否被接受?接受不接受输出错误位置NY NY结束。

词法分析程序设计与实现

词法分析程序设计与实现

实验一词法分析程序设计与实现一、实验目的及内容调试并完成一个词法分析程序,加深对词法分析原理的理解。

二、实验原理(状态转换图)1、C语言子集(1)关键字:begin if then while do end所有关键字都是小写。

(2)运算符和界符::= + –* / < <= <> > >= = ; ( ) #(3)其他单词是标识符(ID)和整型常数(NUM),通过以下正规式定义:ID=letter(letter| digit)*NUM=digit digit *(4)空格由空白、制表符和换行符组成。

空格一般用来分隔ID、NUM,运算符、界符和关键字,词法分析阶段通常被忽略。

3、词法分析程序的功能输入:所给文法的源程序字符串。

输出:二元组(syn,token或sum)构成的序列。

其中:syn为单词种别码;token为存放的单词自身字符串;sum为整型常数。

二、软件平台及工具PC机以及VISUAL C++6.0软件。

三、实验方法、步骤(或:程序代码或操作过程)(1)程序代码:#include<stdio.h>#include<string.h>#include<iostream.h>char prog[80],token[8];char ch;int syn,p,m=0,n,row,sum=0;char *rwtab[6]={"begin","if","then","while","do","end"};void scaner(){for(n=0;n<8;n++) token[n]=NULL;ch=prog[p++];while(ch==' '){ch=prog[p];p++;}if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){m=0;while((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){token[m++]=ch;ch=prog[p++];}token[m++]='\0';p--;syn=10;for(n=0;n<6;n++)if(strcmp(token,rwtab[n])==0){syn=n+1;break;}}else if((ch>='0'&&ch<='9')){{sum=0;while((ch>='0'&&ch<='9')){sum=sum*10+ch-'0';ch=prog[p++];}}p--;syn=11;if(sum>32767)syn=-1;}else switch(ch){case'<':m=0;token[m++]=ch;ch=prog[p++];if(ch=='>'){syn=21;token[m++]=ch;}else if(ch=='='){syn=22;token[m++]=ch;}else{syn=23;p--;}break;case'>':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=24;token[m++]=ch;}else{syn=20;p--;}break;case':':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=18;token[m++]=ch;}else{syn=17;p--;}break;case'*':syn=13;token[0]=ch;break; case'/':syn=14;token[0]=ch;break; case'+':syn=15;token[0]=ch;break; case'-':syn=16;token[0]=ch;break; case'=':syn=25;token[0]=ch;break; case';':syn=26;token[0]=ch;break; case'(':syn=27;token[0]=ch;break; case')':syn=28;token[0]=ch;break; case'#':syn=0;token[0]=ch;break; case'\n':syn=-2;break;default: syn=-1;break;}}void main(){p=0;row=1;cout<<"Please input string:"<<endl;do{cin.get(ch);prog[p++]=ch;}while(ch!='#');p=0;do{scaner();switch(syn){case 11: cout<<"("<<syn<<","<<sum<<")"<<endl; break;case -1: cout<<"Error in row "<<row<<"!"<<endl; break;case -2: row=row++;break;default: cout<<"("<<syn<<","<<token<<")"<<endl;break;}}while (syn!=0);}(2)创建编辑程序(3)连接、编译和调试程序(4)运行程序五、实验过程原始记录( 测试数据、图表、计算等)(1)给定源程序begin x:=8; if x>0 then x:=2*x+1/5; end#输出结果(2)源程序(包括上式未有的while、do以及判断错误语句):beginx<=$; whilea<0dob<>9-x; end#。

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

题目词法分析的设计与实现学院专业名称计算机科学与技术姓名导师姓名2010年12 月目录1.课程设计的目的 (1)2.课程设计的内容 (1)3、课程设计的要求 (1)4.课程设计报告内容 (1)4.1设计功能分析 (1)4.2 设计思路 (1)4.3 正规文法 (2)4.4 状态图 (3)4.5设计词法分析算法代码 (5)4.6基本测试数据 (12)4.7结果截图 (12)5.设计体会 (12)6.参考文献 (13)7.思考题 (13)词法分析的设计与实现一、课程设计的目的1、基本掌握计算机语言的词法分析程序的开发方法。

2、实现一个词法分析程序,将字符串流分解成终结符流供语法分析使用。

3、通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。

并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。

4、了解当前常用的软件开发工具Visual C++,熟练掌握基于MFC的程序设计,培养解决实际问题的能力。

5、对C语言和数据结构的进一步巩固加深。

二课程设计的内容编制一个能够分析三种数、标识符、主要运算符、分隔符和主要关键字的词法分析程序。

三、课程设计的要求1.根据以下的正规式,编制正规文法,画出状态图;标识符 <字母>(<字母>|<数字字符>)*十进制数(0 | 1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)*(ε|.)(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)*八进制数0(1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7)*(ε|.)(0|1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7)*十六进制0x(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)* (ε|.)(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)* 运算符和分隔符 + - * / > < = ( ) ;关键字 if then else while do2.根据状态图,设计词法分析函数int scan( ),完成以下功能:1)从键盘读入数据,分析出一个单词。

2)返回单词种别(用整数表示),3)返回单词属性(不同的属性可以放在不同的全局变量中)。

3.编写测试程序,反复调用函数scan( ),输出单词种别和属性。

四、课程设计报告内容4.1、设计功能分析程序能够从左到右一个字符一个字符地读入源程序,并对构成的源程序的字符流进行扫描和分解,从而识别出一个个单词,并给出单词的种别和属性。

4.2、设计思路主函数main()的思想:先输入一串字符,将字符串用空格打断,若是分隔出的单元不为空,则对此单元继续分析,根据所输入的字符串判断出是标识符、八进制数、十进制数、十六进制数、运算符、分隔符还是关键字,然后赋予那单词的种别和属性。

4.3、正规文法对于十进制数:A1——>B1C1B1——>D1B1|εC1——>E1B1E1——> ε|.D1——>0|1|2|3|4|5|6|7|8|9对于八进制数:A2——>0B2B2——>C2D2C2——>E2F2E2——>1|2|3|4|5|6|7F2——>GF|εD2——>H2F2H2——> ε|.D2——>1|2|3|4|5|6|7G2——>0|1|2|3|4|5|6|7对于十六进制:A3——>0xB3B3——>C3D3C3——>E3C3|εE3——> 0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|fD3——>F3C3F3——> ε|.对于运算符和分隔符:A4——>+|-|*|/|>|<|=|(|)|;对于标识符和关键字:A5——>B5C5B5——>D5E5D5——>a|b|……|y|zE5——>F5E5|εF5——>a|b|……|y|z|0|1|2|3|4|5|6|7|8|9C5——>G5E5G5——> ε|.综上正规文法为:S——>A1|A2|A3|A4|A5A1——>B1C1B1——>D1B1|εC1——>E1B1E1——> ε|.D1——>0|1|2|3|4|5|6|7|8|9A2——>0B2B2——>C2D2C2——>E2F2E2——>1|2|3|4|5|6|7F2——>GF|εD2——>H2F2H2——> ε|.D2——>1|2|3|4|5|6|7G2——>0|1|2|3|4|5|6|7A3——>0xB3B3——>C3D3C3——>E3C3|εE3——> 0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f D3——>F3C3F3——> ε|.A4——>+|-|*|/|>|<|=|(|)|;A5——>B5C5B5——>D5E5D5——>a|b|……|y|zE5——>F5E5|εF5——>a|b|……|y|z|0|1|2|3|4|5|6|7|8|9 C5——>G5E5G5——> ε|.4.4、状态图0 (7)*0….9/a …z/A …Z1 (9)0 (9)其他开始空白a ….z / A …Z23 469其他。

0 (9)非数字。

0 (7)非o..7且非。

1100 (7)非o..7。

7581211131…9/a ….f / A …F 14非1….9且非a...f 且非A...F15 0….9/a...f/A...F 16非0….9且非a...f 且非A...F。

17。

1819+/-/ …/;If/while/then/dox/X4.4设计词法分析算法代码:#include<string.h>#include<stdio.h>#include "stdafx.h"union chars{ //联合,可存储字符串,整型和浮点型char pro_char[15];int pro_number;float real;};struct data{ //将每个单元用一个结构来存储,其内容包括:类型,所属的具体类型,以及属性值char kind[7];int id;union chars pro;};int scan(char *a); //对每个用空格打断的单元进行进一步的分析,对其进行进一步的分类void Prints(char a[15],int id,int a_long); //将分析后的每个token输出void save(char *a,int id,int x); //将分析后的结果保存到一个结构数组中char nowChar[15]; //临时的存储单元,用来存储被空格打断以后单元char kinds[11][8]={" ","INT10","INT8","INT16","IDN"," "," "," ","REAL10","REAL8","REAL16"};//单词的不同种别struct data link[100]; //用来存放词法分析以后的结果的结构数组int link_long=0; //全局变量int scan(char *a){int id;int a_long=0;int doc=0;while(*a!=NULL){nowChar[0]='\0';a_long=0;doc=0;//对数值的判断及处理if('0'<=*a&&*a<='9'){ //如果第一个字符为数值nowChar[a_long]=*a;*a++;a_long++;//对十六进制的判断及处理if(nowChar[0]=='0'&&(*a=='x'||*a=='X')){ //如果第一个字符为0且第二个字符为x,则为十六进制数nowChar[a_long]=*a;*a++;a_long++;while(*a!=NULL&&(('0'<=*a&&*a<='9')||('a'<=*a&&*a<='f')||('A'<=*a&&*a<='F')||*a=='.')){ nowChar[a_long]=*a; //一直将此十六进制数完全读入,若为浮点型的,则加以标记if(*a=='.')doc=1;*a++;a_long++;}nowChar[a_long]='\0'; //判断输入的十六进制数是否合法if(a_long==2){ //输入的只有0x,则输入错误Prints(nowChar,7,a_long);return 0;}if(doc) //输入的十六进制数是浮点型的Prints(nowChar,10,a_long); //则将其具体的类型属性定为10else //输入的十六进制数是整型的Prints(nowChar,3,a_long); //则将其具体的类型属性定义为3continue;}//对八进制的判断及处理if(nowChar[0]=='0'&&'0'<=*a&&*a<='7'){ //如果第一个字符为0且第二个字符为0~7,则为八进制数nowChar[a_long]=*a;*a++;a_long++;while(*a!=NULL&&(('0'<=*a&&*a<='7')||*a=='.')){nowChar[a_long]=*a; //一直将此八进制数完全读入,若为浮点型的,则加以标记if(*a=='.')doc=1;*a++;a_long++;}nowChar[a_long]='\0';if(doc) //输入的八进制数是浮点型的Prints(nowChar,9,a_long); //则将其具体的类型属性定为9else //输入的十六进制数是整型的Prints(nowChar,2,a_long); //则将其具体的类型属性定义为2continue;}//对十进制数的判断及处理else{while(*a!=NULL&&(('0'<=*a&&*a<='9')||*a=='.')){nowChar[a_long]=*a; //一直将此十进制数完全读入,若为浮点型的,则加以标记if(*a=='.')doc=1;*a++;a_long++;}nowChar[a_long]='\0';if(doc) //输入的十进制数是浮点型的Prints(nowChar,8,a_long); //则将其具体的类型属性定为8else //输入的十进制数是整型的Prints(nowChar,1,a_long); //则将其具体的类型属性定义为1continue;}} //完成了对数值的判断及处理//对字符的判断及处理else{nowChar[a_long]=*a;*a++;a_long++;//判断输入的字符是否为运算符或其他的分隔符switch(nowChar[0]){case'+':case'-':case'*':case'/':case'<':case'>':case'(':case')':case'=':case';':nowChar[a_long]='\0';Prints(nowChar,5,a_long); //将其具体的类型属性定义为5continue;default:break;}//判断输入的第一个字符是否为字母if(('a'<=nowChar[0]&&nowChar[0]<='z')||('A'<=nowChar[0]&&nowChar[0]<='Z')){while(*a!=NULL&&(('a'<=*a&&*a<='z')||('A'<=*a&&*a<='Z')||('0'<=*a&&*a<='9')||(*a=='.')||( *a=='_'))){ //一直将此字符串完全读入nowChar[a_long]=*a;*a++;a_long++;}nowChar[a_long]='\0';//判断输入的字符串是否为特殊的标识符,若是,则将其具体类型值定义为6//判断输入的字符串是否为特殊的字符串ifif(a_long==2&&strcmp(nowChar,"if")==0){Prints(nowChar,6,a_long);continue;}//判断输入的字符串是否为特殊的字符串thenif(a_long==4&&strcmp(nowChar,"then")==0){Prints(nowChar,6,a_long);continue;}//判断输入的字符串是否为特殊的字符串elseif(a_long==4&&strcmp(nowChar,"else")==0){Prints(nowChar,6,a_long);continue;}//判断输入的字符串是否为特殊的字符串whileif(a_long==5&&strcmp(nowChar,"while")==0){Prints(nowChar,6,a_long);continue;}//判断输入的字符串是否为特殊的字符串doif(a_long==2&&strcmp(nowChar,"do")==0){Prints(nowChar,6,a_long);continue;}//若输入的字符串不符合以上几种情况,则输入的为变量//若输入的字符串为变量,则将其具体属性值定义为4Prints(nowChar,4,a_long);continue;}//如果输入的既不是数值也不是字符串,则输入错误,将其具体类型之定义为7 else{Prints(nowChar,7,a_long);return 0;}}}return 1;}main(){char buf[100]; //用来存储从键盘上输入一串字符char *tokenPtr; //用来存储用空格打断后的单元int id=1; //用来存储具体的类型号link_long=0;while(id){link_long=0;gets(buf); //从键盘上输入一串字符tokenPtr=strtok(buf," "); //用空格将字符串打断while(id&&*tokenPtr!=NULL){ //分割出来的单元不为空id=scan(tokenPtr); //将此单元进行继续分析,并返回其具体的类型值tokenPtr=strtok(NULL," "); //将字符串继续用空格进行分割}}printf("\n\n");getchar();return 0;}//将所分解后的单元存入结构数组中void save(char *a,int id,int x,float y){int i;if(link_long<100){link[link_long].id=id; //将具体的类型值存入if(id>=5){if(id>=8){//id=8,9,10//若为浮点型的数值,则将浮点型的y值(转换后的)存入其属性当中且存入单词的种别for(i=0;i<9&&kinds[id][i]!='\0';i++)link[link_long].kind[i]=kinds[id][i];link[link_long].pro.real=y;}//id=5,6,7else{//若为标识符,则将单词种别定为自身,属性值定为空for(i=0;i<15&&a[i]!='\0';i++)link[link_long].kind[i]=a[i];link[link_long].pro.pro_char[0]='-';link[link_long].pro.pro_char[1]='\0';}link_long++;}//id=1,2,3,4else{for(i=0;i<8&&kinds[id][i]!='\0';i++)link[link_long].kind[i]=kinds[id][i]; //若分解后的token为变量或者整型数值,则将其单词种别直接输出if(id==4){ //若token为变量,则将其属性值设为自身for(i=0;i<15&&a[i]!='\0';i++)link[link_long].pro.pro_char[i]=a[i];link[link_long].pro.pro_char[i]='\0';}else //若token为整型数值,则将其相应的十进制数值赋给其属性值link[link_long].pro.pro_number=x;}link_long++; //继续存入下一个token}elseprintf("Full 100\n"); //结构数组已经存满return;}//将词法分析器分解后的结果输出出来void Prints(char a[15],int id,int a_long){int i;int x=0;float y=0;//int float1;//char *c;if(id==1){ //若为十进制整数for(i=1;i<a_long&&a[i]!='\0';i++)x=x*10+(a[i]-48);printf("INT10\t%s\n",a);save(a,id,x,y); //存入结构数组return;}if(id==2){ //若为八进制整数for(i=1;i<a_long&&a[i]!='\0';i++)x=x*8+(a[i]-48); //换算为十进制数printf("INT8\t%d\n",x);save(a,id,x,y); //存入结构数组return;}if(id==3){ //若为十六进制整数for(i=2;i<a_long&&a[i]!='\0';i++){if('0'<=a[i]&&a[i]<'9')x=x*16+(a[i]-48); //换算为十进制数else{if('a'<=a[i]&&a[i]<='f')x=x*16+(a[i]-87);elsex=x*16+(a[i]-55);}printf("INT16\t%d\n",x);save(a,id,x,y); //存入结构数组return;}if(id==4){ //若为变量printf("IDN\t%s\n",a);save(a,id,x,y); //存入结构数组return;}if(id==5||id==6){ //若为标识符(+,-,*,/,++以及if,else,while,then,do)printf("%s\t-\n",a);save(a,id,x,y); //存入结构数组return;}if(id==8){ //若为十进制浮点型for(i=0;i<a_long&&a[i]!='.';i++)x=x*10+(a[i]-48);for(i=strlen(a)-1;i>=0&&a[i]!='.';i--)y=(y+(a[i]-48))/10;y=y+x; //整数部分与小数部分换算后相加printf("REAL10\t%f\n",y);save(a,id,x,y); //存入结构数组return;}if(id==9){ //若为八进制浮点型for(i=1;i<a_long&&a[i]!='.';i++)x=x*8+(a[i]-48);for(i=strlen(a)-1;i>=0&&a[i]!='.';i--)y=(y+(a[i]-48))/8;y=y+x; //整数部分与小数部分换算后相加printf("REAL8\t%f\n",y);save(a,id,x,y); //存入结构数组return;}if(id==10){ //若为十六进制浮点型for(i=2;i<a_long&&a[i]!='.';i++) //将整数部分与小数部分分割开,并进行相应的换算x=x*16+(a[i]-48);for(i=strlen(a)-1;i>=0&&a[i]!='.';i--)y=(y+(a[i]-48))/16;y=y+x; //整数部分与小数部分换算后相加printf("REAL16\t%f\n",y); //存入结构数组save(a,id,x,y);return;printf("Wrong Enter"); //所得的具体类型值为7,则输入有错误return ;}4.5基本测试数据:输入数据例:00 96*name 25> 0x8d while 5;4.6结果截图:五、设计体会本次的课程设计使团队成员对词法分析的过程有了全新的了解,同时也明白了词法分析何时可以采用空格来区分单词,明白了程序设计中影响词法分析的效率的环节。

相关文档
最新文档