浙江理工大学编译原理实验一
编译原理实验一
实验内容:实现标准C语言词法分析器实验目的:1.掌握程序设计语言词法分析的设计方法;2.掌握DFA的设计与使用方法;3.掌握正规式到有限自动机的构造方法;实验要求:1.单词种别编码要求基本字(关键字)、运算符、界符:一符一种;标识符(变量名):统一为一种;常量():按类型编码;2.词法分析工作过程中建立符号表、常量表,并以文本文件形式输出;3.词法分析的最后结果以文本文件形式输出;4.完成对所设计词法分析器的功能测试,并给出测试数据和实验结果;5.为增加程序可读性,请在程序中进行适当注释说明;6.整理上机步骤,总结经验和体会;7.认真完成并按时提交实验报告。
二、设计方案:这个词法分析器分析的主要关键字有:main, int, float, char, if, else, for, while, do, switch, case, break; default……。
选择要分析的c文件,首先对其去掉注释和与空格处理,再根据字符的不同类型分析。
1、全局数据结构:*key[ ]:关键字表全局文件指针*fr,*fw, *temp1,*temp2用于文件的读写。
2、以层次图模块的组成及调用关系3、主要函数的设计要求(功能、参数、返回值):isKey:判断ch中的字符是否为关键字;isLer 和isNum:布尔函数过程,分别判断ch中的字符是否为字母和数字;isBoudany():布尔函数过程,分别判断ch组成的字符否为边界符号;check:词法分析;clock:时间函数,计算程序运行所需的时间main:主函数。
4、状态转换图:字符a包括:= , & , | , + , --字符b包括:-- , < , > , | , *字符c包括:, , : , ( , ) , { , } , [ , ] , ! ,# , % , ” , / , * , + , -- , > , <, .# include<stdio.h># include <string.h># include <stdlib.h># include <time.h># include <ctype.h>FILE *fr,*fw,*temp1,*temp2;char *key0[]={"main","printf","scanf","else","if","auto","double", "int","struct","break","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"};/*关键字表*/char *key1[]={"\"","\\","(",")","[","]","{","}",",",";","'"};/*边界符表*/int isLet(char c)//判断是否是字母{if(c>='a'&& c<='z'||c>='A'&&c<='Z')return 1;elsereturn 0;}int isNum(char c)//判断是否是数字{if (c>='0'&&c<='9')return 1;elsereturn 0;}int isKey(char *word){int m,i;for(i=0;i<36;i++){if((m=strcmp(word,key0[i]))==0){if(i==0)return 2;elsereturn 1;}}return 0;}int isBoudany(char c){if(c=='\\')return 2;elseif(c=='('||c==')'||c=='{'||c=='}'||c=='['||c==']'||c==','||c==';'||c=='\''||c=='\"'||c=='\"') return 1;elsereturn 0;}void check(FILE *fr){char word[30];while(!feof(fr)){memset(word,0,sizeof(word));char ch,temp;ch=fgetc(fr); //获取字符,指针fr并自动指向下一个字符int i,c;if(ch=='#')//预处理{//temp=fgetc(fr);while(ch!='>')ch=fgetc(fr);ch=fgetc(fr);fprintf(fw,"*****************************************跳过头文件和文件宏定义\n");}elseif (ch=='/')//跳过注释/**/类型{ch=fgetc(fr);if (ch=='/')//跳过注释//类型{while(ch!='\n')ch=fgetc(fr);fprintf(fw,"*********************************************************跳过注释\n");}elseif (ch=='*'){ch=fgetc(fr);temp=fgetc(fr);do{ch=fgetc(fr);temp=fgetc(fr);}while (ch!='*'||temp!='/');fprintf(fw,"******************************************************跳过注释\n");ch=fgetc(fr);}}elseif(isLet(ch)){word[0]=ch;ch=fgetc(fr);i=1;while(isNum(ch)||isLet(ch))//判断该字符是否是字母或数字{word[i]=ch;i++;ch=fgetc(fr);}word[i]='\0'; //'\0' 代表字符结束(空格)fseek(fr,-1,1);c=isKey(word); //判断是否是关键字if(c==0) //不是关键字{fprintf(temp1,"%s ",word);fprintf(fw,"字符%s是:标识符,种别编码为:%d\n",word,2);}else{if(ch!='"')//判断是否是定义的字符{if(c==2)fprintf(fw,"字符%s是:***************************************************主函数,种别编码为:%d\n",word,0);//主函数elsefprintf(fw,"字符%s是:关键字,种别编码为:%d\n",word,1);//关键字}else{fprintf(fw,"字符%s是:定义的字符常量,种别编码为:%d\n\n",word,32);}}}else//开始判断的字符不是字母if(isNum(ch)){ //判断是否是数字word[0]=ch;ch=fgetc(fr);i=1;while(isNum(ch)){word[i]=ch;i++;ch=fgetc(fr);}word[i]='\0';fseek(fr,-1,1); //回退fprintf(fw,"字符%s是:常量,种别编码为:%d\n",word,3);}else{c=isBoudany(ch);//开始判断的字符不是字母也不是数字//边界符if(c){if(c==2)//判断是否是转义字符{word[0]=ch;ch=fgetc(fr);word[1]=ch;word[2]='\0';fprintf(fw,"字符%s是:转义字符,种别编码为:%d\n",word,4);}elseif(c==1){fprintf(fw,"字符%c是:界符,种别编码为:%d\n",ch,5);fprintf(temp2,"%c ",ch);}}elseswitch(ch){case'+':word[0]=ch;ch=fgetc(fr);word[1]=ch;if(ch=='='){word[2]='\0';fprintf(fw,"字符%s是:运算符,种别编码为:%d\n",word,6);//运算符"+="}elseif(ch=='+'){word[2]='\0';fprintf(fw,"字符%s是运算符,种别编码为:%d\n",word,7); //判断结果为"++"}else {fseek(fr,-2,1);ch=fgetc(fr);fprintf(fw,"字符%c是运算符,种别编码为:%d\n",ch,8); //判断结果为"+"}break;case'-':word[0]=ch;ch=fgetc(fr);word[1]=ch;if(ch=='='){word[2]='\0';fprintf(fw,"字符%s是:运算符,种别编码为:%d\n",word,9); }elseif(ch=='-'){word[2]='\0';fprintf(fw,"字符%s是运算符,种别编码为:%d\n",word,10); //判断结果为"--"}else {fseek(fr,-2,1);ch=fgetc(fr);fprintf(fw,"字符%c是运算符,种别编码为:%d\n",ch,11); //判断结果为"-"}break;case'*':word[0]=ch;ch=fgetc(fr);word[1]=ch;if(ch!='='){if(isNum(ch)){fseek(fr,-2,1);ch=fgetc(fr);fprintf(fw,"字符%c:是运算符,种别编码为:%d\n",ch,12);//判断结果为"*"}else{ //判断是否是指针i=2;ch=fgetc(fr);while(isLet(ch)){word[i]=ch;ch=fgetc(fr);i++;}fprintf(fw,"字符%s:是指针定义运算符,种别编码为:%d\n",word,13);}}else{word[2]='\0';fprintf(fw,"字符%s:是运算符,种别编码为:%d\n",word,14);//判断结果为"*="}break;case'/':word[0]=ch;ch=fgetc(fr);word[1]=ch;if(ch!='='){if(isNum(ch)){fseek(fr,-2,1);ch=fgetc(fr);fprintf(fw,"字符%c:是运算符,种别编码为:%d\n",ch,15);//判断结果为"/"}}else {word[2]='\0';fprintf(fw,"字符%s:是运算符,,种别编码为:%d\n",word,16);//判断结果为"/="}break;case'!':case'?':case':':case'.':case'=':word[0]=ch;ch=fgetc(fr);word[1]=ch;if(ch!='='){fseek(fr,-2,1);ch=fgetc(fr);fprintf(fw,"字符%c:是运算符,种别编码为:%d\n",ch,17);}else {word[2]='\0';fprintf(fw,"字符%s:是运算符,种别编码为:%d\n",word,18);break;case'|':word[0]=ch;ch=fgetc(fr);word[1]=ch;if(ch=='|'){word[2]='\0';fprintf(fw,"字符%c是运算符,种别编码为:%d\n",ch,19); //判断结果为运算符"||"}else {fseek(fr,-2,1);ch=fgetc(fr);fprintf(fw,"字符%c是运算符,种别编码为:%d\n",ch,20); //判断结果为"|"}break;case'%':word[0]=ch;ch=fgetc(fr);word[1]=ch;if(ch=='='){word[2]='\0';fprintf(fw,"字符%s是运算符,种别编码为:%d\n",word,21);}elseif(isLet(ch)){word[2]='\0';fprintf(fw,"字符%s是输出类型标识符,种别编码为:%d\n",word,22);}else{fseek(fr,-2,1);ch=fgetc(fr);fprintf(fw,"字符%c是取余运算符,种别编码为:%d\n",ch,23);}break;case'&':word[0]=ch;ch=fgetc(fr);word[1]=ch;if(ch=='&'){word[2]='\0';fprintf(fw,"字符%s是:运算符,种别编码为:%d\n",word,24); //判断结果为运算符"&&"}else {fseek(fr,-2,1);ch=getc(fr);fprintf(fw,"字符%c是:运算符,种别编码为:%d\n",ch,25); //判断结果为"&"}break;case'<':word[0]=ch;ch=fgetc(fr);word[1]=ch;if(ch=='='){word[2]='\0';fprintf(fw,"字符%s是:运算符,种别编码为:%d\n",word,26); //判断结果为运算符"<="}elseif(ch=='<'){word[2]='\0';fprintf(fw,"字符%s是:运算符,种别编码为:%d\n",word,27); //判断结果为运算符"<<"}else{fseek(fr,-2,1);ch=fgetc(fr);fprintf(fw,"字符%c是:运算符,种别编码为:%d\n",ch,28); //判断结果为"<"}break;case'>':word[0]=ch;ch=fgetc(fr);word[1]=ch;if(ch=='=') {word[2]='\0';fprintf(fw,"字符%s是运算符,种别编码为:%d\n",word,29);}elseif(ch=='>'){word[2]='\0';fprintf(fw,"字符%s是运算符,种别编码为:%d\n",word,30);}else {fseek(fr,-2,1);ch=fgetc(fr);fprintf(fw,"字符%c是运算符,种别编码为:%d\n",ch,31);}break;default: break;}}fprintf(fw,"\n");}}int main(){clock_t start,end;char cr;char str_in[25],str_out[25],str_out1[25],str_out2[25];double duration;start=clock();printf("请输入文件的读取路径(包含文件的后缀名):\n");scanf("%s",str_in);fr=fopen(str_in,"r");while(fr==NULL){printf("文件路径输入错误!请重新输入:\n");scanf("%s",str_in);fr=fopen(str_in,"r");}printf("文件读入成功!内容显示如下:\n");printf("**************************************************\n");cr=fgetc(fr);while (cr!=EOF) {putchar(cr);cr=fgetc(fr);}printf("\n");printf("**************************************************\n");printf("请输入文件的最终结果的写入路径(包含文件的后缀名):\n");scanf("%s",str_out);printf("请输入文件的常量表的写入路径(包含文件的后缀名):\n");scanf("%s",str_out1);printf("请输入文件的符号表的写入路径(包含文件的后缀名):\n");scanf("%s",str_out2);while(str_in==str_out||str_in==str_out1||str_in==str_out2){if(str_out==str_in){printf("请输入文件的最终结果的写入路径(包含文件的后缀名):\n");scanf("%s",str_out);}elseif(str_in==str_out1){printf("请输入文件的常量表的写入路径(包含文件的后缀名):\n");scanf("%s",str_out1);}elseif(str_in==str_out2){printf("请输入文件的符号表的写入路径(包含文件的后缀名):\n");scanf("%s",str_out2);}}fw=fopen(str_out,"w");temp1=fopen(str_out1,"w");temp2=fopen(str_out2,"w");while(fw==NULL||temp1==NULL||temp2==NULL){printf("文件写入路径错误,请重新输入:\n");if(fw==NULL){scanf("%s",str_out);fw=fopen(str_out,"w");}elseif(temp1=NULL){scanf("%s",str_out1);temp1=fopen(str_out1,"w");}elseif (temp2=NULL) {scanf("%s",str_out2);temp2=fopen(str_out2,"w");}}fprintf(temp1,"文件中依次出现的标识符\n");fprintf(temp2,"文件中依次出现的符号\n");fr=fopen(str_in,"r");check(fr);printf("文件写入成功!编译结果已写入指定文件区域!请注意查看...........\n\n");fclose(fw);fclose(temp1);fclose(temp2);fclose(fr);printf("\n");end=clock();duration=(double)(end-start)/CLOCKS_PER_SEC * 1000;printf("该词法分析程序共运行约%lf ms\n", duration);return 0;}测试结果:这个程序主要参考书上关于词法分析器的假设,完成了关于c语言词法分析的所有的功能。
编译原理实验报告
编译原理实验报告一、实验目的和要求本次实验旨在对PL_0语言进行功能扩充,添加新的语法特性,进一步提高编译器的功能和实用性。
具体要求如下:1.扩展PL_0语言的语法规则,添加新的语法特性;2.实现对新语法的词法分析和语法分析功能;3.对扩展语法规则进行语义分析,并生成中间代码;4.验证扩展功能的正确性。
二、实验内容1.扩展语法规则本次实验选择扩展PL_0语言的语句部分,添加新的控制语句,switch语句。
其语法规则如下:<switch_stmt> -> SWITCH <expression> CASE <case_list><default_stmt> ENDSWITCH<case_list> -> <case_stmt> , <case_stmt> <case_list><case_stmt> -> CASE <constant> : <statement><default_stmt> -> DEFAULT : <statement> ,ε2.词法分析和语法分析根据扩展的语法规则,需要对新的关键字和符号进行词法分析,识别出符号类型和记号类型。
然后进行语法分析,建立语法树。
3.语义分析在语义分析阶段,首先对switch语句的表达式进行求值,判断其类型是否为整型。
然后对case语句和default语句中的常量进行求值,判断是否与表达式的值相等。
最后将语句部分生成中间代码。
4.中间代码生成根据语法树和语义分析的结果,生成对应的中间代码。
例如,生成switch语句的跳转表,根据表达式的值选择相应的跳转目标。
5.验证功能的正确性设计一些测试用例,验证新语法的正确性和扩展功能的实用性。
三、实验步骤与结果1.扩展语法规则,更新PL_0语法分析器的词法规则和语法规则。
编译原理实验报告
编译原理实验报告一、实验目的编译原理是计算机科学中的重要学科,它涉及到将高级编程语言转换为计算机能够理解和执行的机器语言。
本次实验的目的是通过实际操作和编程实践,深入理解编译原理中的词法分析、语法分析、语义分析以及中间代码生成等关键环节,提高我们对编译过程的认识和编程能力。
二、实验环境本次实验使用的编程语言为C++,开发环境为Visual Studio 2019。
此外,还使用了一些相关的编译工具和调试工具,如 GDB 等。
三、实验内容(一)词法分析器的实现词法分析是编译过程的第一步,其任务是将输入的源程序分解为一个个单词符号。
在本次实验中,我们使用有限自动机的理论来设计和实现词法分析器。
首先,定义了各种单词符号的类别,如标识符、关键字、常量、运算符等。
然后,根据这些类别设计了相应的状态转换图,并将其转换为代码实现。
在实现过程中,使用了正则表达式来匹配输入字符串中的单词符号。
对于标识符和常量等需要进一步处理的单词符号,使用了相应的规则进行解析和转换。
(二)语法分析器的实现语法分析是编译过程的核心环节之一,其任务是根据给定的语法规则,分析输入的单词符号序列是否符合语法结构。
在本次实验中,我们使用了递归下降的语法分析方法。
首先,根据实验要求定义了语法规则,并将其转换为相应的递归函数。
在递归函数中,通过对输入单词符号的判断和处理,逐步分析语法结构。
为了处理语法错误,在分析过程中添加了错误检测和处理机制。
当遇到不符合语法规则的输入时,能够输出相应的错误信息,并尝试进行恢复。
(三)语义分析及中间代码生成语义分析的目的是对语法分析得到的语法树进行语义检查和语义处理,生成中间代码。
在本次实验中,我们使用了三地址码作为中间代码的表示形式。
在语义分析过程中,对变量的定义和使用、表达式的计算、控制流语句等进行了语义检查和处理。
对于符合语义规则的语法结构,生成相应的三地址码指令。
四、实验步骤(一)词法分析器的实现步骤1、定义单词符号的类别和对应的正则表达式。
编译原理-实验1
实验1《词法分析程序设计与实现》实验学时: 2 实验地点:实验日期:一、实验目的加深对词法分析器的工作过程的理解;加强对词法分析方法的掌握;能够采用一种编程语言实现简单的词法分析程序;能够使用自己编写的分析程序对简单的程序段进行词法分析。
二、实验内容自定义一种程序设计语言,或者选择已有的一种高级语言,编制它的词法分析程序。
词法分析程序的实现可以采用任何一种编程语言和编程工具。
从输入的源程序中,识别出各个具有独立意义的单词,即关键字、标识符、常数、运算符、界符。
并依次输出各个单词的内部编码及单词符号自身值。
(遇到错误时可显示“Error”,然后跳过错误部分继续显示)三、实验方法算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
主程序初始包括以下两个方面:⑴关键字表的初值。
关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。
如能查到匹配的单词,则该单词为关键字,否则为一般标识符。
关键字表为一个字符串数组,其描述如下:Char *rwtab[6] = {“begin”, “if”, “then”, “while”, “do”, “end”,};图3-1(2)程序中需要用到的主要变量为syn,token和sum扫描子程序的算法思想:首先设置3个变量:①token用来存放构成单词符号的字符串;②sum用来整型单词;③syn用来存放单词符号的种别码。
四、实验步骤1.定义目标语言的可用符号表和构词规则;2.依次读入源程序符号,对源程序进行单词切分和识别,直到源程序结束;3.对正确的单词,按照它的种别以<种别码,值>的形式保存在符号表中;4.对不正确的单词,做出错误处理。
五、实验结果输入begin x:=9: if x>9 then x:=2*x+1/3; end #显示结果如下:六、实验结论该词法分析器可以进行输入、预处理;关键字的识别;标识符的识别、常数的识别、算符和界符的识别等。
编译原理实验报告(手打)
《编译原理》实验报告班级:计C104姓名:李云霄学号:108490实验一词法分析程序实现一、实验目的与要求通过编写和调试一个词法分析程序,掌握在对程序设计语言的源程序进行扫描的过程中,将字符形式的源程序流转化为一个由各类单词符号组成的流的词法分析方法。
二、实验内容选取无符号数的算术四则运算中的各类单词为识别对象,要求将其中的各个单词识别出来。
输入:由无符号数和+,-,*,/, ( , ) 构成的算术表达式,如1.5E+2-100。
输出:对识别出的每一单词均单行输出其类别码(无符号数的值暂不要求计算)。
三、实现方法与环境1、首先设计识别各类单词的状态转换图。
描述无符号常数的确定、最小化状态转换图如图1所示。
其中编号0,1,2,…,6代表非终结符号<无符号数>、<余留无符号数>、<十进小数>、<小数部分>、<指数部分>、<整指数>及<余留整指数>, 1,2和6为终态,分别代表整数、小数和科学计数的识别结束状态。
图1 文法G[<无符号数>]的状态转换图其中编号0,1,2,…,6代表非终结符号<无符号数>、<余留无符号数>、<十进小数>、<小数部分>、<指数部分>、<整指数>及<余留整指数>, 1,2和6为终态,分别代表整数、小数和科学计数的识别结束状态。
在一个程序设计语言中,一般都含有若干类单词符号,为此可首先为每类单词建立一张状态转换图,然后将这些状态转换图合并成一张统一的状态图,即得到了一个有限自动机,再进行必要的确定化和状态数最小化处理,最后据此构造词法分析程序。
四则运算算术符号的识别很简单,直接在状态图的0状态分别引出相应标记的矢根据描述语言中各类单词的文法状态转换图或状态矩阵,利用某种语言(C语言或JAVA语言)直接编写词法分析程序。
编译原理实验一
编译原理实验一
编译原理实验一是一个非常重要的实验环节,它涉及到一些基本的编译原理知识和实践技能。
在这个实验中,我们将学习如何设计并实现一个简单的词法分析器。
在编译原理实验一中,我们将首先学习词法分析的基本概念和原理。
词法分析是编译器的第一阶段,它的主要任务是将输入的源代码分解成一个个的词法单元,如标识符、关键字、数字、运算符等。
为了完成这个任务,我们需要设计一个适用于特定编程语言的词法分析器。
接下来,我们将学习如何使用正则表达式来描述词法单元的模式。
通过定义正确的正则表达式,我们可以准确地识别出源代码中的各种词法单元。
为了实现这一功能,我们将使用一个常用的正则表达式引擎,如lex工具。
在实验过程中,我们将根据给定的编程语言规范,编写相应的正则表达式规则,并通过lex工具生成对应的词法分析器程序。
然后,我们将使用这个词法分析器程序来对一些示例源代码进行分析,确保它能正确地识别出各种词法单元。
最后,我们将对实验结果进行总结和分析。
通过实验一,我们将更深入地了解词法分析的原理和实现方法,为以后更复杂的编译原理实验和项目打下坚实的基础。
希望大家能够认真对待这个实验,积极探索和学习,并尽可能多地掌握相关知识和技能。
编译原理实验报告
编译原理实验报告实验⼀词法分析器的设计与实现 (1)1)实验⽬的 (1)2)实验内容 (1)3)实验要求 (1)4)实验原理 (1)5)实验步骤 (1)6)状态转化图及词法分析程序 (2)7)测试 (7)实验⼆语法分析器的设计与实现 (9)1)实验⽬的 (9)2)实验内容 (9)3)实验要求 (9)4)实验原理 (9)5)实验步骤 (9)6)语法分析程序 (10)7)测试 (16)编译原理实验报告专业:计算机科学与技术学⽣姓名:学号: 48完成时间:2020年11⽉25⽇实验⼀词法分析器的设计与实现1)实验⽬的①掌握正规式、状态转换图、C语⾔单词符号的划分及词法分析器的实现②掌握词法分析程序的作⽤和接⼝。
2)实验内容设计及实现C语⾔程序的词法分析器。
3)实验要求①对任给的⼀个C语⾔源程序,能够虑掉空格、回车换⾏符、tab键及注释。
②识别各类单词符号,如关键字、标识符、运算符、常数、界符,结果以⼆元式形式输出。
并构造符号表。
③输出有词法错误的单词及所在⾏号。
4)实验原理根据扫描到的单词符号的第⼀个字符的种类,分别转到相应的程序进⾏处理。
这些程序的功能就是识别以相应字符开头的各类单词符号。
5)实验步骤①根据C语⾔各类单词的正规式,构造能识别各类单词的状态转换图。
②根据状态转换图,构造识别各类单词的词法分析器。
6)状态转化图及词法分析程序#include ""#include ""#include ""FILE *fp;int id;void main(){char cbuffer;char alphaprocess(char buffer);char digitprocess(char buffer);char otherprocess(char buffer);if ((fp=fopen("","r"))==NULL) /*以只读⽅式打开⽂件"",NULL在⽂件中已被定义为0*/ printf("error");else{cbuffer=fgetc(fp); /*⽂件不为空则从⽂件中取字符*/while (cbuffer!=EOF) /*EOF⽂件结束标志*/{if(cbuffer==' '||cbuffer=='\n') /*掠过空格和回车符*/{cbuffer=fgetc(fp);id=4;}else if(isalpha(cbuffer))cbuffer=alphaprocess(cbuffer); /*检查cbuffer是否为字母,是则调⽤alphaprocess()函数*/ else if (isdigit(cbuffer))cbuffer=digitprocess(cbuffer); /*检查cbuffer是否为数字0~9,是则调⽤digitprocess()函数*/ else cbuffer=otherprocess(cbuffer); /*⾮上述两者则调⽤otherprocess()函数*/}}char alphaprocess(char buffer){int search(char searchchar[],int wordtype); /*函数声明*/int atype;int i=-1;char alphatp[20]; /*字符数组存储从⽂件中读取的字符*/while((isalpha(buffer))||(isdigit(buffer))||buffer=='_') /*标识符的组成成分*/{alphatp[++i]=buffer; /*将当前读取的字符存如数组*/buffer=fgetc(fp); /*读取下⼀个字符*/}alphatp[i+1]='\0'; /*字符串以'\0'作为结束标志*/atype=search(alphatp,1); /*调⽤函数,判断当前字符串是否为关键字*/if(atype!=0) /*是关键字则输出该关键字,编号为1,并输出该关键字在关键字表中的位⼦*/{printf("(%s, (1,%d))\n",alphatp,atype);id=1; /*关键字的ID为1*/}else{printf("(%s ,2)\n",alphatp); /*为标识符时,编号为2*/id=2; /*标识符的ID为2*/}return(buffer);}/*判断字符串是否为关键字*/int search(char searchchar[],int wordtype){char * key[32]={"auto","break","case","char","const","continue","default","do", "double","else","enum","extern","float","for","goto","if","int","long", "register","return","short","signed","sizeof","static","struct", "volatile","while","switch","typedef","union","unsigned","void"};/*设置数组指针存储c语⾔中的32个关键字*/int i;int p;switch (wordtype)case 1:for (i=0;i<=31;i++){if (strcmp(key[i],searchchar)==0) /*⽐较字符串,为关键字则定位该关键字的序号*/{ p=i+1; break; }else p=0;}return(p);}}char digitprocess(char buffer){int i=-1;char digittp[20];while ((isdigit(buffer))||buffer=='.'||buffer=='e'||buffer=='E')//考虑数字为⼩数和指数时的情况{digittp[++i]=buffer;buffer=fgetc(fp); /*同上*/}digittp[i+1]='\0';printf("(%s ,3)\n",digittp); /*输出该数字,编号为3*/ id=3; /*设置ID为3*/return(buffer);}char otherprocess(char buffer){int n=0;char ch[20];ch[0]=buffer;ch[1]='\0';if(ch[0]=='%'||ch[0]=='\\'){ buffer=fgetc(fp);ch[1]=buffer;ch[2]='\0';printf("(%s ,5)\n",ch);id=4;return(buffer);}if(ch[0]=='&'){buffer=fgetc(fp);if(buffer!='&')printf("(%s ,5)\n",ch);id=4;return(buffer);}if(buffer=='&'){ch[1]=buffer;ch[2]='\0';printf("(%s ,4)\n",ch);id=3;buffer=fgetc(fp);return(buffer);}}if(ch[0]==','||ch[0]==';'||ch[0]=='{'||ch[0]=='}'||ch[0]=='('||ch[0]==')') { printf("(%s ,5)\n",ch);buffer=fgetc(fp);id=4;return(buffer);}if(ch[0]=='*'||ch[0]=='/')printf("(%s ,4)\n",ch);buffer=fgetc(fp);id=4;return(buffer);}if(ch[0]=='='||ch[0]=='!'||ch[0]=='<'||ch[0]=='>'){if(buffer=='=') /*防⽌'==','!=','<=','>='符号的分离*/ {ch[1]=buffer;ch[2]='\0';printf("(%s ,4)\n",ch);}else{printf("(%s ,4)\n",ch);id=4;return(buffer);}buffer=fgetc(fp);id=4;return(buffer);if(ch[0]=='+'||ch[0]=='-'){if(id==4) /*如果'+','-'前ID为4的字符则可能为正负数或'++','--',否则为加减号*/ {for(int i=1;i<10;i++){buffer=fgetc(fp);if(buffer=='+'){ch[1]='+';ch[2]='\0';id=4;printf("(%s ,4)\n",ch);buffer=fgetc(fp);id=4;return(buffer);}if(buffer=='-'){ch[1]='-';ch[2]='\0';id=4;printf("(%s ,4)\n",ch);buffer=fgetc(fp);id=4;return(buffer);}if((buffer==',')||(buffer==';')||(buffer=='+')||(buffer=='-')||(buffer==')')) break; /*防⽌将+562;+562,+562+,+562-,+561)作为整体输出*/ ch[i]=buffer;ch[i+1]='\0';}printf("(%s ,3)\n",ch);id=3;//buffer=fgetc(fp);return(buffer);}ch[2]='\0';}printf("(%s ,wrong word!)\n",ch);buffer=fgetc(fp);id=4;return(buffer);}7)测试实验⼆语法分析器的设计与实现1)实验⽬的掌握⾃上⽽下语法分析⽅法、⾃下⽽上语法分析⽅法分析思路。
编译原理实验教程课程设计
编译原理实验教程课程设计背景编译原理是计算机科学专业的一门重要课程,它研究如何将高级语言翻译成低级语言,以便计算机执行。
编译器是实现这一过程的关键工具。
然而,对于很多学生来说,编译原理的理论知识学习起来比较抽象,难以掌握。
因此,本文旨在为编译原理的学习提供一些实验教程的设计思路。
实验一:词法分析器词法分析器是编译器的第一个模块,它的作用是将输入的字符流转化为一个个单词符号。
本实验的目的是设计并实现一个简单的词法分析器,实现以下功能:1.识别输入的程序中所包含的各个单词符号。
2.输出所有单词符号及其对应的单词类型。
3.当遇到不合法单词符号时,给出相应的错误提示。
具体实现可以采用有限自动机的思想,使用正则表达式或者手写代码,实现对于不同的单词类型的识别,并对于不合法单词进行识别和报错处理。
实验二:语法分析器语法分析器是编译器的第二个模块,它的作用是将词法分析器输出的单词序列转换成语法树或者语法分析表,以便后续进行语义分析和目标代码生成。
本实验的目的是设计并实现一个简单的语法分析器,实现以下功能:1.识别输入的程序是否符合所设计的文法规则。
2.输出语法树或语法分析表。
具体实现可以采用自上而下的递归下降分析法或自下而上的移进-规约分析法,实现对于不同的句型的识别,并生成语法树或语法分析表。
实验三:语义分析器语义分析器是编译器的第三个模块,它的作用是对语法分析器输出的语法树或语法分析表进行语义分析,并生成中间代码。
本实验的目的是设计并实现一个简单的语义分析器,实现以下功能:1.对语法树或语法分析表进行遍历,识别语法错误和语义错误,给出相应的错误提示。
2.生成中间代码。
具体实现可以采用语义规则和符号表的检查方式,识别语法错误和语义错误,并在生成中间代码时,根据中间代码语言的规则进行实现。
实验四:目标代码生成器目标代码生成器是编译器的第四个模块,它的作用是将中间代码转换成机器语言,以便计算机执行。
本实验的目的是设计并实现一个简单的目标代码生成器,实现以下功能:1.将中间代码转换成机器语言。
编译原理实验报告语义分析
编译原理实验报告语义分析实验名称:语义分析实验目的:1.掌握词法分析器生成的词法单元序列的构造;2.学会设计语法分析器,实现对程序的基本语法结构检查,并生成抽象语法树;3.学习语义规约的实现,实现对程序的语义分析和错误检查;4.熟悉语义分析向语法分析的接口。
实验原理:语义分析是编译过程的一个重要环节,它的主要任务是对生成的抽象语法树进行遍历,并验证程序的类型一致性、语义规则的正确性、错误的检查和恢复等。
语义分析的输入是由语法分析生成的抽象语法树,输出是继续优化的抽象语法树或中间代码,以供后续的中间代码生成等工作使用。
实验步骤:1.设计语法分析器,包括语法规则、优先级关系等;2.生成词法单元序列;3.构建语法分析器,进行语法分析,并生成抽象语法树;4.针对不同的语义规约,设计语义动作,实现对程序的语义分析和错误检查;5.完成语义分析器的构建和测试。
实验设备:1.计算机;2. 编程语言:C++/Java/Python等;3. 开发环境:Visual Studio/ Eclipse/PyCharm等。
实验结果:通过对语法分析生成的抽象语法树进行遍历,实现了对程序的语义分析和错误检查。
具体实现包括:1.类型检查:根据语义规约,对程序中的类型进行检查,包括变量的声明及使用、函数的调用、赋值语句的一致性等;2.作用域检查:检查变量的作用域和可见性等;3.错误检查:检测语义错误,如变量未声明、函数重复定义等;4.错误恢复:当检测到错误时,采取适当的错误恢复措施,如跳过错误的部分继续分析、提示错误信息等。
实验心得:本次实验主要学习了语义分析的原理和实现方法,深入了解了编译过程中各个环节的作用和关系。
通过实践操作,加深了对语法分析和语义分析的理解,提高了编程能力和解决问题的能力。
同时,实验过程中也遇到了一些挑战和困难,例如语义规约的设计和实现、错误检查和恢复等,但通过查阅资料和与同学讨论,最终解决了这些问题。
通过本次实验,我对编译原理和语义分析有了更深入的了解,并且对以后的学习和工作有了更好的准备。
编译原理实验一1
实验2:语法分析程序班级:计算机1103 姓名:王静 学号:1101308336一、 实验目的与实验1.复习上下文无关文法的基本结构、判断方法;2.理解文法存在左递归、回溯现象的害处及消除方法,掌握FIRST 集、FOLLOW 集的含义、求解方法与用途,掌握LL (1)文法的判断方法及构造技术;3.掌握预测分析法的理论精髓,理解下推自动机的基本概念及运行原理;4.学会基于上下文无关文法构造LL (1)预测表,并使用Visual C++编写LL(1)分析器;5.能利用预测分析法,在给定的文法基础上,分析特定输入串的语法结构, 能判断其是否合法,并能提取大部分中间信息,以备后续分析时使用。
二、 实验仪器与设备1. 微型电子计算机(PC 机)。
2. 配置Windows 2000及以上版本操作系统。
3. 安装Visual C++6.0或Visual C#2003或Delphi6.0等以上版本的 开发环境。
三、实验内容与步骤1.实验内容已知文法G[E]:E →E+T|E-T|TT →T*F|T/F|FF →(E)|I编写该文法的LL(1)语法分析程序,用以识别下面的符号串: #((i+i)*i-i)/i#1 2 0 0 1-90-9 其它 无符号整数 4 5 3 6 7 9 1其他 ( ) + - * #8/2.实验步骤(一)准备工作回答下面问题,并将分析过程与结果写在实验报告册上。
上述文法G[E]存在左递归吗?若存在,首先消除左递归,得到对应的文法G ’[E];构造文法G ’[E]的预测分析表(需要先求FIRST 、FOLLOW 集),并根据定义, 逐步判断该文法是否为LL(1)文法;基于上述分析表,仿照教材,写出符号串#((i+i)*i-i)/i#的详细的分析过程。
2. 状态转换图1 2 0 01-0-9|其它 无符号整数 4 5 3 6 7 8 9 其他 ()+-*/3. 实验步骤1. 判断所给出的转换图能否实现预期目的?若有错误,请加以修正;2. 尝试将状态图转换为正则文法;3. 试写出无符号整数对应的正则表达式;4. 根据上述结果,构造出最简的DFA;5.编写对应的词法分析程序,并识别下述符号串:((23+12)*9-200)/54. 流程图开始接受输入字符串是是否为字符串尾否按位字符判断否是否为有效输入是进入自动机判断结果结束1.源程序FILE *fp;char cbuffer;char*key[8]={"if","else","for","while","do","return","break","contin ue"};char *border[6]={",",";","{","}","(",")"};char *arithmetic[4]={"+","-","*","/"};char *relation[6]={"<","<=","=",">",">=","<>"};char *consts[20]={"0","1","2","3","4","5","6","7","8","9"}; char *label[20];int constnum=0,labelnum=0;int search(char searchchar[],int wordtype){ int i=0;switch (wordtype) {case 1:for (i=0;i<=7;i++){ if (strcmp(key[i],searchchar)==0){return(i+1);}}break;case 2:{for (i=0;i<=5;i++){ if (strcmp(border[i],searchchar)==0) return(i+1);} return(0);}break;case 3:{for (i=0;i<=3;i++){ if (strcmp(arithmetic[i],searchchar)==0) { return(i+1);}}return(0);}break;case 4:{for (i=0;i<=5;i++){ if (strcmp(relation[i],searchchar)==0) {return(i+1);} }return(0);}break;case 5:{for (i=0;i<=constnum;i++){ if (strcmp(consts[i],searchchar)==0){ return(i+1);} }}break;case 6:{for (i=0;i<=labelnum;i++){ if (strcmp(label[i],searchchar)==0){ return(i+1);} }label[i-1]=(char *)malloc(sizeof(searchchar));strcpy(label[i-1],searchchar);labelnum++;return(i);}break;}}char alphaprocess(char buffer)//关键字{ int atype;int i=-1;char alphatp[20];while ((isalpha(buffer))||(isdigit(buffer))){ alphatp[++i]=buffer;buffer=fgetc(fp);}alphatp[i+1]='\0';if (atype=search(alphatp,1))printf("%s \t(1,%d)\n",alphatp,atype-1);//结束else { atype=search(alphatp,6);printf("%s \t(6,%d)\n",alphatp,atype-1);}return(buffer);}char digitprocess(char buffer)//数字{ int i=-1;char digittp[20];int dtype;while ((isdigit(buffer))){ digittp[++i]=buffer;buffer=fgetc(fp);}digittp[i+1]='\0';dtype=search(digittp,5);printf("%s \t(5,%d)\n",digittp,dtype-1);return(buffer);}char otherprocess(char buffer)//其它字符{ int i=-1;char othertp[20];int otype,otypetp;othertp[0]=buffer;othertp[1]='\0';if (otype=search(othertp,3)){ printf("%s \t(3,%d)\n",othertp,otype-1);buffer=fgetc(fp);goto out;}if (otype=search(othertp,4)){ buffer=fgetc(fp);othertp[1]=buffer;othertp[2]='\0';if (otypetp=search(othertp,4)){ printf("%s \t(4,%d)\n",othertp,otypetp-1);goto out;}elseothertp[1]='\0';printf("%s \t(4,%d)\n",othertp,otype-1); goto out;}if (buffer==':'){ buffer=fgetc(fp);if (buffer=='=')printf(":= (2,2)\n");buffer=fgetc(fp);goto out;}else{ if (otype=search(othertp,2)) { printf("%s \t(2,%d)\n",othertp,otype-1); buffer=fgetc(fp);goto out;}}if ((buffer!='\n')&&(buffer!=' '))printf("%c error,not a word\n",buffer); buffer=fgetc(fp);out: return(buffer);}void main(){int i;for (i=0;i<=20;i++){label[i]=NULL;};if ((fp=fopen("message.txt","r"))==NULL)printf("error");else{cbuffer = fgetc(fp);while (cbuffer!=EOF){if (isalpha(cbuffer))cbuffer=alphaprocess(cbuffer);else if (isdigit(cbuffer))cbuffer=digitprocess(cbuffer);elsecbuffer=otherprocess(cbuffer);}printf("over\n");getchar();}}2.运行结果四、实验小结。
编译原理实验报告一
图1识别表I所列语言中的部分单词的DFA及相关的语义过程
图1中所出现的语义变量及语义函数的含义和功能说明如下:
函数GETCHAR:每调用一次,就把扫描指示器当前所指示的源程序字符送入字符变量ch,然后把扫描指示器前推一个字符位置。
三、实现方法与环境
词法分析是编译程序的第一个处理阶段,可以通过两种途径来构造词法分析程序。其一是根据对语言中各类单词的某种描述或定义(如BNF),用手工的方式(例如可用C语言)构造词法分析程序。一般地,可以根据文法或状态转换图构造相应的状态矩阵,该状态矩阵连同控制程序一起便组成了编译器的词法分析程序;也可以根据文法或状态转换图直接编写词法分析程序。构造词法分析程序的另外一种途径是所谓的词法分析程序的自动生成,即首先用正规式对语言中的各类单词符号进行词型描述,并分别指出在识别单词时,词法分析程序所应进行的语义处理工作,然后由一个所谓词法分析程序的构造程序对上述信息进行加工。如美国BELL实验室研制的LEX就是一个被广泛使用的词法分析程序的自动生成工具。
四.源程序
#include<stdio.h>
#include <ctype.h>
#include<string.h>
#include<math.h>
#defineID 6
#define INT7
#define LT 8
#define LE9
#defineEQ 10
#defineNE11
#defineGT12
#define POINT 2
#define OTHER3
#define POWER4
#define PLUS5
《编译原理》课程实验报告
华东交大理工学院《编译原理》课程实验报告题目:词法分析器实验专业:计算机科学与技术班级:1班学号:* * * *****姓名:* * *一、实验目的通过本实验的编程实践,使学生了解词法分析的任务,掌握词法分析程序设计的原理和构造方法,使学生对编译的基本概念、原理和方法有完整的和清楚的理解,并能正确地、熟练地运用。
二、实验内容及要求用VC++/VB/JA V A语言实现对C语言子集的源程序进行词法分析。
通过输入源程序从左到右对字符串进行扫描和分解,依次输出各个单词的内部编码及单词符号自身值;若遇到错误则显示“Error”,然后跳过错误部分继续显示;同时进行标识符登记符号表的管理。
以下是实现词法分析设计的主要工作:(1)从源程序文件中读入字符。
(2)统计行数和列数用于错误单词的定位。
(3)删除空格类字符,包括回车、制表符空格。
(4)按拼写单词,并用(内码,属性)二元式表示。
(属性值——token的机内表示)(5)如果发现错误则报告出错(6)根据需要是否填写标识符表供以后各阶段使用。
单词的基本分类:关键字:由程序语言定义的具有固定意义的标识符。
也称为保留字例如if、for、while、printf ;单词种别码为1。
标识符:用以表示各种名字,如变量名、数组名、函数名;常数:任何数值常数。
如125, 1,0.5,3.1416;运算符:+、-、*、/;关系运算符:<、<=、= 、>、>=、<>;分界符:;、,、(、)、[、];三、实验程序设计说明1.实验方案设计1、主程序设计考虑:程序的说明部分为各种表格和变量安排空间。
在具体实现时,将各类单词设计成结构和长度均相同的形式,较短的关键字后面补空。
k数组------关键字表,每个数组元素存放一个关键字(事先构造好关键字表)。
s 数组------存放分界符表(可事先构造好分界符表)。
为了简单起见,分界符、算术运算符和关系运算符都放在s表中(编程时,应建立算术运算符表和关系运算符表,并且各有类号),合并成一类。
编译原理实验指导书(-).docx
编译原理实验指导书合肥学院计算编译原理实验指导书实验一词法分析一、实验目的:通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。
并掌握在对程序设计语言源程序进行扫描过程屮将其分解为各类单词的词法分析方法。
编制一个读单词过程,从输入的源程序中,识別出各个具有独立意义的单词, 即基木保留字、标识符、常数、运算符、分隔符五大类。
并依次输出各个单词的内部编码及单词符号自身值。
(遇到错误时可显示“Error”,然后跳过错误部分继续显示)二、实验预习提示1、词法分析器的功能和输出格式词法分析器的功能是输入源程序,输出单词符号。
词法分析器的单词符号常常农示成以下的二元式(单词种别码,单词符号的属性值)。
本实验中,采用的是一类符号一种别码的方式。
2、单词的BNF表示<标识符> -V字母〉v字母数字串〉V字母数字串一V字母〉V字母数字串>|v数字〉V字母数字串〉Iv下划线>v字母数字串I e<无符号整数一V数字〉v数字串〉V数字串〉一V数字〉V数字串〉v加法运算符>-+<减法运算符〉->・V大于关系运算符>->>V大于等于关系运算符>-> =3、“超前搜索”方法词法分析时,常常会用到超前搜索方法。
如当前待分析字符串为“”,当前字符为此时,分析器倒底是将其分析为犬于关系运算符还是犬于等于关系运算符呢?显然,只有知道下一个字符是什么才能下结论。
超前读了一个字符所以要回退一个字符,词法分析器才能正常运行。
在分析标识符,无符号整数等时也有类似情况。
4、模块结构Y饗冲区扫播一个辛閒N ▼三、实验过程和指导:(-)准备:1・阅读课木有关章节,明确语言的语法,写出基木保留字、标识符、常'数、运算符、分隔符和程序例。
2 .初步编制好程序。
3•准备好多组测试数据。
(二)上课上机: 将源代码拷贝到机上调试,发现错误,再修改完善。
第二次上机调试通过。
(三)程序要求:程序输入/输出示例:如源程序为C语言。
输入如卜•一段:main(){int a,b;a = 1 0;b = a 4- 20;}要求输出如下图。
编译原理实验教案
一、实验目的与要求1. 实验目的(1) 理解编译原理的基本概念和流程。
(2) 掌握常用的编译方法和技术。
(3) 熟练使用编译器开发工具。
2. 实验要求(1) 熟悉计算机专业基础知识。
(2) 掌握C/C++编程语言。
(3) 了解基本的编译原理。
二、实验环境1. 硬件环境(1) 计算机一台。
(2) 编译器开发工具(如GCC、Clang等)。
2. 软件环境(1) 操作系统(如Windows、Linux等)。
(2) 文本编辑器或集成开发环境(如Visual Studio、Eclipse等)。
三、实验内容1. 实验一:词法分析(1) 实现一个简单的词法分析器,识别出关键字、标识符、常量等。
(2) 分析输入的程序,输出词法分析结果。
2. 实验二:语法分析(1) 实现一个简单的语法分析器,根据给定的语法规则分析输入的程序。
(2) 分析输入的程序,输出语法分析树。
3. 实验三:语义分析(1) 实现一个简单的语义分析器,检查程序中的语义错误。
(2) 分析输入的程序,输出语义分析结果。
4. 实验四:中间代码(1) 实现一个简单的中间代码器,将转换为中间代码表示。
(2) 对输入的程序进行转换,输出中间代码。
5. 实验五:目标代码(1) 实现一个简单的目标代码器,将中间代码转换为目标代码。
(2) 对输入的中间代码进行转换,输出目标代码。
四、实验步骤与方法1. 实验一:词法分析(1) 编写词法分析器的代码。
(2) 测试并调试词法分析器。
2. 实验二:语法分析(1) 编写语法分析器的代码。
(2) 测试并调试语法分析器。
3. 实验三:语义分析(1) 编写语义分析器的代码。
(2) 测试并调试语义分析器。
4. 实验四:中间代码(1) 编写中间代码器的代码。
(2) 测试并调试中间代码器。
5. 实验五:目标代码(1) 编写目标代码器的代码。
(2) 测试并调试目标代码器。
五、实验注意事项1. 按照实验要求编写代码,注意代码规范和可读性。
编译原理实验报告
实验一词法分析一、实验目的通过设计、编写和调试词法分析程序,了解词法分析程序的作用,组成结构,不同种类单词的识别方法,掌握由单词的词法规则出发,画出识别单词的状态转换图,然后在用程序实现词法分析程序设计方法。
二、词法规则1、注释用{和}括起来。
注释体中不能有{。
注释可以出现在任何记号的后面。
2、记号间的空格可有可无,但关键字前后必须有空格、换行、程序的开头或者结尾的原点。
3、标识符的记号id 与以字母开头的字母数字串相匹配:Letter->[a-zA-Z]Digit->[0-9]Id->letter (letter | digit)*4、记号num与无符号整数相匹配:Digits->digit digit*Optional_fraction -> . Digits | ɛOptional_exponent->(E(+ | - | ɛ ) digits) | ɛNum ->digits optional_fraction optional_exponent5、关键字要被保留且在文法中以黑体出现6、关系运算符(relop)指:=、<、<>、<=、>=、>7、Addop: + 、 - 、or8、Mulop:*、/ 、div、mod、and9、Assignop: :=三、词法分析程序详细设计及判别状态图1、无符号数(可带小数和指数)的状态转换图:2、标识符/关键字的状态转换图:字母或数程序详细设计:四、开发环境本程序在Microsoft Visual C++ 6.0环境中编写,无特殊编译要求。
五、函数清单void LexcialAnalysis(FILE *fp);//词法分析主函数int JudgeFirstLetter(char ch);//判断单词的第一个字符int IsDigit(char ch);//判断是否为数字int IsLetter(char ch);//判断是否为字母int IsSpecialPunc(char ch);//判断是否为特殊标点void RecogDigit(char StrLine[]);//用状态图识别无符号数字void RecogIdentifier(char strLine[]);//用状态图识别标识符void RecogPunc(char strLine[]);//识别特殊标点int IsKeyWord(string str);//判断标识符是否为关键字void error();//出错处理六、测试程序program example(input, output);{comments goes here!}var x, y: integer;function gcd(a, b: integer): integer;beginif b =1.2e3 then gcd := aelse gcd := gcd(b, a mod b)end;beginread(x, y);write(gcd(x, y));end.七、运行效果八、实验总结通过这次编译器词法分析程序的编写,我更好地了解了词法分析的作用及工作原理,讲课本中的知识融入到程序编写过程中,理论结合了实际。
编译原理实验一
实验一词法分析程序实现一、实验目的与要求通过编写和调试一个词法分析程序,掌握在对程序设计语言的源程序进行扫描的过程中,将字符形式的源程序流转化为一个由各类单词符号组成的流的词法分析方法。
二、实验设计语言中具有的单词包括五个关键字begin、end、if、then、else;标识符;整型常数;六种关系运算符;一个赋值符和四个算术运算符。
参考实现方法简述如下。
单词的分类:构造上述语言中的各类单词符号及其分类码表。
表I 语言中的各类单词符号及其分类码表识别表I所列语言中的部分单词的DFA及相关的语义过程将表I单词集中的整常数改为无符号常数,无符号常数的单词分类码助记符:UCON描述无符号数的正规文法和状态转换图:无符号数的右线性文法G1[<无符号数>]如下:〈无符号数〉→d〈余留无符号数〉〈无符号数〉→·〈小数部分〉〈无符号数〉→ d〈余留无符号数〉→d〈余留无符号数〉〈余留无符号数〉→·〈十进小数〉〈余留无符号数〉→E〈指数部分〉〈余留无符号数〉→ d〈余留无符号数〉→·〈十进小数〉→E〈指数部分〉〈十进小数〉→d〈十进小数〉〈十进小数〉→ d〈小数部分〉→d〈十进小数〉〈小数部分〉→ d〈指数部分〉→d〈余留整指数〉〈指数部分〉→+〈整指数〉〈指数部分〉→-〈整指数〉〈指数部分〉→ d〈整指数〉→d〈余留整指数〉〈整指数〉→ d〈余留整指数〉→d〈余留整指数〉〈余留整指数〉→ d图所示为上述文法的状态转换图,其中编号0、1、2、…、6分别代表非终结符号<无符号数>、<余留无符号数>、<十进小数>、<小数部分>、<指数部分>、<整指数>及<余留整指数>。
文法G1[<无符号数>]的状态转换图包含语义处理过程的识别无符号数的状态矩阵三、源程序////////扫描器///////#include<stdio.h>#include<ctype.h>#include<stdlib.h>#include<string.h>#include<math.h>#define BEGIN 1#define END 2#define IF 3#define THEN 4#define ELSE 5#define ID 6#define INT 7#define LT 8#define LE 9#define EQ 10#define NE 11#define GT 12#define GE 13#define PL 14#define MI 15#define MU 16#define DI 17#define TOKEN_SIZE 64#define TAB_SIZE 5char TOKEN[TOKEN_SIZE]; extern int lookup(char *); extern void out(int ,char*); extern void report_error(); int GetChar(void);int EXCUTE(int,int);int LEX(void);#define LETTER 0#define DIGIT 1#define POINT 2#define OTHER 3#define POWER 4#define PLUS 5#define MINUS 6#define ClassNo 100#define ClassOther 200#define EndState -1int w,n,p,e,d;int Class;int ICON;float FCON;static int CurrentState;char ch;//信息表保存5个关键字typedef struct{int ad;char id[6];}info_ele;info_ele Tab[TAB_SIZE]={{1,"begin"},{2,"end"},{3,"if"},{4,"then"},{5,"else"}}; void scanner_example(FILE *fp) //扫描器函数{int i,c;ch=fgetc(fp);if(isalpha(ch)) //是否为字母{TOKEN[0]=ch;i=1;ch=fgetc(fp);while(isalnum(ch)) //是否为字母或数字{TOKEN[i]=ch;i++;ch=fgetc(fp);}fseek(fp,-1,1);TOKEN[i]='\0';c=lookup(TOKEN); //调用输出函数out()if (c==0)out(ID,TOKEN);elseout(c,TOKEN);}else if(isdigit(ch)) //判断是否为整数{TOKEN[0]=ch;i=1;ch=fgetc(fp);while(isdigit(ch)||ch=='.'||ch=='e'||ch=='-'){TOKEN[i]=ch;i++;ch=fgetc(fp);}fseek(fp,-1,1);TOKEN[i]='\0';out(INT,TOKEN);LEX();}else //判断运算符if(ch==' '||ch=='\n'); //遇见空格、回车继续elseswitch(ch){case '=':out(EQ,"=");break;case '>':ch=fgetc(fp);if(ch=='=')out(GE,">=");else{fseek(fp,-1,1);out(GT,">");}break;case'<':ch=fgetc(fp);if(ch=='=')out(LE,"<=");else if(ch=='>')out(NE,"<>");else{fseek(fp,-1,1);out(LT,"<");}break;case '+':out(PL,"+");break;case '-':out(MI,"-");break;case '*':out(MU,"*");break;case '/':out(DI,"/");break;default: report_error();break;}}int lookup(char p[]) //查找是否为关键字{int i=0;for(i;i<TAB_SIZE;i++){if(!strcmp(Tab[i].id,p))return (Tab[i].ad);}return 0;}void out(int a,char *p) ///输出结果{switch(a){case BEGIN: printf("(BEGIN,%s)\n",p);break;case END : printf("(END,%s)\n",p); break;case IF: printf("(IF,%s)\n",p);break;case THEN: printf("(THEN,%s)\n",p);break;case ELSE: printf("(ELSE,%s)\n",p);break;case ID: printf("(ID,%s)\n",p);break;case INT:printf("(UCON,%s)\n",p);break;case LT:printf("(LT,%s)\n",p);break;case LE:printf("(LE,%s)\n",p);break;case EQ:printf("(EQ,%s)\n",p);break;case NE:printf("(NE,%s)\n",p);break;case GT:printf("(GT,%s)\n",p);break;case GE:printf("(GE,%s)\n",p);break;case PL:printf("(PL,%s)\n",p);break;case MI:printf("(MI,%s)\n",p);break;case MU:printf("(MU,%s)\n",p);break;case DI: printf("(DI,%s)\n",p);break;default: break;}}void report_error(){printf("\n有错误!\n");exit(0);}///////////////////////////////////////////////////识别无符号数////int HandleOtherWord(void){return ClassOther;}int HandleError(void){printf("Error!\n");return 0;}int GetChar(int i){int c;c=(int)TOKEN[i];//scanf("d%",c);if(isdigit(c)){d=c-'0';return DIGIT;}if(c=='.') return POINT;if(c=='e'||c=='e') return POWER;if(c=='+') return PLUS;if(c=='-') return MINUS;return OTHER;}int EXCUTE(int state,int symbol){float pow(int,int);switch(state){case 0:switch(symbol){caseDIGIT:n=0;p=0;e=1;w=d;CurrentState=1;Class=ClassNo;break;casePOINT:w=0;n=0;p=0;e=1;CurrentState=3;Class=ClassNo;break;default:HandleOtherWord();ClassOther;CurrentState=EndState;}break;case 1:switch(symbol){case DIGIT:w=w*10+d;break;case POINT:CurrentState=2;break;case POWER:CurrentState=4;break;default:ICON=w;CurrentState=EndState;printf("%d\n",ICON);}break;case 2:switch(symbol){case DIGIT:n++;w=w*10+d;break;case POWER:CurrentState=4;break;default:FCON=w*pow(10,e*p-n);CurrentState=EndState;printf("%f\n",FCON);}break;case 3:switch(symbol){case DIGIT:n++;w=w*10+d;CurrentState=2;break;default:HandleError();CurrentState=EndState;}break;case 4:switch(symbol){case DIGIT:p=p*10+d;CurrentState=6;break;case MINUS:e=-1;CurrentState=5;break;case PLUS:CurrentState=5;break;default:HandleError();CurrentState=EndState;}break;case 5:switch(symbol){case DIGIT:p=p*10+d;CurrentState=6;break;default:HandleError();CurrentState=EndState;}break;case 6:switch(symbol){case DIGIT:p=p*10+d;break;default:FCON=w*pow(10,e*p-n);CurrentState=EndState;printf("%f\n",FCON);}break;}return CurrentState;}int LEX(void){int ch,a=0;CurrentState=0;while(CurrentState!=EndState){ch=GetChar(a);EXCUTE(CurrentState,ch);a++;}return Class;}void main(){extern char ch;FILE * fp;if((fp=fopen("data.txt","r"))==NULL) //打开文件data.txt {printf("\nfile open error!\n");exit(0);}do{scanner_example(fp); //调用扫描程序}while(ch!=EOF);}四、测试输入:输出:五、实验总结我通过编写和调试一个词法分析程序,掌握在对程序设计语言的源程序进行扫描的过程中,还学会了将字符形式的源程序流转化为一个由各类单词符号组成的流的词法分析方法。
编译原理实验(布置版)
编译原理实验(布置版)实验一:基于有限自动机方法的简单词法分析程序的设计与实现——无符号实数识别程序1、实验目的通过本实验,使学生进一步熟悉词法分析程序所用的工具——自动机方法,掌握文法转换成自动机的技术及用C语言实现有穷自动机识别单词的方法。
2、实验内容根据教材P46无符号实数的状态转换图,用C或C++语言编制识别无符号实数的程序。
要求:程序执行时,首先给出提示“Please input a unsigned real number:”,输入数据后,给出对该数据的分析结果信息如“The number is right!”或“The number is error!”,反复输入数据和分析,直到输入回车或其他键符,退出程序执行。
3、实验报告要求按照实验报告模板格式要求组织内容,必须要有以下内容:(1)无符号实数词法分析的思想。
(2)无符号实数的文法和根据文法生成的状态转换图(即有穷自动机)。
(3)程序处理的流程图(4)程序运行(测试)结果截图(5)源程序清单实验二:综合词法分析程序的设计与实现1、实验目的设计、编制、调试一个词法分析子程序-识别单词,加深对词法分析原理的理解。
2、实验内容(1)本程序自行规定:关键字:“begin”,“end”,“if”,“then”,“else”,“while”,“write”,“read”,“do”,“call”,“const”,“char”,“until”,“procedure”,“repeat”。
运算符:“+”,“-”,“*”,“/”,“=”界符:“{”,“}”,“[”,“]”,“;”,“,”,“.”,“(”,“)”,“:”标识符:以字母开头的字符串。
空格、回车、换行符跳过。
(2)用C或C++语言编制程序,实现对下述一段源程序的词法分析。
//源程序文件位置及名称:F:\…\MY.TXTbeginx:=9if x>0 then x:=x+1;while a:=0 dob:=2*x/3;end;输出结果(在屏幕上显示)形式举例:( 1 , 无符号整数)( begin , 关键字)( if , 关键字)( +, 运算符)( ;界符)( a , 标识符)……编程提示:构造一个关键字表,根据关键字表及当前所接受的状态,可以识别出单词的属性。
编译原理实验报告
编译原理实验报告编译原理实验报告一、引言编译原理是计算机科学中的重要课程之一,它研究的是如何将高级语言程序转化为机器语言程序的过程。
在本次实验中,我们将学习并实践编译原理中的一些基本概念和技术,包括词法分析、语法分析和语义分析等。
二、词法分析词法分析是编译过程中的第一步,它负责将源程序中的字符序列转化为有意义的词法单元。
在本次实验中,我们使用了Flex工具来生成词法分析器。
通过定义一系列正则表达式和对应的动作,我们可以将源程序中的字符序列识别为不同的词法单元,如标识符、关键字、运算符等。
三、语法分析语法分析是编译过程中的第二步,它负责将词法单元序列转化为抽象语法树。
在本次实验中,我们使用了Bison工具来生成语法分析器。
通过定义一系列文法规则和对应的动作,我们可以将词法单元序列转化为抽象语法树,并进行语法错误的检测和恢复。
四、语义分析语义分析是编译过程中的第三步,它负责对抽象语法树进行语义检查和语义动作的执行。
在本次实验中,我们通过自定义语义规则和对应的动作,对抽象语法树进行类型检查、符号表管理等操作。
同时,我们还实现了一些简单的语义动作,如计算表达式的值、生成中间代码等。
五、中间代码生成中间代码生成是编译过程中的一项重要任务,它负责将源程序转化为机器无关的中间表示形式。
在本次实验中,我们使用了三地址码作为中间表示形式。
通过对抽象语法树的遍历和一系列的转换规则,我们可以将源程序转化为等价的三地址码表示形式。
六、实验结果与分析通过对一些简单的测试程序的编译,我们验证了我们所实现的词法分析、语法分析、语义分析和中间代码生成的正确性。
同时,我们还进行了一些性能测试,对比了不同算法和数据结构在编译过程中的效率差异。
实验结果表明,我们所实现的编译器在处理大规模程序时具有较好的性能。
七、结论通过本次实验,我们深入了解了编译原理中的一些基本概念和技术,并通过实践加深了对编译过程的理解。
同时,我们也意识到编译器的设计和实现是一项复杂而有挑战性的任务,需要综合运用多种算法和数据结构。
编译原理实验教案
编译原理实验教案(总46页) --本页仅作预览文档封面,使用时请删除本页--2实验教学进度表3实验一 C语言子集编译程序一、实验目的用C语言对一个C语言的子集编制一个一遍扫描的编译程序,以加深对编译原理的理解,掌握编译程序的实现方法和技术。
1.设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。
2.编制一个递归下降分析程序,并对C语言的简单子集进行分析。
3.通过上机实习,加深对语法制导翻译原理的理解,掌握将语法分析所识别的语法成分变换中间代码的语义翻译方法。
二、实验要求、内容及学时词法分析部分:2学时(一)待分析的C语言子集的词法:1.关键字main if else int return void while所有关键字都是小写。
2.专用符号= + - * / < <= > >= == != ; : , { } [ ] ( )3.其他标记ID和NUM通过以下正规式定义其他标记:ID→letter(letter|digit)*NUM→digit(digit)*letter→a|…|z|A|…|Z digit→0|…|94.空格由空白、制表符和换行符组成空格一般用来分隔ID、NUM、专用符号和关键字,词法分析阶段空格通常被忽略。
各种单词符号对应的类别码:(采用一符一类别码,见下表)4(二)词法分析程序的功能:输入:所给文法的源程序字符串。
输出:二元组(syn,token或sum)构成的序列。
其中,syn 为单词类别码。
token 为存放的单词自身字符串。
sum 为整型常量。
具体实现时,可以将单词的二元组用结构进行处理。
例如:对源程序main(){int i=10;while(i) i=i-1;}的源文件,经词法分析后输出如下序列:(1,main) (26,() (27,)) (30,{) (2,int) (10,i) (21,=) (20,10) (34,;) (7,while) (26,() (10,i) (27,)) (10,i) (21,=) (10,i) (23,-) (20,1) (34,;) (31, })(三)词法分析程序主要算法思想:算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
2015-2016学年第一学期《编译原理》实验一实验报告
13计科3 夏以彬 201333030253
一、实验目的
1、构造一个《科学计算器》的词法分析程序,程序要求能对输入的字符串流进行词法分析。
2、在实验的过程中,学会应用词法分析的方法——构造NFA和DFA。
二、token的正规式描述
数字:(0|1|2...|8|9)*.( 0|1|2...|8|9)*
分隔符:(=|^|!|%|+|-|*|/|(|))
字符串:(a|b|…|y|z)+
因为在实现中,特殊字符串是先取的普通字符串的token,然后与存储的特殊字符表比对,因此这里只给出普通字符串的token。
三、有限状态机状态图
四、词法分析器的数据结构与算法
主要数据结构包括:
主要的算法:根据有限状态机状态图构造类如下二维表格
然后根据表格构造各个事件的处理方法,以及各个动作的处理方法。
当然,也需要添加一个辅助方法,以根据输入判断触发的是哪个事件。
源代码:
#include<iostream>
#include<string>
using namespace std;
int main(){
stringst,st_num="";
charch[100];
doubleresult,point;
cout<<"请输入字符串流"<<endl;
cin>>st;
strncpy(ch,st.c_str(),st.length());
//cout<<ch[2];
for(int i=0;i<=st.length();i++){
if(ch[i]=='+'){
cout<<"$("<<"number,"<<st_num<<")"<<endl;
cout<<"$("<<"plus,"<<"+"<<")"<<endl;
//point=atof(st_num);
//result=result+point;
st_num="";
}
else if(ch[i]=='-'){
cout<<"$("<<"number,"<<st_num<<")"<<endl;
cout<<"$("<<"minus,"<<"-"<<")"<<endl;
st_num="";
}
else if(ch[i]=='*'){
cout<<"$("<<"number,"<<st_num<<")"<<endl;
cout<<"$("<<"mul,"<<"*"<<")"<<endl;
st_num="";
}
else if(ch[i]=='/'){
cout<<"$("<<"number,"<<st_num<<")"<<endl;
cout<<"$("<<"devide,"<<"/"<<")"<<endl;
st_num="";
}
else if(ch[i]=='='){
cout<<"$("<<"number,"<<st_num<<")"<<endl;
cout<<"$("<<"equal,"<<"="<<")"<<endl;
st_num="";
}
else if(ch[i]=='c'){
if(ch[i+1]=='o'){
if(ch[i+2]=='s'){
cout<<"$("<<"number,"<<st_num<<")"<<endl;
cout<<"$("<<"symbol,"<<"cos"<<")"<<endl;
st_num="";
}
}
}
else if(ch[i]=='s'){
if(ch[i+1]=='i'){
if(ch[i+2]=='n'){
cout<<"$("<<"number,"<<st_num<<")"<<endl;
cout<<"$("<<"symbol,"<<"sin"<<")"<<endl;
st_num="";
}
}
}
else if(ch[i]=='l'){
if(ch[i+1]=='o'){
if(ch[i+2]=='g'){
cout<<"$("<<"number,"<<st_num<<")"<<endl;
cout<<"$("<<"symbol,"<<"log"<<")"<<endl;
st_num="";
}
}
}
else if(ch[i]=='t'){
if(ch[i+1]=='g'){
cout<<"$("<<"number,"<<st_num<<")"<<endl;
cout<<"$("<<"symbol,"<<"tg"<<")"<<endl;
st_num="";
}
}
else{
st_num=st_num+ch[i];
}
}
}
五、token的输出
输入1.0+2*3=
输出
输入1.0+(2*3+cos3)/3.6-6=
输出
输入tan(1.0+(sin2*3+cos3)/3.6-6)= 输出
输入4.0log(1.0+(sin2*3+cos3)/3.6-6)=
输出
六、思考题:
程序设计中哪些环节影响词法分析的效率?如何提高效率?
对于特殊字符的词法分析,采用了先接收再对比识别,略影响了分析效率。
如果可以在完全接受之前就做出判断,则可提高效率。