编译原理 实验一
- 格式:docx
- 大小:110.07 KB
- 文档页数:31
编译原理实验报告实验名称:实验一编写词法分析程序实验类型:验证型实验指导教师:何中胜专业班级:13软件四姓名:丁越学号:13030504电子邮箱:862245792@实验地点:秋白楼B720实验成绩:日期:2016年3 月18 日一、实验目的通过设计、调试词法分析程序,实现从源程序中分出各种单词的方法;熟悉词法分析程序所用的工具自动机,进一步理解自动机理论。
掌握文法转换成自动机的技术及有穷自动机实现的方法。
确定词法分析器的输出形式及标识符与关键字的区分方法。
加深对课堂教学的理解;提高词法分析方法的实践能力。
通过本实验,应达到以下目标:1、掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的方法。
2、掌握词法分析的实现方法。
3、上机调试编出的词法分析程序。
二、实验过程以编写PASCAL子集的词法分析程序为例1.理论部分(1)主程序设计考虑主程序的说明部分为各种表格和变量安排空间。
数组 k为关键字表,每个数组元素存放一个关键字。
采用定长的方式,较短的关键字后面补空格。
P数组存放分界符。
为了简单起见,分界符、算术运算符和关系运算符都放在 p表中(编程时,还应建立算术运算符表和关系运算符表,并且各有类号),合并成一类。
id和ci数组分别存放标识符和常数。
instring数组为输入源程序的单词缓存。
outtoken记录为输出内部表示缓存。
还有一些为造表填表设置的变量。
主程序开始后,先以人工方式输入关键字,造 k表;再输入分界符等造p表。
主程序的工作部分设计成便于调试的循环结构。
每个循环处理一个单词;接收键盘上送来的一个单词;调用词法分析过程;输出每个单词的内部码。
⑵词法分析过程考虑将词法分析程序设计成独立一遍扫描源程序的结构。
其流程图见图1-1。
图1-1该过程取名为 lexical,它根据输入单词的第一个字符(有时还需读第二个字符),判断单词类,产生类号:以字符 k表示关键字;i表示标识符;c表示常数;p表示分界符;s表示运算符(编程时类号分别为 1,2,3,4,5)。
实验内容:实现标准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语言词法分析的所有的功能。
实验1简单的词法分析子程序【实验目的】●理解词法分析在编译程序中的作用●初步了解和掌握词法分析程序的实现方法和技术【实验内容】1. 编写程序,输入一串字符,判断该字符串是否为合法标识符或合法整型常量。
2. 无符号数的算术四则运算中的各类单词的识别。
输入:由无符号数、+、-、*、/、(、)构成的算术表达式。
输出:对识别出的每一单词均单行输出。
如,输入:8*2.5-1.0e2则,输出:8*2.5-1.0e2描述无符号数的确定的、最小化的状态转换图如图1所示。
其中编号1,2和6为终态,分别代表整数、小数和科学计数的识别结束状态。
图1 文法G[<无符号数>]的状态转换图实验2词法分析程序设计【实验目的】●理解词法分析中的正规式和自动机●掌握词法分析程序的实现方法和技术【实验内容】某一高级程序设计语言的部分语言子集定义如下:(1)关键字:for if then else while do(所有关键字都是小写)(2)运算符和分隔符:+ - * / : = <><= <>>= == ; ( ) #(3)其他标识符(ID)和整型常数(NUM),通过以下正规式定义:ID=letter(letter|digit)*NUM=digit·digit*(4)空格由空白、制表符和换行符组成。
空格一般用来分隔ID、NUM、运算符、分隔符和关键字,词法分析阶段通常被忽略。
各种词法单元对应的词法记号如下:编写程序,实现词法分析功能。
输入:源程序输出:二元组(词法记号,属性值/其在符号表中的位置)构成的序列。
例如:输入源程序x=5;if (x>0)thenx=2*x+1/3;elsex=2/x;#(# 表示输入结束)经词法分析后输出如下序列:(10,x)(18,=)(11,5)(26,;)(2,if)(27,()…说明:关键字表的初值。
关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符,查关键字表。
实验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 #显示结果如下:六、实验结论该词法分析器可以进行输入、预处理;关键字的识别;标识符的识别、常数的识别、算符和界符的识别等。
实验一词法分析器设计【实验目的】1.熟悉词法分析的基本原理,词法分析的过程以及词法分析中要注意的问题。
2.复习高级语言,进一步加强用高级语言来解决实际问题的能力。
3.通过完成词法分析程序,了解词法分析的过程。
【实验内容】用C语言编写一个PL/0词法分析器,为语法语义分析提供单词,使之能把输入的字符串形式的源程序分割成一个个单词符号传递给语法语义分析,并把分析结果(基本字,运算符,标识符,常数以及界符)输出。
【实验流程图】【实验步骤】1.提取pl/0文件中基本字的源代码while((ch=fgetc(stream))!='.'){int k=-1;char a[SIZE];int s=0;while(ch>='a' && ch<='z'||ch>='A' && ch<='Z'){if(ch>='A' && ch<='Z') ch+=32;a[++k]=(char)ch;ch=fgetc(stream);}for(int m=0;m<=12&&k!=-1;m++)for(int n=0;n<=k;n++){if(a[n]==wsym[m][n]) ++s;else s=0;if(s==(strlen(wsym[m]))) {printf("%s\t",wsym[m]);m=14;n=k+1;} }2.提取pl/0文件中标识符的源代码while((ch=fgetc(stream))!='.'){int k=-1;char a[SIZE]=" ";int s=0;while(ch>='a' && ch<='z'||ch>='A' && ch<='Z'){if(ch>='A' && ch<='Z') ch+=32;a[++k]=(char)ch;ch=fgetc(stream);}for(int m=0;m<=12&&k!=-1;m++)for(int n=0;n<=k;n++){if(a[n]==wsym[m][n]) ++s;else s=0;if(s==(strlen(wsym[m]))) {m=14;n=k+1;}}if(m==13) for(m=0;a[m]!=NULL;m++) printf("%c ",a[m]);3.提取pl/0文件中常数的源代码while((ch=fgetc(stream))!='.'){while(ch>='0' && ch<='9'){num=10*num+ch-'0';ch=fgetc(stream);}if(num!=0) printf("%d ",num);num=0;}4.提取pl/0文件中运算符的源代码int ch=fgetc(stream);while(ch!='.'){switch(ch){case'+': printf("+ ");break;case'-': printf("- ");break;case'*': printf("* ");break;case'/': printf("/ ");break;case'>': if(fgetc(stream)=='=')printf(">= "); else printf("> ");break;case'<': if(fgetc(stream)=='=')printf("<= "); else printf("< ");break;case':': printf(":= ");break;case'#': printf("# ");break;case'=': printf("= ");break;default: break;}ch=fgetc(stream);5.提取pl/0文件中界符的源代码int ch=fgetc(stream);while(ch!='.'){switch(ch){case',': printf(", ");break;case';': printf("; ");break;case'(': printf("( ");break;case')': printf(") ");break;default: break;}ch=fgetc(stream);}【实验结果】1.pl/0文件(222.txt)内容const a=10;var b,c;procedure p;beginc:=b+a;end;beginread(b);while b#0 dobegincall p;write(2*c);read(b)endend .2.实验运行结果【实验小结】1.了解程序在运行过程中对词法分析,识别一个个字符并组合成相应的单词,是机器能过明白程序,定义各种关键字,界符。
《编译原理》实验报告班级:计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语言)直接编写词法分析程序。
《编译原理》(实验部分)实验1_程序预处理一、实验目的明确预处理子程序的任务,构造一个简单的预处理子程序,对源程序进行相应的预处理。
二、实验设备1、PC 兼容机一台;操作系统为WindowsWindowsXP。
2、Visual C++ 6.0 或以上版本, Windows 2000 或以上版本,汇编工具(在Software 子目录下)。
三、实验原理定义模拟的简单语言的词法构成,编制读入源程序和进行预处理的程序,要求将源程序读入到文件或存入数组中,再从文件或数组中逐个读取字符进行预处理,包括去掉注释、Tab、Enter和续行符等操作,并显示预处理后的程序。
四、实验步骤1、从键盘读入源程序存放到输入缓冲区中。
2、对源程序进行预处理,预处理后的程序存放到扫描缓冲区中。
3、显示预处理后的程序。
参考源程序(C++语言编写)//源程序的输入及预处理#include <fstream.h>#include <iostream.h>void pro_process(char *);void main( ) //测试驱动程序{//定义扫描缓冲区char buf[4048]={'\0'}; //缓冲区清0//调用预处理程序pro_process(buf); //在屏幕上显示扫描缓冲区的内容cout<<buf<<endl;}void pro_process(char *buf) //预处理程序{ifstream cinf("source.txt",ios::in);int i=0; //计数器char old_c='\0',cur_c; //前一个字符,当前字符。
bool in_comment=false; //false表示当前字符未处于注释中。
while(cinf.read(&cur_c,sizeof(char))){ //从文件读一个字符switch(in_comment){case false:if(old_c=='/' && cur_c=='*'){ //进入注释i--; //去除已存入扫描缓冲区的字符'/'in_comment=true;}else {if(old_c=='\\' && cur_c=='\n') //发现续行i--; //去除已存入扫描缓冲区的字符'\'else {if(cur_c>='A' && cur_c<='Z') //大写变小写cur_c+=32;if(cur_c =='\t' || cur_c =='\n')//空格取代TAB换行cur_c=' ';buf[i++]=cur_c ;}}break;case true:if(old_c=='*' && cur_c=='/') //离开注释in_comment=false;}//end of switchold_c= cur_c; //保留前一个字符}//end of whilebuf[i++]='#'; //在源程序尾部添加字符'#' }。
编译原理实验教程课程设计背景编译原理是计算机科学专业的一门重要课程,它研究如何将高级语言翻译成低级语言,以便计算机执行。
编译器是实现这一过程的关键工具。
然而,对于很多学生来说,编译原理的理论知识学习起来比较抽象,难以掌握。
因此,本文旨在为编译原理的学习提供一些实验教程的设计思路。
实验一:词法分析器词法分析器是编译器的第一个模块,它的作用是将输入的字符流转化为一个个单词符号。
本实验的目的是设计并实现一个简单的词法分析器,实现以下功能:1.识别输入的程序中所包含的各个单词符号。
2.输出所有单词符号及其对应的单词类型。
3.当遇到不合法单词符号时,给出相应的错误提示。
具体实现可以采用有限自动机的思想,使用正则表达式或者手写代码,实现对于不同的单词类型的识别,并对于不合法单词进行识别和报错处理。
实验二:语法分析器语法分析器是编译器的第二个模块,它的作用是将词法分析器输出的单词序列转换成语法树或者语法分析表,以便后续进行语义分析和目标代码生成。
本实验的目的是设计并实现一个简单的语法分析器,实现以下功能:1.识别输入的程序是否符合所设计的文法规则。
2.输出语法树或语法分析表。
具体实现可以采用自上而下的递归下降分析法或自下而上的移进-规约分析法,实现对于不同的句型的识别,并生成语法树或语法分析表。
实验三:语义分析器语义分析器是编译器的第三个模块,它的作用是对语法分析器输出的语法树或语法分析表进行语义分析,并生成中间代码。
本实验的目的是设计并实现一个简单的语义分析器,实现以下功能:1.对语法树或语法分析表进行遍历,识别语法错误和语义错误,给出相应的错误提示。
2.生成中间代码。
具体实现可以采用语义规则和符号表的检查方式,识别语法错误和语义错误,并在生成中间代码时,根据中间代码语言的规则进行实现。
实验四:目标代码生成器目标代码生成器是编译器的第四个模块,它的作用是将中间代码转换成机器语言,以便计算机执行。
本实验的目的是设计并实现一个简单的目标代码生成器,实现以下功能:1.将中间代码转换成机器语言。
编译原理实验(一)——词法分析器一.实验描述运行环境:vc++2008对某特定语言A ,构造其词法规则。
该语言的单词符号包括:12状态转换图3程序流程:词法分析作成一个子程序,由另一个主程序调用,每次调用返回一个单词对应的二元组,输出标识符表、常数表由主程序来完成。
二.实验目的通过动手实践,使学生对构造编译系统的基本理论、编译程序的基本结构有更为深入的理解和掌握;使学生掌握编译程序设计的基本方法和步骤;能够设计实现编译系统的重要环节。
同时增强编写和调试程序的能力。
三.实验任务编制程序实现要求的功能,并能完成对测试样例程序的分析。
四.实验原理char set[1000],str[500],strtaken[20];//set[]存储代码,strtaken[]存储当前字符char sign[50][10],constant[50][10];//存储标识符和常量定义了一个Analyzer类class Analyzer{public:Analyzer(); //构造函数 ~Analyzer(); //析构函数int IsLetter(char ch); //判断是否是字母,是则返回 1,否则返回 0。
int IsDigit(char ch); //判断是否为数字,是则返回 1,否则返回 0。
void GetChar(char *ch); //将下一个输入字符读到ch中。
void GetBC(char *ch); //检查ch中的字符是否为空白,若是,则调用GetChar直至ch进入一个非空白字符。
void Concat(char *strTaken, char *ch); //将ch中的字符连接到strToken之后。
int Reserve(char *strTaken); //对strTaken中的字符串查找保留字表,若是一个保留字返回它的数码,否则返回0。
void Retract(char *ch) ; //将搜索指针器回调一个字符位置,将ch置为空白字符。
实验一编译程序的分析与验证一、实验目的了解编译程序中LR分析表的作用以及语义加工程序的功能二、实验内容(1)验证下述程序的正确性while (a<=b) dobeginif m>=n then a:=a+1elseif j>i then i=i+jelsewhile k=h do x:=x+2;m:=n+m+x+y+n*m+x*yend#~三、编译程序理解输入文件名,取一个字符,程序扫描,词法分析结果打印,变量名表打印,语句分析栈初始化,符号栈初始化,四元式空白初始化,状态栈加工过程及归约顺序,读结果缓冲区中字符到当前字符中,语句分析,四元式分析结果打印,程序运行结束。
具体函数功能介绍:char ch='\0';//可用于存放读出的一个字符int count=0;//词法分析结果缓冲区计数器static char spelling[10]={""};//存放是别的字static char line[81]={""};//一行字符缓冲区char *pline;//line的指针static char ntab1[100][10];//变量类型名表struct ntab{int tc;//真int fc;//假}ntab2[200];//用于存放布尔表达式的值int label=0;//指向ntab2的指针struct rwords{char sp[10];int sy;};//匹配表结构体struct rwords reswords[10]={{"if",sy_if},{"do",sy_do},{"else",sy_else},{"while",sy_while},{"then",sy_then},{"begin",sy_begin},{"end",sy_end},{"and",op_and},{"or",op_or},{"not",op_not}};//初始化匹配表,用于关键字的匹配struct aa{int sy1;//存放变量的类型名int pos;//存放该变量在自己表中的位置}buf[1000],//词法分析结果缓冲区n,//存放二元式当前字符n1,//表达式当前的字符E,//非终结符sstack[100],//算术表达式和布尔表达式的符号栈ibuf[100],//算术表达式和布尔表达式的缓冲区stack[1000];//语法分析的符号栈struct aa oth;//四元式中没有填写的空白位置struct fourexp//四元式结构体{char op[10];struct aa arg1;struct aa arg2;int result;}fexp[200];int ssp=0;//指向 sstack的指针struct aa *pbuf=buf;//词法分析结果缓冲区的指针int nlength=0;//词法分析中记录单词的长度int lnum=0;//行数计数源程序int tt1=0;//变量类型名表的指针FILE *cfile;//源程序文件/********************************************************/int newt=0;//临时变量计数器int nxq=100;//总是指向下一个要形成的四元式每次执行gen()int lr;//用于存放action1中的当前状态int lr1;//用于存放action2,3中的当前状态int sp=0;//LR分析表栈顶指针int stack1[100];//状态栈1int sp1=0;//状态栈的指针int num=0;//算术表达式或布尔表达式的指针struct ll{int nxq1;//指向下一条四元式的指针int tc1;//真值链int fc1;//假值链}labelmark[10];//记录嵌套中每层布尔表达式e的首地址int labeltemp[10];//记录每层else之前四元式的地址int pointmark=-1,pointtemp=-1;//labelmark的指针,labelmark的指针int sign=0;// sign=1 赋值语句,sign=2 while语句,sign=3 if语句构造程序语句的LR分析表算术表达式的LR分析表布尔表达式的LR分析表readline()//读一行{char ch1;pline=line;ch1=fgetc(cfile);//从文件中取一个while((ch1!='\n')&&(ch1!=EOF))//把字符缓冲区填满{*pline=ch1;pline++;ch1=fgetc(cfile);}*pline='\0';//结尾终结符pline=line;//字符缓冲区指针重新回到字符缓冲区的第一个字符位置}/**********************从缓冲区读取一个字符*********************/ readch()//读一个{if(ch=='\0')//读到尾姐再来一行,行数加一{readline();lnum++;}ch=*pline;//从行缓冲区读取一个字符pline++;//字符缓冲区指针后移}/***********************标识符和关键字的识别********************/ find(char spel[])//在变量表中查询{int ss1=0;// 是否查到的变量的标志(1为查到,0为没查到)int ii=0;//记录查到变量表第几条while((ss1==0)&&(ii<nlength))//只要没有查到,或没有超过变量表表长,就继续查{if(!strcmp(spel,ntab1[ii]))ss1=1;ii++;}if(ss1==1)//查到了return ii-1;//返回在表量表的地址(-1的原因是上面的ii++最后多加了一次)else return -1;//没查到,返回-1}identifier()//关键字或变量或常量查询{int iii=0,j,k;//iii关键字表中的指针位置int ss=0;//关键字是否匹配到的标识k=0;//存放的识别的字的指针(spelling[k])do//将取出的字符放入识别的字 spelling数组中{spelling[k]=ch;k++;readch();//取一个字符}while(((ch>='a')&&(ch<='z'))||((ch>='0')&&(ch<='9')));//数字或小写字母pline--;//取字时多加的一个,-1可使 *pline指向字符缓冲区行尾spelling[k]='\0';while((ss==0)&&(iii<10)){if(!strcmp(spelling,reswords[iii].sp))//在关键字表中查询ss=1;//查到标志置1iii++;}/*关键字匹配*/if(ss==1)//在关键字表中查到{buf[count].sy1=reswords[iii-1].sy;//关键字名字放入结果缓冲区}else//没查到{buf[count].sy1=ident;//将变量名置入结果缓冲区j=find(spelling);//变量表查询,查到就把变量在变量表的地址赋给jif(j==-1)//没查到就新建一个变量{buf[count].pos=tt1;//将其在变量表中的地址放入结果缓冲区中的地址栏 strcpy(ntab1[tt1],spelling);//将识别的变量名放入变量名表tt1++;nlength++;//变量名表长加一}else buf[count].pos=j;//查到后,将变量名表中变量的地址放入结果缓冲区该变量的地址栏中}count++;//指向结果缓冲区下一位置for(k=0;k<10;k++) spelling[k]=' ';//以识别的临时字符清空}/**********************数字识别*************************/number(){int ivalue=0;int digit;do{digit=ch-'0';//取出的字符转换为数字ivalue=ivalue*10+digit;//数字地址从10后开始记录readch();//取一个字符}while((ch>='0')&&(ch<='9'));buf[count].sy1=intconst;//常量名存入结果缓冲区buf[count].pos=ivalue;//该常量地址存入结果缓冲区count++;// 向结果缓冲区下一位置pline--;//指向行缓冲区尾字符}scan()//扫描主程序readnu()//读取当前结果缓冲区的二元式存入struct aa n中,pbuf指向结果缓冲区中下一位置的指针newtemp()//返回目前临时变量数gen(char op1[],struct aa arg11,struct aa arg22,int result1)//op1算符,arg11操作数1,arg22操作数2, result1结果merg(int p1,int p2)// 将链首“指针”分别为p1和p2的两条链合并为一条,并返回新链的链首“指针”(此处的“指针”实际上是四元式的序号,应为整型值)backpatch(int p,int t)//用四元式序号t回填以p为首的链,将链中每个四元式的Result域改写为t的值。
change1(int chan)//action1的符号查找排序(i,+,*,(,),#,E,-,/)change2(int chan)//action2的符号查找排序lrparse1(int num)//算数表达式语义分析lrparse2(int num)// 布尔表达式的分析test(int value) // 测试字符是否为表达式中的值(不包括":") lrparse()//程序语句分析disp1()//打印词法分析结果disp2()//打印四元式分析结果disp3()//打印变量表名main()//主函数四、A语言程序分析与验证五、源码(带注释)#include "stdio.h"#include "string.h"#define ACC -2/**************************************/ #define sy_if 0#define sy_then 1#define sy_else 2#define sy_while 3#define sy_begin 4#define sy_do 5#define sy_end 6#define a 7#define semicolon 8#define e 9#define jinghao 10#define S 11#define L 12#define tempsy 15#define EA 18#define E0 19#define plus 34#define sub 35//减#define times 36#define div 37//除#define becomes 38#define op_and 39#define op_or 40#define op_not 41#define rop 42#define lparent 48#define rparent 49#define ident 56#define intconst 57/********************************************/char ch='\0';//可用于存放读出的一个字符int count=0;//词法分析结果缓冲区计数器static char spelling[10]={""};//存放是别的字static char line[81]={""};//一行字符缓冲区char *pline;//line的指针static char ntab1[100][10];//变量类型名表struct ntab{int tc;//真int fc;//假}ntab2[200];//用于存放布尔表达式的值int label=0;//指向ntab2的指针struct rwords{char sp[10];int sy;};//匹配表结构体struct rwords reswords[10]={{"if",sy_if},{"do",sy_do},{"else",sy_else},{"while",sy_while},{"then",sy_then},{"begin",sy_begin},{"end",sy_end},{"and",op_and},{"or",op_or},{"not",op_not}};//初始化匹配表,用于关键字的匹配struct aa{int sy1;//存放变量的类型名int pos;//存放该变量在自己表中的位置}buf[1000],//词法分析结果缓冲区n,//存放二元式当前字符n1,//表达式当前的字符E,//非终结符sstack[100],//算术表达式和布尔表达式的符号栈ibuf[100],//算术表达式和布尔表达式的缓冲区stack[1000];//语法分析的符号栈struct aa oth;//四元式中没有填写的空白位置struct fourexp//四元式结构体{char op[10];struct aa arg1;struct aa arg2;int result;}fexp[200];int ssp=0;//指向 sstack的指针struct aa *pbuf=buf;//词法分析结果缓冲区的指针int nlength=0;//词法分析中记录单词的长度int lnum=0;//行数计数源程序int tt1=0;//变量类型名表的指针FILE *cfile;//源程序文件/********************************************************/int newt=0;//临时变量计数器int nxq=100;//总是指向下一个要形成的四元式每次执行gen()int lr;//用于存放action1中的当前状态int lr1;//用于存放action2,3中的当前状态int sp=0;//LR分析表栈顶指针int stack1[100];//状态栈1int sp1=0;//状态栈的指针int num=0;//算术表达式或布尔表达式的指针struct ll{int nxq1;//指向下一条四元式的指针int tc1;//真值链int fc1;//假值链}labelmark[10];//记录嵌套中每层布尔表达式e的首地址int labeltemp[10];//记录每层else之前四元式的地址int pointmark=-1,pointtemp=-1;//labelmark的指针,labelmark的指针int sign=0;// sign=1 赋值语句,sign=2 while语句,sign=3 if语句/********************程序语句的LR分析表********************/ static int action[19][13]={{2,-1,-1,3,4,-1,-1,5,-1,-1,10,1,-1},{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,ACC,-1,-1},{-1,-1,-1,-1,-1,-1,-1,-1,-1,6,-1,-1,-1},{-1,-1,-1,-1,-1,-1,-1,-1,-1,7,-1,-1,-1},{2,-1,-1,3,4,-1,-1,5,-1,-1,-1,9,8},{-1,-1,104,-1,-1,-1,104,-1,104,-1,104,-1,-1},{-1,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1,11,-1,-1,-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1,-1,12,-1,-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1,-1,105,-1,13,-1,-1,-1,-1},{2,-1,-1,3,4,-1,-1,5,-1,-1,-1,14,-1},{2,-1,-1,3,4,-1,-1,5,-1,-1,-1,15,-1},{-1,-1,103,-1,-1,-1,103,-1,103,-1,103,-1,-1},{2,-1,-1,3,4,-1,-1,5,-1,-1,-1,9,16},{-1,-1,17,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},{-1,-1,102,-1,-1,-1,102,-1,102,-1,102,-1,-1},{-1,-1,-1,-1,-1,-1,106,-1,-1,-1,-1,-1,-1},{2,-1,-1,3,4,-1,-1,5,-1,-1,-1,18,-1},{-1,-1,101,-1,-1,-1,101,-1,101,-1,101,-1,-1}};/********************算术表达式的LR分析表********************/ static int action1[14][9]={{3,-1,-1,2,-1,-1,1,-1,-1,},{-1,4,6,-1,-1,ACC,-1,5,7},{3,-1,-1,2,-1,-1,8,-1,-1},{-1,104,104,-1,104,104,-1,104,104},{3,-1,-1,2,-1,-1,9,-1,-1},{3,-1,-1,2,-1,-1,10,-1,-1},{3,-1,-1,2,-1,-1,11,-1,-1},{3,-1,-1,2,-1,-1,12,-1,-1},{-1,4,6,-1,13,-1,-1,5,7},{-1,101,6,-1,101,101,-1,101,7},{-1,105,6,-1,105,105,-1,105,7},{-1,102,102,-1,102,102,-1,102,102},{-1,106,106,-1,106,106,-1,106,106},{-1,103,103,-1,103,103,-1,103,103}};/********************布尔表达式的LR分析表*********************/ static int action2[16][11]={{1,-1,4,-1,5,-1,-1,-1,13,7,8},{-1,2,-1,101,-1,101,101,101,-1,-1,-1},{3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},{-1,-1,-1,102,-1,102,102,102,-1,-1,-1},{1,-1,4,-1,5,-1,-1,-1,11,7,8},{1,-1,4,-1,5,-1,-1,-1,6,7,8},{-1,-1,-1,104,-1,9,10,104,-1,-1,-1},{1,-1,4,-1,5,-1,-1,-1,14,7,8},{1,-1,4,-1,5,-1,-1,-1,15,7,8},{105,-1,105,-1,105,-1,-1,-1,-1,-1,-1},{107,-1,107,-1,107,-1,-1,-1,-1,-1,-1},{-1,-1,-1,12,-1,9,10,-1,-1,-1,-1},{-1,-1,-1,103,-1,103,103,103,-1,-1,-1},{-1,-1,-1,-1,-1,9,10,ACC,-1,-1,-1},{-1,-1,-1,106,-1,9,10,106,-1,-1,-1},{-1,-1,-1,108,-1,9,10,108,-1,-1,-1}};/********************从文件读一行到缓冲区**********************/ readline()//读一行{char ch1;pline=line;ch1=fgetc(cfile);//从文件中取一个while((ch1!='\n')&&(ch1!=EOF))//把字符缓冲区填满{*pline=ch1;pline++;ch1=fgetc(cfile);}*pline='\0';//结尾终结符pline=line;//字符缓冲区指针重新回到字符缓冲区的第一个字符位置}/**********************从缓冲区读取一个字符*********************/ readch()//读一个{if(ch=='\0')//读到尾姐再来一行,行数加一{readline();lnum++;}ch=*pline;//从行缓冲区读取一个字符pline++;//字符缓冲区指针后移}/***********************标识符和关键字的识别********************/ find(char spel[])//在变量表中查询{int ss1=0;// 是否查到的变量的标志(1为查到,0为没查到)int ii=0;//记录查到变量表第几条while((ss1==0)&&(ii<nlength))//只要没有查到,或没有超过变量表表长,就继续查{if(!strcmp(spel,ntab1[ii]))ss1=1;ii++;}if(ss1==1)//查到了return ii-1;//返回在表量表的地址(-1的原因是上面的ii++最后多加了一次)else return -1;//没查到,返回-1}identifier()//关键字或变量或常量查询{int iii=0,j,k;//iii关键字表中的指针位置int ss=0;//关键字是否匹配到的标识k=0;//存放的识别的字的指针(spelling[k])do//将取出的字符放入识别的字 spelling数组中{spelling[k]=ch;k++;readch();//取一个字符}while(((ch>='a')&&(ch<='z'))||((ch>='0')&&(ch<='9')));//数字或小写字母pline--;//取字时多加的一个,-1可使 *pline指向字符缓冲区行尾spelling[k]='\0';while((ss==0)&&(iii<10)){if(!strcmp(spelling,reswords[iii].sp))//在关键字表中查询ss=1;//查到标志置1iii++;}/*关键字匹配*/if(ss==1)//在关键字表中查到{buf[count].sy1=reswords[iii-1].sy;//关键字名字放入结果缓冲区}else//没查到{buf[count].sy1=ident;//将变量名置入结果缓冲区j=find(spelling);//变量表查询,查到就把变量在变量表的地址赋给j if(j==-1)//没查到就新建一个变量{buf[count].pos=tt1;//将其在变量表中的地址放入结果缓冲区中的地址栏 strcpy(ntab1[tt1],spelling);//将识别的变量名放入变量名表tt1++;nlength++;//变量名表长加一}else buf[count].pos=j;//查到后,将变量名表中变量的地址放入结果缓冲区该变量的地址栏中}count++;//指向结果缓冲区下一位置for(k=0;k<10;k++) spelling[k]=' ';//以识别的临时字符清空}/**********************数字识别*************************/number(){int ivalue=0;int digit;do{digit=ch-'0';//取出的字符转换为数字ivalue=ivalue*10+digit;//数字地址从10后开始记录readch();//取一个字符}while((ch>='0')&&(ch<='9'));buf[count].sy1=intconst;//常量名存入结果缓冲区buf[count].pos=ivalue;//该常量地址存入结果缓冲区count++;// 向结果缓冲区下一位置pline--;//指向行缓冲区尾字符}/***********************扫描主程序************************/scan(){int i;while(ch!='~')//~为程序结束符{switch(ch){case ' ':break;case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':case 'g':case 'h':case 'i':case 'j':case 'k':case 'l':case 'm':case 'n':case 'o':case 'p':case 'q':case 'r':case 's':case 't':case 'u':case 'v':case 'w':case 'x':case 'y':case 'z':identifier();break;//关键词或变量查询case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':number();break;//数字查询case '<':readch();//6种关系运算符buf[count].pos=(<=为0,<为1,>=为2,>为3,<>为4,=为5)if(ch=='=')buf[count].pos=0;else{if(ch=='>') buf[count].pos=4;else{buf[count].pos=1;pline--;}}buf[count].sy1=rop;//关系运算符名存入结果count++;//结果指针后移break;case '>':readch();if(ch=='=')else{buf[count].pos=3;pline--;}buf[count].sy1=rop;count++;break;case '(':buf[count].sy1=lparent; count++;break;case ')':buf[count].sy1=rparent; count++;break;case '#':buf[count].sy1=jinghao; count++;break;case '+':buf[count].sy1=plus;count++;break;case '-':buf[count].sy1=sub;count++;break;case '*':buf[count].sy1=times; count++;break;case '/':buf[count].sy1=div;count++;break;case ':':readch();if(ch=='=')buf[count].sy1=becomes; count++;break;case '=':buf[count].pos=5;count++;break;case ';':buf[count].sy1=semicolon;count++;break;}readch();// 取下一个字符}buf[count].sy1=-1;//结束了}/*******************************************************/readnu()//读取当前结果缓冲区的二元式存入struct aa n中,pbuf指向结果缓冲区中下一位置的指针{if(pbuf->sy1>=0){n.sy1=pbuf->sy1;//存放当前二元式字符名称n.pos=pbuf->pos;//存放当前二元式字符位置pbuf++;}}/***********************中间变量的生成*********************/ newtemp()//返回目前临时变量数{newt++;//临时变量计数器+1return newt;}/***********************生成四元式**************************/gen(char op1[],struct aa arg11,struct aa arg22,int result1)//op1算符,arg11操作数1,arg22操作数2, result1结果{strcpy(fexp[nxq].op,op1);//为四元式传入算符fexp[nxq].arg1.sy1=arg11.sy1;//为四元式操作数1传入名字fexp[nxq].arg1.pos=arg11.pos;// 为四元式操作数1传入地址fexp[nxq].arg2.sy1=arg22.sy1;//为四元式操作数2传入名字fexp[nxq].arg2.pos=arg22.pos;// 为四元式操作数2传入地址fexp[nxq].result=result1;// 为四元式结果传入结果nxq++;//每次指向下一个要生成的四元式地址return nxq-1;//当前四元式地址}/***********************布尔表达式的匹配**********************/merg(int p1,int p2)// 将链首“指针”分别为p1和p2的两条链合并为一条,并返回新链的链首“指针”(此处的“指针”实际上是四元式的序号,应为整型值){int p;if(p2==0) return p1;else{p=p2;while(fexp[p].result!=0)p=fexp[p].result;fexp[p].result=p1;return p2;}}backpatch(int p,int t)//用四元式序号t回填以p为首的链,将链中每个四元式的Result域改写为t的值。