电子科大-编译原理实验报告(得分80分)(共37页).doc
精选优质文档-倾情为你奉上电 子 科 技 大 学实 验 报 告学生姓名:爸爸 学 号:22 指导教师:陈昆实验地点:科研楼A-506 实验时间:2017-04-28一、实验项目名称:词法分析器的设计与实现二、实验学时:4学时三、实验原理 1.编译程序要求对高级语言编写的源程序进行分析和合成,生成目标程序。词法分析是对源程序进行的首次分析,实现词法分析的程序为词法分析程序或词法分析器,也称扫描器。2. 词法分析的功能是:从左到右逐个地扫描源程序字符串,按照词法规则,识别出单词符号作为输出,对识别过程中发现的词法错误,输出相关的错误信息。3. 识别出来的单词会采用某种中间表现形式,通常一个单词用一个二元式来表示:(单词类别,单词的属性)。4. 状态转换图简称转化图,是有限有向图,是设计词法分析器的有效工具。四、 实验目的 通过该实验,让同学们自己独立自主的设计词法分析器,使得同学们可以更好的掌握词法分析程序设计的原理及相应的程序设计方法,对编译这门课程也可以有更加深刻理解,同时还可以锻炼编程能力。五、 实验内容 实现求n!的极小语言的词法分析程序,返回二元式作为输出。六、实验器材(设备、元器件)1. 操作系统:Windows XP2. 开发工具:VS2013七、 实验步骤(1) 在VS2013中创建工程;(2) 编写输入输出,初始化,错误处理等函数;(3) 建立相应的单词符号与种别对照表,根据状态转换图编写相应的处理函数;(4) 运行代码进行调试;(5) 编写测试需要的输入文件:.pas文件;(6) 生成.dyd文件。八、 实验数据及结果分析编码完成后将测试程序放入debug文件夹中,测试程序如下图: 代码运行成功后在debug文件夹中会产生对应的exe,在cmd中运行后,会在debug文件夹中生成后缀为dyd和err的文件,打开dyd如下图所示:因为没有错误,所以对应的test1.err的文件为空 可以对源程序进行词法分析,如果有错给出出错信息和所在行数,如果无错则生成二元式文件。九、 实验结论 词法分析器的功能是:从左到右逐个的扫描源程序的字符串,按照词法规则,识别出单词符号作为输出,对识别过程中发现的词法错误,输出有关的错误信息。十、总结及心得体会 通过本次实验,即对词法分析程序的设计,锻炼了自己的编程能力,同时加深了自己对词法分析器的理解和掌握以及对待编译这门课程的理解,提高了自己的动手能力,在编码的过程中也遇到了许多问题,例如如何解决产生的文件后端对齐等等问题,让我的编码能力在此次实验中得到了一定的提高。十一、对本实验过程及方法、手段的改进建议要先了解词法分析器的功能以及输入输出形式,熟练的掌握状态转化图。 报告评分:指导教师签字:实验参考源代码如下:#include<stdio.h>#include<string.h>#include<Windows.h>#define MAX_COUNT 2048#define ILLEGAL_CHAR_ERR 1#define UNKNOWN_OPERATOR_ERR 2char getnbc()char ch;ch = getchar();while (1)if (ch = 'r' | ch = 't' | ch = ' ')ch = getchar();elsebreak;return ch;bool letter(char character)if (character >= 'a'&&character <= 'z') | (character >= 'A'&&character <= 'Z')return true;elsereturn false;bool digit(char character)if (character >= '0'&&character <= '9')return true;elsereturn false;void retract(char& character)ungetc(character, stdin);character = NULL;int reserve(char* token)if (strcmp(token, "begin") = 0)return 1;else if (strcmp(token, "end") = 0)return 2;else if (strcmp(token, "integer") = 0)return 3;else if (strcmp(token, "if") = 0)return 4;else if (strcmp(token, "then") = 0)return 5;else if (strcmp(token, "else") = 0)return 6;else if (strcmp(token, "function") = 0)return 7;else if (strcmp(token, "read") = 0)return 8;else if (strcmp(token, "write") = 0)return 9;elsereturn 0;int symbol()return 10;int constant()return 11;void output(const char* token, int kindNum)printf("%16s %2dn", token, kindNum);bool error(int lineNum, int errNum)char* errInfo;switch (errNum)case ILLEGAL_CHAR_ERR:errInfo = "出现字母表以外的非法字符"break;case UNKNOWN_OPERATOR_ERR:errInfo = "出现未知运算符"break;default:errInfo = "未知错误"if (fprintf(stderr, "*LINE:%d %sn", lineNum, errInfo) >= 0)return true;elsereturn false;bool LexAnalyze()static int lineNum = 1;char character;char token17 = ""character = getnbc();switch (character)case 'n':output("EOLN", 24);lineNum+;break;case EOF:output("EOF", 25);return false; 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':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':while (letter(character) | digit(character)char s2 = character ;strcat(token, s);character = getchar();retract(character);int num;num = reserve(token);if (num != 0)output(token, num);elseint val;val = symbol();output(token, val);break;case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':while (digit(character)char s2 = character ;strcat(token, s);character = getchar();retract(character);int val;val = constant();output(token, val);break;case '=':output("=", 12);break;case '<':character = getchar();if (character = '>')output("<>", 13);else if (character = '=')output("<=", 14);elseretract(character);output("<", 15);break;case '>':character = getchar();if (character = '=')output(">=", 16);elseretract(character);output(">", 17);break;case '-':output("-", 18);break;case '*':output("*", 19);break;case ':':character = getchar();if (character = '=')output(":=", 20);elseerror(lineNum, 2);/输出“未知运算符”错误break;case '(':output("(", 21);break;case ')':output(")", 22);break;case '':output("", 23);break;default:error(lineNum, 1); return true;void getPath(char* in, char* out)char* name;name = strrchr(in, '');if (name != NULL)strncpy(out, in, strlen(in) - strlen(name) + 1);elsestrcpy(out, "");void getFilename(char* in, char* out)char* fullName;char* extension;fullName = strrchr(in, '');extension = strrchr(in, '.');if (fullName != NULL)strncpy(out, fullName + 1, strlen(fullName) - 1 - strlen(extension);elsestrncpy(out, in, strlen(in) - strlen(extension);bool init(int argc, char* argv)if (argc != 2)return false;elsechar* inFilename = argv1;/argv1;char outFilenameMAX_COUNT = ""char errFilenameMAX_COUNT = ""char filenameMAX_COUNT = ""char pathMAX_COUNT = ""getFilename(inFilename, filename);getPath(inFilename, path);strcat(outFilename, path);strcat(outFilename, filename);strcat(outFilename, ".dyd");strcat(errFilename, path);strcat(errFilename, filename);strcat(errFilename, ".err");if (freopen(inFilename, "r", stdin) != NULL&&freopen(outFilename, "w", stdout) != NULL&&freopen(errFilename, "w", stderr) != NULL)return true;elsereturn false;void main(int argc, char* argv)if (init(argc, argv)while (LexAnalyze()fclose(stdin);fclose(stdout);fclose(stderr);return;电 子 科 技 大 学实 验 报 告学生姓名:爸爸 学 号:22 指导教师:陈昆实验地点:科研楼A-504 实验时间:2017-05-14一、实验项目名称:递归下降分析器的设计与实现二、实验学时:4学时三、实验原理1.语法分析是对源程序经过词法分析后转换成的单词流按方法规则进行判断,对能构成正确句子的单词流,给出相应的语法树;对不能构成正确句子的单词流判断其语法错误并做出相应处理。2在不含左递归的文法G中,如果对每一个非终结符的所有候选式的第一个终结符集合都是两两互不相交的(即无公共左因子),则可能(仅是可能)构造一个不带回溯的自上而下分析程序,这个分析程序由一组递归过程组成,每个过程对应文法的一个非终结符,这样的分析程序称为递归下降分析程序或递归下降分析器,其分析方法称为递归下降分析方法。3.语法分析方法有自上而下和自下而上的分析方法。四、实验目的 通过本次设计递归下降分析器的设计与实现实验,使同学们掌握自上而下的递归分析法的语法分析原理和程序设计方法,了解掌握递归下降分析方法。五、 实验内容根据给定的方法,编写相应的递归下降的语法分析程序,实现对词法分析后的单词序列的语法检查和程序结构的分析,生成相应的变量名表和过程名表,并将编译中语法检查出来的错误写入相应的文件。语法错分类: (1)缺少符号错; (2)符号匹配错 (3)符号无定义或重复定义。六、实验器材(设备、元器件)1.操作系统:Windows XP2.开发工具:VS2013七、实验步骤(1)启动VS2013,创建空白工程项目(2)消除文法中的左递归;(3)实现对方法进行递归向下的分析过程;(4)利用词法分析器生成的二元式文件*.dyd进行语法分析;(5)编译与调试以上程序;(6)查看生成的后缀为var,err,pro的文件并进行截图保存八、实验数据及结果分析 九、 实验结论 本次实验实现了语法分析器,实现了语法分析器的功能,更加深刻地理解了递归下降分析法。十、总结及心得体会 通过该实验,对递归下降分析程序的设计有着更好的掌握,同时锻炼了自己运用C语言进行编程的能力,也加深了自己对语法分析程序的原理的理解与掌握。十一、对本实验过程及方法、手段的改进建议先理解递归下降分析法的原理才能写出正确的程序。 报告评分:指导教师签字:本实验参考源代码如下:#include <stdio.h>#include <string.h>#include <Windows.h>#define MAX_COUNT 1024#define SIGN_UNDEFINED_ERR 1#define SIGN_REDEFINED_ERR 2#define SIGN_EXECUTE_ERR 3#define NO_SIGN_ERR 4#define SIGN_RESERVE_ERR 5#define NO_PARA_ERR 6typedef enum integer types;typedef struct char vname17;char vproc17;bool vkind;types vtype;int vlev;int vadr; varRecord;typedef structchar pname17;types ptype;int plev;int varNum;int fadr;int ladr;int parameter;bool parameterIsDefined; proRecord;void A();void B();void C();void C_();void D();void E();void F();void G();void J();void K();void L();void M();void M_();void N();void O();void P();void Q();void R();void R_();void S();void S_();void T();void U();void W();void X();void Y();void Z();bool init(int argc, char* argv);bool final();bool error(int lineNum, int errNum, const char* sign);void getPath(char* in, char* out);void getFilename(char* in, char* out);bool nextToken();bool nextChar();bool isVarExisted(char* vname, char* vproc, bool vkind);bool isProExisted(char* vname);int getNextToken();char inputMAX_COUNT17; int kindMAX_COUNT;int inputCount; int pToken; int pChar; varRecord currentVar; proRecord currentPro; int lineNum; varRecord varMAX_COUNT;proRecord proMAX_COUNT;int varCount;int proCount;FILE* inFile;FILE* outFile;FILE* errFile;FILE* varFile;FILE* proFile;int main(int argc, char* argv)if (init(argc, argv)A();final();return 0;bool init(int argc, char* argv)if (argc != 2)return false;elsechar* inFilename = argv1;char outFilenameMAX_COUNT = ""char errFilenameMAX_COUNT = ""char varFilenameMAX_COUNT = ""char proFilenameMAX_COUNT = ""char filenameMAX_COUNT = ""char pathMAX_COUNT = ""/获得文件名(不包括扩展名)和路径getFilename(inFilename, filename);getPath(inFilename, path);strcat(outFilename, path);strcat(outFilename, filename);strcat(outFilename, ".dys");strcat(errFilename, path);strcat(errFilename, filename);strcat(errFilename, ".err");strcat(varFilename, path);strcat(varFilename, filename);strcat(varFilename, ".var");strcat(proFilename, path);strcat(proFilename, filename);strcat(proFilename, ".pro");if (inFile = fopen(inFilename, "r") && (outFile = fopen(outFilename, "w") && (errFile = fopen(errFilename, "w") && (varFile = fopen(varFilename, "w") && (proFile = fopen(proFilename, "w")inputCount = 0;pToken = 0;pChar = 0;lineNum = 1;strcpy(currentPro.pname, "");currentPro.plev = 0;currentPro.varNum = 0;currentPro.parameter = -1;varCount = 0;proCount = 0;while (!feof(inFile)char stringOfLineMAX_COUNT;if (fgets(stringOfLine, MAX_COUNT, inFile)char lineString20 = ""strncpy(lineString, stringOfLine, 19);char* kindString = strrchr(lineString, ' ');kindinputCount = atoi(kindString + 1);char string17 = ""strncpy(string, stringOfLine, 16);char* lastString = strrchr(string, ' ');strcpy(inputinputCount, lastString + 1);inputCount+;return true;elsefclose(inFile);fclose(outFile);fclose(errFile);fclose(varFile);fclose(proFile);return false;bool final()for (int i = 0; i < varCount; i+)int vkind = vari.vkind ? 1 : 0;char* vtype = (vari.vtype = integer) ? "integer" : ""fprintf(varFile, "%16s %16s %d %s %d %dn", vari.vname, vari.vproc, vkind, vtype, vari.vlev, vari.vadr);for (int i = 0; i < proCount; i+)char* ptype = (proi.ptype = integer) ? "integer" : ""fprintf(proFile, "%16s %s %d %d %dn", proi.pname, ptype, proi.plev, proi.fadr, proi.ladr);if (fseek(inFile, 0, 0) = 0)while (!feof(inFile)fputc(fgetc(inFile), outFile);bool val;val = fclose(inFile);val = fclose(outFile);val = fclose(errFile);val = fclose(varFile);val = fclose(proFile);return val;bool error(int errNum, const char* symbol)char* errInfo;switch (errNum)case SIGN_UNDEFINED_ERR:fprintf(errFile, "*LINE:%d %s符号无定义n", lineNum, inputpToken);break;case SIGN_REDEFINED_ERR:fprintf(errFile, "*LINE:%d %s符号重定义n", lineNum, inputpToken);break;case SIGN_EXECUTE_ERR:fprintf(errFile, "*LINE:%d %s处不能匹配执行语句n", lineNum, inputpToken);break;case NO_SIGN_ERR:fprintf(errFile, "*LINE:%d %s处缺少%sn", lineNum, inputpToken, symbol);break;case SIGN_RESERVE_ERR:errInfo = "以保留字开头"break;case NO_PARA_ERR:fprintf(errFile, "*LINE:%d 缺少形参%s的声明n", lineNum, symbol);break;default:errInfo = "未知错误"return true;void getPath(char* in, char* out)char* name;name = strrchr(in, '');if (name != NULL)strncpy(out, in, strlen(in) - strlen(name) + 1);elsestrcpy(out, "");void getFilename(char* in, char* out)char* fullName;char* extension;fullName = strrchr(in, '');extension = strrchr(in, '.');if (fullName != NULL)strncpy(out, fullName + 1, strlen(fullName) - 1 - strlen(extension);elsestrncpy(out, in, strlen(in) - strlen(extension);bool nextToken()pToken+;pChar = 0;if (strcmp(inputpToken, "EOF") = 0)return true;while (strcmp(inputpToken, "EOLN") = 0)pToken+;lineNum+;return false;bool nextChar()if (inputpTokenpChar = '0')/nextToken();return true;pChar+;return false;bool isVarExisted(char* vname, char* vproc, bool vkind)for (int i = 0; i < varCount; i+)if (strcmp(vname, vari.vname) = 0) && (strcmp(vproc, vari.vproc) = 0) && (vari.vkind = vkind)return true;for (int i = 0; i < proCount; i+)if (strcmp(vname, proi.pname) = 0)return true;return false;bool isProExisted(char* vname)for (int i = 0; i < varCount; i+)if (strcmp(vname, vari.vname) = 0)return true;for (int i = 0; i < proCount; i+)if (strcmp(vname, proi.pname) = 0)return true;return false;int getNextToken()int pNextToken = pToken + 1;while (strcmp(inputpNextToken, "EOLN") = 0)pNextToken+;return pNextToken;void A()B();void B()if (strcmp(inputpToken, "begin") = 0)nextToken();elseerror(NO_SIGN_ERR, "begin");if (strcmp(inputpToken, "integer") != 0)nextToken();C();if (strcmp(inputpToken, "") = 0)nextToken();elseerror(NO_SIGN_ERR, "");if (strcmp(inputpToken, "integer") != 0) && (strcmp(inputpToken, "read") !=