新版编译原理第一次实验报告1614010102曹妍课件.doc
编译原理 实验报告
编译原理实验报告编译原理实验报告引言编译原理是计算机科学中的重要课程,它研究的是如何将高级语言程序转化为机器语言程序的过程。
在本次实验中,我们学习了编译原理的基本概念和技术,并通过实践来加深对这些概念和技术的理解。
本报告将对我们在实验中遇到的问题、解决方案以及实验结果进行总结和分析。
实验目的本次实验的主要目的是设计并实现一个简单的编译器,能够将类C语言的源代码翻译成目标代码。
通过这个实验,我们可以更好地理解编译器的工作原理,掌握编译器设计的基本方法和技术。
实验过程在实验中,我们首先对给定的类C语言的语法进行了分析,并根据语法规则设计了相应的语法分析器。
然后,我们使用了自顶向下的递归下降分析法来实现语法分析器。
在实现语法分析器的过程中,我们遇到了一些问题,例如如何处理语法规则中的左递归、如何处理语法规则中的优先级和结合性等。
通过仔细研究相关的文献和资料,我们成功地解决了这些问题,并完成了语法分析器的设计和实现。
接下来,我们对语法分析器进行了测试,并对测试结果进行了分析。
通过测试,我们发现语法分析器在处理简单的源代码时能够正确地识别出语法错误,并给出相应的错误提示。
然而,在处理复杂的源代码时,语法分析器可能会出现一些错误,例如无法正确地处理嵌套的语法结构、无法正确地处理运算符的优先级和结合性等。
为了解决这些问题,我们对语法分析器进行了改进,并进行了多次测试,最终得到了令人满意的结果。
实验结果通过本次实验,我们成功地设计并实现了一个简单的编译器,能够将类C语言的源代码翻译成目标代码。
在实验中,我们对编译器的工作原理有了更深入的了解,掌握了编译器设计的基本方法和技术。
同时,我们也发现了一些问题,并通过不断地改进和测试,最终得到了令人满意的结果。
结论编译原理是一门重要的计算机科学课程,它研究的是如何将高级语言程序转化为机器语言程序的过程。
通过本次实验,我们对编译原理的基本概念和技术有了更深入的了解,并通过实践来加深了对这些概念和技术的理解。
《编译原理》实验指导及报告书(新)课件
《编译原理》实验指导及报告书 / 学年第学期姓名:______________学号:______________班级:______________指导教师:______________计算机科学与工程学院2016编译原理实验初步一、实验目的1、熟练掌握使用CODEBLOCK进行C程序编程,提高阅读程序与调试程序的能力。
2、掌握堆栈与队列的应用。
3、掌握C语言中对字符串处理的常见函数与方法。
4、熟悉编程规范,养成对重要的程序段进行必要的注释说明。
二、实验内容与步骤1、下面的程序是对一个简单的算术表达式进行计算求值,并输出表达式的值与该表达式的后缀形式。
该程序在求值与转换后缀形式时使用了2个堆栈和1个队列。
请认真阅读程序和调试,并将程序补充完整。
#include<stdio.h>#include<malloc.h>#include<string.h>#define ERROR 0#define OK 1#define STACK_INT_SIZE 10 /*存储空间初始分配量*/#define Queue_Size 20typedef int ElemType; /*定义元素的类型*/typedef struct{char Qdata[Queue_Size];int front,rear;}SeqQueue;typedef struct{ElemType *base;ElemType *top;int stacksize; /*当前已分配的存储空间*/}SqStack;SqStack OPTR, OPND;SeqQueue SeQ;char PreTab[7][7]={{'>','>','<','<','<','>','>'},{'>','>','<','<','<','>','>'},{'>','>','>','>','<','>','>'},{'>','>','>','>','<','>','>'},{'<','<','<','<','<','=','x'},{'>','>','>','>','x','>','>'},{'<','<','<','<','<','x','='}}; // 该矩阵中,X字符表示不存在优先关系,在分析过程查找到这个值,表示表达式有错。
编译原理实验报告(C语言)
编译原理实验报告实验项目1:词法分析程序实验一、实验的目的与任务:编译原理是计算机类专业特别是计算机软件专业的一门重要专业课。
设置该课程的目的在于系统地向学生讲述编译系统的结构、工作流程及编译程序各组成部分的设计原理和实现方法,使学生通过学习既掌握编译理论和方法方面的基本知识,也具有设计、实现、分析和维护编译程序等方面的初步能力。
编译原理是一门理论性和实践性都比较强的课程。
进行上机实验的目的是使学生通过完成上机实验题目加深对课堂教学内容的理解。
同时培养学生实际动手能力。
编译实验由三个独立实验组成,按照由浅入深进行排列,希望通过本实验使学生更深学习并理解编译的主要过程和相关方法。
词法分析的目的是将输入的源程序进行划分,给出基本符号(token)的序列,并掠过注解和空格等分隔符号。
基本符号是与输入的语言定义的词法所规定的终结符。
本实验要求学生编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。
并依次输出各个单词的内部编码及单词符号自身值。
(遇到错误时可显示“Error”,然后跳过错误部分继续进行)二、题目分析1.这里采用C语言编写的源程序作为词法分析程序的输入数据,输入数据保存在“in.txt”记事本中,将分析结果存在“out.txt”记事本中。
词法分析器的源代码使用C语言编写。
2.下面就词法分析程序中的主要变量进行说明:主函数main():打开要分析的C语言源程序,若不能正确打开,则报错。
先从源程序中读入一个字符ch,然后进行如下处理:1、cp消耗掉空格,制表符,换行符后,cp数组复位,开始检测cp;2、数字检测,对照符号表输出,若匹配成功,则返回序号;3、字符串检测, 对照符号表输出,若匹配成功,则返回序号;4、基本保留字检测,对照符号表输出,若匹配成功,则返回序号;5、运算符检测,对照符号表输出,若匹配成功,则返回序号;注意这里碰到‘/’时,要判断后面是否跟着是注释语句。
编译原理实验报告
编译原理实验报告一、实验概述本次实验旨在设计并实现一个简单的词法分析器,即实现编译器的第一个阶段,词法分析。
词法分析器将一段源程序代码作为输入,将其划分为一个个的词法单元,并将其作为输出。
二、实验过程1.设计词法规则根据编程语言的规范和所需实现的功能,设计词法规则,以明确规定如何将源程序代码分解为一系列的词法单元。
2.实现词法分析器采用合适的编程语言,根据所设计的词法规则,实现词法分析器。
词法分析器的主要任务是读入源程序代码,并将其根据词法规则进行分解,生成对应的词法单元。
3.测试词法分析器设计测试用例,用于检验词法分析器的正确性和性能。
测试用例应包含各种情况下的源程序代码。
4.分析和修正错误根据测试过程中发现的问题,分析产生错误的原因,并进行修正。
重复测试和修正的过程,直到词法分析器能够正确处理所有测试用例。
三、实验结果我们设计了一个简单的词法分析器,并进行了测试。
测试用例涵盖了各种情况下的源程序代码,包括正确的代码和错误的代码。
经过测试,词法分析器能够正确处理所有的测试用例。
词法分析器将源程序代码分解为一系列的词法单元,每个词法单元包含了单词的种类和对应的值。
通过对词法单元的分析,可以进一步进行语法分析和语义分析,从而完成编译过程。
四、实验总结通过本次实验,我深入了解了编译原理的词法分析阶段。
词法分析是编译器的第一个重要阶段,它将源程序代码分解为一个个的词法单元,为后续的语法分析和语义分析提供基础。
在实现词法分析器的过程中,我学会了如何根据词法规则设计词法分析器的算法,并使用编程语言实现词法分析器。
通过测试和修正,我掌握了调试和错误修复的技巧。
本次实验的经验对我今后的编程工作有很大帮助。
编译原理是计算机科学与技术专业的核心课程之一,通过实践能够更好地理解和掌握其中的概念和技术。
我相信通过进一步的学习和实践,我能够在编译原理领域取得更大的成果。
编译原理实验报告
编译原理实验报告编译原理实验报告一、实验目的1. 了解编译器的基本原理和工作过程;2. 掌握编译器设计和实现的基本方法和技巧;3. 通过设计和实现一个简单的编译器,加深对编程语言和计算机系统的理解和认识。
二、实验原理编译器是将高级语言程序翻译成机器语言程序的一种软件工具。
它由编译程序、汇编程序、链接程序等几个阶段组成。
本次实验主要涉及到的是编译程序的设计和实现。
编译程序的基本原理是将高级语言程序转换为中间代码,再将中间代码转换为目标代码。
整个过程可以分为词法分析、语法分析、语义分析、代码生成和代码优化几个阶段。
三、实验内容本次实验的设计目标是实现一个简单的四则运算表达式的编译器。
1. 词法分析根据规定的语法规则,编写正则表达式将输入的字符串进行词法分析,将输入的四则运算表达式划分成若干个单词(Token),例如:运算符、操作数等。
2. 语法分析根据定义的语法规则,编写语法分析程序,将词法分析得到的Token序列还原成语法结构,构建抽象语法树(AST)。
3. 语义分析对AST进行遍历,进行语义分析,判断表达式是否符合语法规则,检查语义错误并给出相应的提示。
4. 代码生成根据AST生成目标代码,目标代码可以是汇编代码或者机器码。
四、实验过程和结果1. 首先,根据输入的表达式,进行词法分析。
根据所定义的正则表达式,将输入的字符串划分成Token序列。
例如:输入表达式“2+3”,经过词法分析得到的Token序列为["2", "+", "3"]。
2. 然后,根据语法规则,进行语法分析。
根据输入的Token序列,构建抽象语法树。
3. 接着,对抽象语法树进行语义分析。
检查表达式是否符合语法规则,给出相应的提示。
4. 最后,根据抽象语法树生成目标代码。
根据目标代码的要求,生成汇编代码或者机器码。
五、实验总结通过本次实验,我对编译器的工作原理有了更深入的认识,掌握了编译器设计和实现的基本方法和技巧。
编译原理实验报告
编译原理实验报告实验⼀词法分析器的设计与实现 (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)实验⽬的掌握⾃上⽽下语法分析⽅法、⾃下⽽上语法分析⽅法分析思路。
编译原理实验报告文档
《编译原理》实验报告
专业班级:计101班
学号:109074002
姓名:卞恩会
指导老师:王森玉
实验内容:
1.求出每个非终结符的FIRST集合
2.求出每个产生式右部的FIRST集合
3.求出每个非终结符的Follow集合实验环境:
Visual Studio2010
实验目的:
掌握FIRST集合和FOLLOW集合的求法
测试数据1:
S->aH
H->aMd|d
M->Ab|@
A->aM|e
输出结果:
测试数据2:S->AB
S->bC
A->@
A->b
B->@
B->aD
C->AD
C->b
D->aS
D->c
测试数据3:E->TX
X->+TX|@ T->FY
Y->*FY|@ F->i|(E)
输出结果:
感受:通过上机调试代码让我对书上的单纯的理论的知识有了一个更深的理解同时让我明白了对待一个问题我们应该全面的去理解它,这样才能学到的更多。
程序清单:。
《编译原理》课程(词法分析)实验报告
一. 实验序号:《编译原理》第一次实验二. 实验题目:词法分析三. 实验日期:2010.10四. 实验环境(操作系统,开发语言)操作系统:Windows开发语言:C五. 实验内容(实验要求)a)将标识符的词法改为“以大写字母或小写字母开头,后面可以跟大写字母或小写字母或数字或下划线”。
b)将<条件>中的表示相等关系的单词“=”改为“= =”c)将原来的无小数的数改为可以有小数的数六. 实验步骤a)打开VC++,找到getsym()项目。
int getsym(){...}在getsym()函数中设置断点,F10逐过程调试根据要求a修改为if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z')往后面看,修改while(ch>='a' && ch<='z' || ch>='0' && ch<='9' || ch>='A' && ch<='Z' || ch=='_');b)在检测赋值符号的程序段中找到等号 = 的判断代码,改变成为 = = 即可。
c)在获取整数数字的值的程序段后面添加判断小数点的代码。
如果是,即读取符号并且按照小数的要求将其缩小并且累加到总的符号串中。
七. 实验体会(包括收获、心得体会、存在的问题及解决问题的方法、建议等)通过实验,如果要修改代码的话,首先应该读懂源码,在修改之前了解到程序段的功能是什么,然后再在相应的行进行修改添加,再进行合理的调试。
如果问题太过困难可以查询资料或与同学进行讨论八. 实验结果(关键源程序)a)int getsym(){int i,j,k;while(ch==' '||ch==10||ch==9) /*忽略空格,换行和TAB*/{getchdo;}if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z')/*名字或保留字以a..z A。
编译原理实验报告一
洛阳理工学院实验报告本次实验比较复杂,通过查阅网上资料并且修改完成了本次的实验,此次实验难度在于修改的问题,每一个字符都对应一个数字。
这次实验最大的收获就是掌握了词法分析器的实现。
也让我又熟悉了一遍C语言的相关内容。
对编译原理这门课有了#include<conio.h>#include<math.h>#include<string.h>#include<stdlib.h>int i, row = 0, line = 0;char a[1000]; //程序int number[1000][100]; //常数表char mark[100][5]; //标识符表char buffer[100];//保存文件void savefile(FILE *fp1,char outfile[15]){fp1 = fopen(outfile, "a+");fseek(fp1, 0, SEEK_END);fwrite(buffer, strlen(buffer), 1, fp1);fclose(fp1);}//词法分析int wordanalysis(FILE *fp1,char outfile[15]){if ((a[i] >= 'A'&&a[i] <= 'Z')||(a[i]>='a'&&a[i]<='z')) //分析标识符和关键字{char word[10];char pro[100][100] = {"if","else","int","char","for","while","do","return","break","continue","double","float"}; //13个关键字表int n = 0;word[n++] = a[i++];//若字符为A~Z或0~9,则继续读取while ((a[i] >= 'A'&&a[i] <= 'Z') ||(a[i]>='a'&&a[i]<='z')|| (a[i] >= '0' && a[i] <= '9')){word[n++] = a[i++];}word[n] = '\0';i--;//判断该标识符是否为关键字for (n = 0; n < 100; n++){if (strcmp(word, pro[n]) == 0){sprintf(buffer,"(%d,%s) 关键字\n",n+1,pro[n]);savefile(fp1,outfile);printf("(%d,%s) 关键字\n", n + 1,pro[n]);return 3;}}//判断标识符长度是否超出规定if (strlen(word)>10){sprintf(buffer,"%s\tERROR\n",word);savefile(fp1,outfile);printf("%s\tERROR\n",word);return 0;}//判断该标识符是否存在标识符表中int m = 0;if (line != 0){int q = 0; //标识符编号while (q<line){if (strcmp(word, mark[q++]) == 0){sprintf(buffer,"(14,%s) 标识符\n", word);savefile(fp1,outfile);printf("(14,%s) 标识符\n", word);return 3;}}}//将该标识符保存到标识符表中strcpy(mark[line], word);sprintf(buffer,"(14,%s) 标识符\n", word);savefile(fp1,outfile);printf("(14, %s) 标识符\n", word);line++;return 3;}else if (a[i] >= '0' && a[i] <= '9') //分析常数,单词种别码是14 {char x[100];int n = 0;double sum;x[n++] = a[i++];//判断字符是否是0~9while (a[i] >= '0' && a[i] <= '9'){x[n++] = a[i++];}x[n] = '\0';i--;int num = atoi(x); //将字符串转换成int型//判断该常数是否存在于常数表中if (row != 0){int y; //常数编号for (y = 0; y < 1000; y++){int w = number[y][0];sum = 0;int d;for (d = 1; d <= number[y][0]; d++){w = w - 1;sum = sum + number[y][d] * pow(2, w);}if (num == sum){sprintf(buffer,"(15,%d) 常数\n", num);savefile(fp1,outfile);printf("(15,%d) 常数\n", num);return 3;}}}int z = num, c = num;int m = 0;do //计算是几位二进制数{z = z / 2;m++;} while (z != 0);for (n = m; n > 0; n--) //将二进制保存于常数表中{number[row][n] = c % 2;c = c / 2;}number[row][0] = m;int line = row;sprintf(buffer,"(15,%d) 常数\n", num);savefile(fp1,outfile);printf("(15,%d) 常数\n", num, line + 1);row++;return 3;}else //分析符号switch (a[i]){case ' ':case '\n': return -1;case '#': return 0;//分析运算符+:16; -:17; *:18; /:19; =:20; <:21; >:22; <=:23; >=:24; !=:25 case '+':if(1==1){sprintf(buffer,"(16,+) 运算符\n");savefile(fp1,outfile);printf("(16,+)\t运算符\n"); return 3;}case '-':if(1==1){sprintf(buffer,"(17,-) 运算符\n");savefile(fp1,outfile);printf("(17,-)\t运算符\n"); return 3;}case '*':if(1==1){sprintf(buffer,"(18,-) 运算符\n");savefile(fp1,outfile);printf("(18,*)\t运算符\n"); return 3;}case '=':if(1==1){sprintf(buffer,"(20,=) 运算符\n");savefile(fp1,outfile);printf("(20,=)\t运算符\n"); return 3;}case '/':i++;if(a[i]!='/'){i--;if(1==1){sprintf(buffer,"(19,/) 运算符\n");savefile(fp1,outfile);printf("(19,/)\t运算符\n"); return 3;}}else{while(1){if(a[i++]=='\n')return -1;}if(1==1){sprintf(buffer,"(41,//)\n");savefile(fp1,outfile);printf ("(41,//)\t界符\n");return 3;}}case '<':case '>':case '<=':case '>=':case '!=':i++;if(a[i] == '<'){if(1==1){sprintf(buffer,"(21,<) 运算符\n");savefile(fp1,outfile);printf("<>(21,<)\t运算符\n");return 3;}}else if (a[i] == '>'){if(1==1){sprintf(buffer,"(22,>) 运算符\n");savefile(fp1,outfile);printf("<>(22,>)\t运算符\n");return 3;}}else if (a[i] == '<='){if(1==1){sprintf(buffer,"(23,<=) 运算符\n");savefile(fp1,outfile);printf("<>(23,<=)\t运算符\n");return 3;}}else if (a[i] == '>='){if(1==1){sprintf(buffer,"(24,>=) 运算符\n");savefile(fp1,outfile);printf("<>(24,>=)\t运算符\n");return 3;}}else if (a[i] == '!='){if(1==1){sprintf(buffer,"(25,!=) 运算符\n");savefile(fp1,outfile);printf("<>(25,!=)\t运算符\n");return 3;}}else{printf("<>(ERROR)\n");return 0;}//分析界符case '(':if(1==1){sprintf(buffer,"(26,() 界符\n");savefile(fp1,outfile);printf("(26,()\t界符\n"); return 3;} case ')':if(1==1){sprintf(buffer,"(27,)) 界符\n");savefile(fp1,outfile);printf("(27,))\t界符\n"); return 3;} case '{':if(1==1){sprintf(buffer,"(28,{) 界符\n");savefile(fp1,outfile);printf("(28,{)\t界符\n"); return 3;} case '}':if(1==1){sprintf(buffer,"(29,}) 界符\n");savefile(fp1,outfile);printf("(29,})\t界符\n"); return 3;} case '[':if(1==1){sprintf(buffer,"(30,[) 界符\n");savefile(fp1,outfile);printf("(30,[)\t界符\n"); return 3;} case ']':if(1==1){sprintf(buffer,"(31,]) 界符\n");savefile(fp1,outfile);printf("(31,])\t界符\n"); return 3;} case '|':if(1==1){sprintf(buffer,"(32,|) 界符\n");savefile(fp1,outfile);printf("(32,|)\t界符\n"); return 3;} case '"':if(1==1){sprintf(buffer,"(33,\") 界符\n");savefile(fp1,outfile);printf("(33,\")\t界符\n"); return 3;} case ',':if(1==1){sprintf(buffer,"(34,,) 界符\n");savefile(fp1,outfile);printf("(34,,)\t界符\n"); return 3;} case '\'':if(1==1){sprintf(buffer,"(35,') 界符\n");savefile(fp1,outfile);printf("(35,')\t界符\n"); return 3;}case ';':if(1==1){sprintf(buffer,"(36,;) 界符\n");savefile(fp1,outfile);printf("(36,;)\t界符\n"); return 3;}case ':':if(1==1){sprintf(buffer,"(37,:) 界符\n");savefile(fp1,outfile);printf("(37,:)\t界符\n"); return 3;}case '&':i++;if(a[i]!='&'){i--;if(1==1){sprintf(buffer,"(38,&) 界符\n");savefile(fp1,outfile);printf("(38,&)\t分隔符\n"); return 3;}}else{if(1==1){sprintf(buffer,"(39,&&) 界符\n");savefile(fp1,outfile);printf("(39,&&)\t分隔符\n");return 3;} }case '\\':if(1==1){sprintf(buffer,"(40,\\) 界符\n");savefile(fp1,outfile);printf("(40,\\)\t界符\n"); return 3;} }return 0;}int main(){int l = 0;int m;i = 0;FILE *fp,*fp1;char infile[15],outfile[15]; //定义输入和输出文件名printf("输入需要扫描的文件名\n");scanf("%s",infile);printf("输入需要另存为的文件名\n");scanf("%s",outfile);if((fp = fopen(infile,"r")) == NULL) //打开需要扫描的文件{printf("cannot open file\n");exit(0);}if((fp1 = fopen(outfile,"w")) == NULL) //打开需要存入的文件{printf("cannot open file\n");exit(0);}printf ("\n");while (!feof(fp)){a[l++] = fgetc(fp);}a[l] = '#';do{m = wordanalysis(fp1,outfile);switch (m){case -1:i++; break;case 0: i++; break;case 3: i++; break;}} while (m != 0);_getch();return 0;}。
编译原理实验报告
编译原理实验报告一、实验目的编译原理是计算机科学中的重要课程,旨在让学生了解编译器的基本工作原理以及相关技术。
本次实验旨在通过设计和实现一个简单的编译器,来进一步加深对编译原理的理解,并掌握实际应用的能力。
二、实验环境本次实验使用了Java编程语言及相关工具。
在开始实验前,我们需要安装Java JDK并配置好运行环境。
三、实验内容及步骤1. 词法分析词法分析是编译器的第一步,它将源代码分割成一系列词法单元。
我们首先实现一个词法分析器,它能够将输入的源代码按照语法规则进行切割,并识别出关键字、标识符、数字、运算符等。
2. 语法分析语法分析是编译器的第二步,它将词法分析得到的词法单元序列转化为语法树。
我们使用自顶向下的LL(1)语法分析算法,根据文法规则递归地构建语法树。
3. 语义分析语义分析是编译器的第三步,它对语法树进行检查和转换。
我们主要进行类型检查、语法错误检查等。
如果源代码存在语义错误,编译器应该能够提供相应的错误提示。
4. 代码生成代码生成是编译器的最后一步,它将经过词法分析、语法分析和语义分析的源代码翻译为目标代码。
在本次实验中,我们将目标代码生成为Java字节码。
5. 测试与优化完成以上步骤后,我们需要对编译器进行测试,并进行优化。
通过多个测试用例的执行,我们可以验证编译器的正确性和性能。
四、实验心得通过完成这个编译器的实验,我收获了很多。
首先,我对编译原理的知识有了更深入的理解。
在实验过程中,我深入学习了词法分析、语法分析、语义分析和代码生成等关键技术,对编译器的工作原理有了更系统的了解。
其次,我提高了编程能力。
实现一个完整的编译器需要处理复杂的数据结构和算法,这对我的编程能力是一个很好的挑战。
通过实验,我学会了合理地组织代码,优化算法,并注意到细节对程序性能的影响。
最后,我锻炼了解决问题的能力。
在实验过程中,我遇到了很多困难和挑战,但我不断地调试和改进代码,最终成功地实现了编译器。
编译原理实验报告
编译原理实验报告一、实验目的本次实验的目的是了解编译原理的基本知识,并运用所学知识实现一个简单的词法分析器。
二、实验内容1.设计一个词法分析器,能够识别并输出源程序中的关键字、标识符、常数和运算符等。
2.设计并实现一个词法分析器的算法。
3.对编写的词法分析器进行测试。
三、实验过程1.设计词法分析器的算法在设计词法分析器的时候,需要先了解源程序的基本构成,了解关键字、标识符、常数和运算符等的特点,以及它们在源程序中的表示形式。
然后,根据这些特点,设计一个适合的算法来进行词法分析。
2.实现词法分析器根据设计好的算法,在编程语言中实现词法分析器。
在实现过程中,需要根据不同的词法单元,设计相应的正则表达式来进行匹配和识别。
3.测试词法分析器编写几个简单的测试用例,对词法分析器进行测试。
检查输出结果是否正确,并根据实际情况对词法分析器进行调试和优化。
四、实验结果经过测试,词法分析器能够正确识别并输出源程序中的关键字、标识符、常数和运算符等。
测试用例的输出结果与预期结果一致。
五、实验总结通过本次实验,我学习了编译原理的基本知识,掌握了词法分析器的设计和实现方法。
在实验过程中,我遇到了一些困难和问题,但通过仔细思考和查阅文献资料,最终成功地完成了实验任务。
这次实验不仅帮助我巩固了所学知识,还提高了我的编程能力和解决问题的能力。
通过实践,我深刻体会到了编译原理在软件开发中的重要性和作用,并对将来的学习和工作有了更好的规划和方向。
通过本次实验,我对编译原理的相关知识有了更深入的理解和掌握,对词法分析器的设计和实现方法有了更加清晰的认识。
同时,我还学会了如何进行实验报告的撰写,提高了我的文档写作能力。
通过本次实验,我不仅实现了实验的目标,还提高了自己的综合素质和能力。
编译原理实验报告(一)----词法分析程序
结束
是 转关键字和标识符处理
是 转数字处理
是 转运算符处理
)[p--8]
{[p--23] char[k--0] ch[i--5] ;[p--13]
关闭所有文件
下面简要分析一下词法分析程序的运行流程:
能否打开所要编译的 C 语言文 件
能
判断当前字符是否是文件结束符
否
报错 是
否
是
从源判程断序当中前读字入符一是行否到是数’组\n缓’ 冲区
否
判断当前字符是否是字母
否 判断当前字符是否是数字
否 判断当前字符是否是运算符
否
【程序调试】 现有源程序 a.c 清单如下: #include <stdio.h> int main(int argc, char *argv[]) {char ch; int i; ch='a'; ch=ch+32 ; i=ch; printf("%d id %c\n",i,ch);/*打印*/ return 0; } 运行词法分析程序后,显示如下结果: after_com.txt 文件: #[p--2] include[i--0] <[p--14] stdio.h[i--1] >[p--16]
"fclose","exit","r","read","close","w","fprintf"};
编译原理上机实验报告
编译原理上机实验报告一、实验目的本次实验旨在通过实践的方式理解和掌握编译原理中的一些重要概念和技术,包括词法分析、语法分析和语义分析等。
通过实验的操作,了解和体验编译器的工作过程,深入理解编译原理的相关理论知识。
二、实验环境本次实验使用了Java语言作为编程语言,使用Eclipse作为开发环境,实验所需的相关工具和库已经提前配置完成。
三、实验内容本次实验主要分为三个部分,分别是词法分析、语法分析和语义分析。
1.词法分析词法分析是编译器的第一个阶段,也是最基础的阶段。
在本次实验中,我们首先需要实现一个词法分析器,该分析器可以将源代码分割成一个个的词法单元,将其存储到一个词法单元表中。
我们首先需要定义一些词法单元的模式,比如关键字、标识符、常量等。
然后,我们使用正则表达式和有限自动机的思想来实现一个可以识别各种模式的词法分析器。
2.语法分析语法分析是编译器的第二个阶段,其目的是将词法单元表中的内容按照语法规则进行分析,生成一个语法树。
在本次实验中,我们需要实现一个递归下降的语法分析器。
我们首先需要定义一些语法规则,然后根据这些规则逐条实现相应的语法分析函数。
最终,我们可以通过递归调用这些函数,将源代码转换成语法树的形式。
3.语义分析语义分析是编译器的第三个阶段,其目的是对语法树进行进一步的检查和处理。
在本次实验中,我们需要实现一个简单的语义分析器。
我们可以在语法分析的基础上,增加一些语义规则,然后对生成的语法树进行检查。
比如,我们可以检查变量的定义和使用是否一致,是否存在未定义的变量等。
最终,我们可以通过语义分析器发现和纠正一些潜在的错误。
四、实验总结通过本次实验,我深入学习了编译原理的相关知识,并通过实践中加深了对这些知识的理解和掌握。
实验中,我了解到了词法分析、语法分析和语义分析在编译器设计中的重要性,也学会了如何使用相关工具和技术来实现这些功能。
通过实验,我发现编译原理是一门非常有趣且实用的课程,它既涉及到理论知识,又需要实践操作。
编译原理教程实验报告
一、实验目的本次实验旨在使学生通过编译原理的学习,了解编译程序的设计原理及实现技术,掌握编译程序的各个阶段,并能将所学知识应用于实际编程中。
二、实验内容1. 词法分析2. 语法分析3. 语义分析4. 中间代码生成5. 代码优化6. 目标代码生成三、实验步骤1. 词法分析(1)设计词法分析器,识别输入源代码中的各种词法单元;(2)使用C语言实现词法分析器,并进行测试。
2. 语法分析(1)根据文法规则设计语法分析器,识别输入源代码的语法结构;(2)使用C语言实现语法分析器,并进行测试。
3. 语义分析(1)设计语义分析器,检查语法分析后的语法树,确保语义正确;(2)使用C语言实现语义分析器,并进行测试。
4. 中间代码生成(1)设计中间代码生成器,将语义分析后的语法树转换为中间代码;(2)使用C语言实现中间代码生成器,并进行测试。
5. 代码优化(1)设计代码优化器,对中间代码进行优化,提高程序性能;(2)使用C语言实现代码优化器,并进行测试。
6. 目标代码生成(1)设计目标代码生成器,将优化后的中间代码转换为特定目标机的汇编语言;(2)使用C语言实现目标代码生成器,并进行测试。
四、实验结果与分析1. 词法分析实验结果:成功识别输入源代码中的各种词法单元,包括标识符、关键字、运算符、常量等。
2. 语法分析实验结果:成功识别输入源代码的语法结构,包括表达式、语句、程序等。
3. 语义分析实验结果:成功检查语法分析后的语法树,确保语义正确。
4. 中间代码生成实验结果:成功将语义分析后的语法树转换为中间代码,为后续优化和目标代码生成提供基础。
5. 代码优化实验结果:成功对中间代码进行优化,提高程序性能。
6. 目标代码生成实验结果:成功将优化后的中间代码转换为特定目标机的汇编语言,为程序在目标机上运行做准备。
五、实验心得1. 编译原理是一门理论与实践相结合的课程,通过本次实验,我对编译程序的设计原理及实现技术有了更深入的了解。
编译原理实验报告(一)
编译原理实验报告(一)一、实验题目:简单词法分析器的设计二、实验目的:熟悉并实现一个简单的扫描器三、实验内容:1.设计扫描器的自动机;2.设计翻译、生成Token的算法;3.编写代码并上机调试运行通过。
要求:输入——源程序文件;输出——(1)相应的Token序列;(2)关键字、界符表,符号表,常数表。
四、扫描器设计:自动机:关键字表和界符表单词编码program 3procedure 4④-begin 5end 6while 7do 8+ 9* 10⑧-:11:= 12⑨-= 13,14;15五、概要设计:(1)各模块概要设计1.判断当前读入的字符是字母还是数字int IsLetter(char ch) //判断ch是否为字母 { if (ch是A~Z或a~z) return 1;else return 0;}int IsDigit(char ch) //判断ch是否为数字{ if (ch是0~9) return 1;else return 0;}2.将读入的字符连接成单词或数while (IsLetter(ch)||IsDigit(ch)){ Concat(); //将ch中的字符拼接到strToken中ch=GetChar();}3.查表判断当前的独立串是关键字、标示符还是常数4.求出当前的独立串的code 和value(2)程序说明:1、关键字表、界符表和常数表中初始化后都有元素,即都不是空表。
而符号表则是空的。
它用来存放用户自己定义的变量名,按输入的被识别串中的顺序依次标识其value的值的1,2,3,……,n。
2、value=-1用来标识它是一个关键字;value=1用来标识它是一个界符常数的code值一定为2六、程序源代码及注释:#include "stdio.h"#include "string.h"#define N 15struct TokenType{ int code,value; };char*keywords[]={"program","procedure","begin","end","while","do","+","*",":",":=","=",",",";","(",")",}; //关键字表、界符表char ID[10][10]; //符号表int m;int Cons[10]; //常数表int n;void print(struct TokenTykpe token) //输出Token{ printf("( %d %d)\n",token.code,token.value);}void ProcError(){ printf("Error! You haven't defined it!");}int IsLetter(char ch) //判断ch是否为字母¸{ if (ch>='A' && ch<='Z' || ch>='a' && ch<='z')return 1; else return 0;}int IsDigit(char ch) //判断ch是否为数字{ if (ch>='0' && ch<='9') return 1;else return 0;}int Reserve(char *strToken) //用strToken中的单词去查关键字表。
编译原理第一次实验报告1614010102曹妍
哈尔滨理工大学软件与微电子学院实验报告(2017-2018第二学期)课程名称:编译原理班级:软件16-1班学号: 02姓名:曹妍一、实验目的:通过设计编制调试构造FIRSTVT集、LASTVT集和构造算符优先表,了解构造算符优先分析表的步骤,对文法的要求,生成算符优先关系表的算法。
二、实验内容:1.编写算符优先分析表的构造程序,求出给定的算符优先文法中的非终结符的FirstVT集合和LastVT集合。
2.构造算符优先表。
三、实验设备及软件环境:PC机,主机操作系统为windows;C编译器等软件四、实验过程及结果:在存放文法的文件内输入待判断文法产生式(文件已输入教材116页文法),格式E->a|S,注意左部和右部之间是“->”,每个产生式一行,ENTER键换行。
文法结束再输入一行G->#E#。
1.先做文法判断,即可判断文法情况。
2.若是算符优先文法,则在优先表栏显示优先表。
实验样例:图中给出了终结符号表,非终结符号表,计算FirstVT和LastVT集合,并给出了算符优先关系矩阵。
代码和实验结果分析:#include <>#include <>#include <iostream>char data[20][20]; //算符优先关系char s[100]; //模拟符号栈schar lable[20]; //文法终极符集char input[100]; //文法输入符号串char string[20][10]; //用于输入串的分析int k;char a;int j;char q;int r; //文法规则个数int r1; //转化后文法规则个数char st[10][30]; //用来存储文法规则char first[10][10]; //文法非终结符FIRSTVT集char last[10][10]; //文法非终结符LASTVT集int fflag[10]= {0}; //标志第i个非终结符的FIRSTVT集是否已求出int lflag[10]= {0}; //标志第i个非终结符的LASTVT集是否已求出int deal(); //对输入串的分析int zhongjie(char c); //判断字符c是否是终极符int xiabiao(char c); //求字符c在算符优先关系表中的下标void out(int j,int k,char *s); //打印s栈void firstvt(char c); //求非终结符c的FIRSTVT集void lastvt(char c); //求非终结符c的LASTVT集void table(); //创建文法优先关系表int main(){int i,j,k=0;printf("请输入文法规则数:");scanf("%d",&r);printf("请输入文法规则:\n");for(i=0; i<r; i++){scanf("%s",st[i]); //存储文法规则,初始化FIRSTVT集和LASTVT 集first[i][0]=0; /*first[i][0]和last[i][0]分别表示st[i][0]非终极符的FIRSTVT集和LASTVT集中元素的个数*/last[i][0]=0;for(i=0; i<r; i++) //判断文法是否合法{for(j=0; st[i][j]!='\0'; j++){if(st[i][0]<'A'||st[i][0]>'Z'){printf("不是算符文法!\n");exit(-1);}if(st[i][j]>='A'&&st[i][j]<='Z'){if(st[i][j+1]>='A'&&st[i][j+1]<='Z'){printf("不是算符文法!\n");exit(-1);}}}}for(i=0; i<r; i++){for(j=0; st[i][j]!='\0'; j++){if((st[i][j]<'A'||st[i][j]>'Z')&&st[i][j]!='-'&&st[i][j]!='>'&&st[i][ j]!='|')lable[k++]=st[i][j];}lable[k]='#';lable[k+1]='\0';table();printf("每个非终结符的FIRSTVT集为:\n"); //输出每个非终结符的FIRSTVT集for(i=0; i<r; i++){printf("%c: ",st[i][0]);for(j=0; j<first[i][0]; j++){printf("%c ",first[i][j+1]);}printf("\n");}printf("每个非终结符的LASTVT集为:\n"); //输出每个非终结符的LASTVT集for(i=0; i<r; i++){printf("%c: ",st[i][0]);for(j=0; j<last[i][0]; j++){printf("%c ",last[i][j+1]);}printf("\n");}printf("算符优先分析表如下:\n");for(i=0; lable[i]!='\0'; i++)printf("\t%c",lable[i]);printf("\n");for(i=0; i<k+1; i++){printf("%c\t",lable[i]);for(j=0; j<k+1; j++){printf("%c\t",data[i][j]);}printf("\n");}printf("请输入文法输入符号串以#结束:"); scanf("%s",input);deal();}void table(){char text[20][10];int i,j,k,t,l,x=0,y=0;int m,n;x=0;for(i=0; i<r; i++){firstvt(st[i][0]);lastvt(st[i][0]);}for(i=0; i<r; i++){text[x][y]=st[i][0];y++;for(j=1; st[i][j]!='\0'; j++){if(st[i][j]=='|'){text[x][y]='\0';x++;y=0;text[x][y]=st[i][0];y++;text[x][y++]='-';text[x][y++]='>';}else{text[x][y]=st[i][j];y++;}}text[x][y]='\0';x++;y=0;}r1=x;printf("转化后的文法为:\n");for(i=0; i<x; i++) //输出转化后的文法规则串 {printf("%s\n",text[i]);}for(i=0; i<x; i++) /*求每个终结符的推导结果(去掉"->"后的转化文法,用于最后的规约)*/{string[i][0]=text[i][0];for(j=3,l=1; text[i][j]!='\0'; j++,l++)string[i][l]=text[i][j];string[i][l]='\0';}for(i=0; i<x; i++){for(j=1; text[i][j+1]!='\0'; j++){if(zhongjie(text[i][j])&&zhongjie(text[i][j+1])){m=xiabiao(text[i][j]);n=xiabiao(text[i][j+1]);data[m][n]='=';}if(text[i][j+2]!='\0'&&zhongjie(text[i][j])&&zhongjie(text[i][j+2])&& !zhongjie(text[i][j+1])){m=xiabiao(text[i][j]);n=xiabiao(text[i][j+2]);data[m][n]='=';}if(zhongjie(text[i][j])&&!zhongjie(text[i][j+1])) {for(k=0; k<r; k++){if(st[k][0]==text[i][j+1])break;}m=xiabiao(text[i][j]);for(t=0; t<first[k][0]; t++){n=xiabiao(first[k][t+1]);data[m][n]='<';}}if(!zhongjie(text[i][j])&&zhongjie(text[i][j+1])) {for(k=0; k<r; k++){if(st[k][0]==text[i][j])break;}n=xiabiao(text[i][j+1]);for(t=0; t<last[k][0]; t++){m=xiabiao(last[k][t+1]);data[m][n]='>';}}}}m=xiabiao('#');for(t=0; t<first[0][0]; t++){n=xiabiao(first[0][t+1]);data[m][n]='<';}n=xiabiao('#');for(t=0; t<last[0][0]; t++){m=xiabiao(last[0][t+1]);data[m][n]='>';}data[n][n]='=';}void firstvt(char c) //求FIRSTVT集{int i,j,k,m,n;for(i=0; i<r; i++){if(st[i][0]==c)break;}if(fflag[i]==0){n=first[i][0]+1;m=0;do{if(m==2||st[i][m]=='|'){if(zhongjie(st[i][m+1])){first[i][n]=st[i][m+1];n++;}else{if(zhongjie(st[i][m+2])){first[i][n]=st[i][m+2];n++;}if(st[i][m+1]!=c){firstvt(st[i][m+1]);for(j=0; j<r; j++){if(st[j][0]==st[i][m+1])break;}for(k=0; k<first[j][0]; k++){int t;for(t=0; t<n; t++){if(first[i][t]==first[j][k+1])break;}if(t==n){first[i][n]=first[j][k+1]; n++;}}}}}m++;}while(st[i][m]!='\0');first[i][n]='\0';first[i][0]=--n;fflag[i]=1;}}void lastvt(char c) //求LASTVT集{int i,j,k,m,n;for(i=0; i<r; i++){if(st[i][0]==c)break;}if(lflag[i]==0){n=last[i][0]+1;m=0;do{if(st[i][m+1]=='\0'||st[i][m+1]=='|') {if(zhongjie(st[i][m])){last[i][n]=st[i][m];n++;}else{if(zhongjie(st[i][m-1])){last[i][n]=st[i][m-1];n++;}if(st[i][m]!=c){lastvt(st[i][m]);for(j=0; j<r; j++){if(st[j][0]==st[i][m]) break;}for(k=0; k<last[j][0]; k++){int t;for(t=0; t<n; t++){if(last[i][t]==last[j][k+1])break;}if(t==n){last[i][n]=last[j][k+1];n++;}}}}}m++;}while(st[i][m]!='\0');last[i][n]='\0';last[i][0]=--n;lflag[i]=1;}}int deal(){int i,j;int x,y;int z; //输入串的长度k=1;s[k]='#'; //栈置初值for(i=0; input[i]!='\0'; i++); //计算输入串的长度z=i--;i=0;while((a=input[i])!='\0'){if(zhongjie(s[k]))j=k;elsej=k-1;x=xiabiao(s[j]);y=xiabiao(a);if(data[x][y]=='>'){out(1,k,s);printf("%c",a);out(i+1,z,input);printf("规约\n");do{q=s[j];if(zhongjie(s[j-1]))j=j-1;else j=j-2;x=xiabiao(s[j]);y=xiabiao(q);}while(data[x][y]!='<');int m,n,N;for(m=j+1; m<=k; m++){for(N=0; N<r1; N++)for(n=1; string[N][n]!='\0'; n++){if(!zhongjie(s[m])&&!zhongjie(string[N][n])) {if(zhongjie(s[m+1])&&zhongjie(string[N][n+1])&&s[m+1]==string[N][n+1]){s[j+1]=string[N][0];break;}}else if(zhongjie(s[m]))if(s[m]==string[N][n]){s[j+1]=string[N][0];break;}}}k=j+1;if(k==2&&a=='#'){out(1,k,s);printf("%c",a);out(i+1,z,input);printf("结束\n");printf("输入串符合文法的定义!\n");return 1; //输入串符合文法的定义}}else if(data[x][y]=='<'||data[x][y]=='='){//移进out(1,k,s);printf("%c",a);out(i+1,z,input);printf("移进\n");k++;s[k]=a;i++;}else{printf("\nflase");return 0;}}printf("\nflase");return 0;}void out(int j,int k,char *s){int n=0;int i;for(i=j; i<=k; i++){printf("%c",s[i]);n++;}for(; n<15; n++){printf(" ");}}int xiabiao(char c) //求字符c在算符优先关系表中的下标{int i;for(i=0; lable[i]!='\0'; i++){if(c==lable[i])return i;}return -1;int zhongjie(char c) //判断字符c是否是终极符{int i;for(i=0; lable[i]!='\0'; i++){if(c==lable[i])return 1;}return 0;}实验成绩:指导教师:年月日。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
哈尔滨理工大学软件与微电子学院实验报告(2017-2018 第二学期)课程名称:编译原理班级:软件16-1 班学号:1614010102 姓名:曹妍实验名称实验一、算符优先分析表的构造程序专业软件工程姓名曹妍学号1614010102 班级软件16-1 班一、实验目的:通过设计编制调试构造FIRSTVT 集、LASTVT 集和构造算符优先表,了解构造算符优先分析表的步骤,对文法的要求,生成算符优先关系表的算法。
二、实验内容:1.编写算符优先分析表的构造程序,求出给定的算符优先文法中的非终结符的FirstVT 集合和LastVT 集合。
2.构造算符优先表。
三、实验设备及软件环境:PC机,主机操作系统为windows ;C编译器等软件四、实验过程及结果:在存放文法的文件in.txt 内输入待判断文法产生式(文件已输入教材116 页文法),格式E->a|S, 注意左部和右部之间是“->”,每个产生式一行,ENTER 键换行。
文法结束再输入一行G->#E# 。
1.先做文法判断,即可判断文法情况。
2.若是算符优先文法,则在优先表栏显示优先表。
实验样例:图中给出了终结符号表,非终结符号表,计算FirstVT 和LastVT 集合,并给出了算符优先关系矩阵。
代码和实验结果分析:#include <stdio.h>#include <stdlib.h>#include <iostream>char data[20][20]; //算符优先关系char s[100]; //模拟符号栈s char lable[20]; //文法终极符集char input[100]; //文法输入符号串char string[20][10]; //用于输入串的分析int k;char a;int j;char q;int r; //文法规则个数int r1; //转化后文法规则个数char st[10][30]; //用来存储文法规则char first[10][10]; //文法非终结符FIRSTVT 集char last[10][10]; //文法非终结符LASTVT 集int fflag[10]= {0}; //标志第i 个非终结符的FIRSTVT 集是否已求出int lflag[10]= {0}; //标志第i 个非终结符的LASTVT 集是否已求出int deal(); //对输入串的分析int zhongjie(char c); //判断字符 c 是否是终极符int xiabiao(char c); //求字符c 在算符优先关系表中的下标void out(int j,int k,char *s); //打印s 栈void firstvt(char c); //求非终结符 c 的FIRSTVT 集void lastvt(char c); //求非终结符 c 的LASTVT 集void table(); //创建文法优先关系表int main(){int i,j,k=0;printf(" 请输入文法规则数:");scanf("%d",&r);printf(" 请输入文法规则:\n");for(i=0; i<r; i++){scanf("%s",st[i]); //存储文法规则,初始化FIRSTVT 集和LASTVT集first[i][0]=0; /*first[i][0] 和last[i][0] 分别表示st[i][0] 非终极符的FIRSTVT 集和LASTVT 集中元素的个数*/last[i][0]=0;}for(i=0; i<r; i++) //判断文法是否合法{for(j=0; st[i][j]!='\0'; j++){if(st[i][0]<'A'||st[i][0]>'Z'){printf(" 不是算符文法!\n");exit(-1);}if(st[i][j]>='A'&&st[i][j]<='Z'){if(st[i][j+1]>='A'&&st[i][j+1]<='Z'){printf(" 不是算符文法!\n");exit(-1);}}}}for(i=0; i<r; i++){for(j=0; st[i][j]!='\0'; j++){if((st[i][j]<'A'||st[i][j]>'Z')&&st[i][j]!='-'&&st[i][j]!='>'&&st[i][j]!='|') lable[k++]=st[i][j];}}lable[k]='#';lable[k+1]='\0';table();printf(" 每个非终结符的FIRSTVT 集为:\n"); //输出每个非终结符的FIRSTVT 集for(i=0; i<r; i++){printf("%c: ",st[i][0]);for(j=0; j<first[i][0]; j++){printf("%c ",first[i][j+1]);}printf("\n");}printf(" 每个非终结符的LASTVT 集为:\n"); //输出每个非终结符的LASTVT 集for(i=0; i<r; i++){printf("%c: ",st[i][0]);for(j=0; j<last[i][0]; j++){printf("%c ",last[i][j+1]);}printf("\n");}printf(" 算符优先分析表如下:\n"); for(i=0; lable[i]!='\0'; i++)printf("\t%c",lable[i]);printf("\n");for(i=0; i<k+1; i++){printf("%c\t",lable[i]);for(j=0; j<k+1; j++){printf("%c\t",data[i][j]);}printf("\n");}printf(" 请输入文法输入符号串以#结束:");scanf("%s",input);deal();}void table(){char text[20][10];int i,j,k,t,l,x=0,y=0;int m,n;x=0;for(i=0; i<r; i++){firstvt(st[i][0]);lastvt(st[i][0]);}for(i=0; i<r; i++){text[x][y]=st[i][0];y++;for(j=1; st[i][j]!='\0'; j++){if(st[i][j]=='|'){text[x][y]='\0';x++;y=0;text[x][y]=st[i][0];y++;text[x][y++]='-';text[x][y++]='>';}else{text[x][y]=st[i][j];y++;}}text[x][y]='\0';x++;y=0;}r1=x;printf(" 转化后的文法为:\n");for(i=0; i<x; i++) //输出转化后的文法规则串{printf("%s\n",text[i]);}for(i=0; i<x; i++) /*求每个终结符的推导结果(去掉"->" 后的转化文法,用于最后的规约)*/{string[i][0]=text[i][0];for(j=3,l=1; text[i][j]!='\0'; j++,l++)string[i][l]=text[i][j];string[i][l]='\0';}for(i=0; i<x; i++){for(j=1; text[i][j+1]!='\0'; j++){if(zhongjie(text[i][j])&&zhongjie(text[i][j+1])){m=xiabiao(text[i][j]);n=xiabiao(text[i][j+1]);data[m][n]='=';}if(text[i][j+2]!='\0'&&zhongjie(text[i][j])&&zhongjie(text[i][j+2])&&!zhongjie(text[i ][j+1])){m=xiabiao(text[i][j]);n=xiabiao(text[i][j+2]);data[m][n]='=';}if(zhongjie(text[i][j])&&!zhongjie(text[i][j+1])) {for(k=0; k<r; k++){if(st[k][0]==text[i][j+1])break;}m=xiabiao(text[i][j]);for(t=0; t<first[k][0]; t++){n=xiabiao(first[k][t+1]);data[m][n]='<';}}if(!zhongjie(text[i][j])&&zhongjie(text[i][j+1])) {for(k=0; k<r; k++){if(st[k][0]==text[i][j])break;}n=xiabiao(text[i][j+1]);for(t=0; t<last[k][0]; t++){m=xiabiao(last[k][t+1]);data[m][n]='>';}}}}m=xiabiao('#');for(t=0; t<first[0][0]; t++) {n=xiabiao(first[0][t+1]);data[m][n]='<';}n=xiabiao('#');for(t=0; t<last[0][0]; t++){m=xiabiao(last[0][t+1]);data[m][n]='>';}data[n][n]='=';}void firstvt(char c) //求FIRSTVT 集{int i,j,k,m,n;for(i=0; i<r; i++){if(st[i][0]==c)break;}if(fflag[i]==0){n=first[i][0]+1;m=0;do{if(m==2||st[i][m]=='|'){if(zhongjie(st[i][m+1])){first[i][n]=st[i][m+1];n++;}else{if(zhongjie(st[i][m+2])){first[i][n]=st[i][m+2];n++;}if(st[i][m+1]!=c){firstvt(st[i][m+1]);for(j=0; j<r; j++){if(st[j][0]==st[i][m+1])break;}for(k=0; k<first[j][0]; k++){int t;for(t=0; t<n; t++){if(first[i][t]==first[j][k+1])break;}if(t==n){first[i][n]=first[j][k+1];n++;}}}}}m++;}while(st[i][m]!='\0');first[i][n]='\0';first[i][0]=--n;fflag[i]=1;}}void lastvt(char c) //求LASTVT 集{int i,j,k,m,n;for(i=0; i<r; i++){if(st[i][0]==c)break;}if(lflag[i]==0){n=last[i][0]+1;m=0;do{if(st[i][m+1]=='\0'||st[i][m+1]=='|'){if(zhongjie(st[i][m])){last[i][n]=st[i][m];n++;}else{if(zhongjie(st[i][m-1])){last[i][n]=st[i][m-1];n++;}if(st[i][m]!=c){lastvt(st[i][m]);for(j=0; j<r; j++){if(st[j][0]==st[i][m])break;}for(k=0; k<last[j][0]; k++){int t;for(t=0; t<n; t++){if(last[i][t]==last[j][k+1])break;}if(t==n){last[i][n]=last[j][k+1];n++;}}}}}m++;}while(st[i][m]!='\0');last[i][n]='\0';last[i][0]=--n;lflag[i]=1;}}int deal(){int i,j;int x,y;int z; //输入串的长度k=1;s[k]='#'; //栈置初值for(i=0; input[i]!='\0'; i++); //计算输入串的长度z=i--;i=0;while((a=input[i])!='\0'){if(zhongjie(s[k]))j=k;elsej=k-1;x=xiabiao(s[j]);y=xiabiao(a);if(data[x][y]=='>'){out(1,k,s);printf("%c",a);out(i+1,z,input);printf(" 规约\n");do{q=s[j];if(zhongjie(s[j-1]))j=j-1;else j=j-2;x=xiabiao(s[j]);y=xiabiao(q);}while(data[x][y]!='<');int m,n,N;for(m=j+1; m<=k; m++){for(N=0; N<r1; N++)for(n=1; string[N][n]!='\0'; n++){if(!zhongjie(s[m])&&!zhongjie(string[N][n])){if(zhongjie(s[m+1])&&zhongjie(string[N][n+1])&&s[m+1]==string[N][n+1]){s[j+1]=string[N][0];break;}}else if(zhongjie(s[m]))if(s[m]==string[N][n]){s[j+1]=string[N][0];break;}}}k=j+1;if(k==2&&a=='#'){out(1,k,s);printf("%c",a);out(i+1,z,input);printf(" 结束\n");printf(" 输入串符合文法的定义!\n");return 1; //输入串符合文法的定义}}else if(data[x][y]=='<'||data[x][y]=='=') {//移进out(1,k,s);printf("%c",a);out(i+1,z,input);printf(" 移进\n");k++;s[k]=a;i++;}else{printf("\nflase");return 0;}}printf("\nflase");return 0;}void out(int j,int k,char *s){int n=0;int i;for(i=j; i<=k; i++){printf("%c",s[i]);n++;}for(; n<15; n++){printf(" ");}}int xiabiao(char c) //求字符c 在算符优先关系表中的下标{int i;for(i=0; lable[i]!='\0'; i++){if(c==lable[i])return i;}return -1;int zhongjie(char c) //判断字符 c 是否是终极符{int i;for(i=0; lable[i]!='\0'; i++){if(c==lable[i])return 1;}return 0;}实验成绩:指导教师:年月日。