编译原理课程设计报告报告-词法语法分析器.doc
-编译原理课程设计Course Design of piling 半期题目:词法和语法分析器课程设计1-C语言词法分析器1.题目C语言词法分析2.容选一个能正常运行的c语言程序,以该程序出现的字符作为单词符号集,不用处理c语言的所有单词符号。将解析到的单词符号对应的二元组输出到文件中保存可以将扫描缓冲区与输入缓冲区合成一个缓冲区,一次性输入源程序后就可以进行预处理了3.设计目的掌握词法分析算法,设计、编制并调试一个词法分析程序,加深对词法分析原理的理解4.设计环境(电脑语言环境)语言环境:C语言CPU:i7HQ6700存:8G5.概要设计(单词符号表,状态转换图)5.1 词法分析器的结构词法分析程序的功能:输入:所给文法的源程序字符串。输出:二元组(syn,token或sum)构成的序列。词法分析程序可以单独为一个程序;也可以作为整个编译程序的一个子程序,当需要一个单词时,就调用此法分析子程序返回一个单词.为便于程序实现,假设每个单词间都有界符或运算符或空格隔开,并引入下面的全局变量及子程序:1) ch 存放最新读进的源程序字符2) strToken 存放构成单词符号的字符串3) Buffer字符缓冲区4)struct keyType 存放保留字的符号和种别源程序输入缓冲区预处理子程序扫描缓冲区1扫描缓冲区2词法分析子程序返回一个单词调用数据5.2 待分析的简单词法(1)保留字break、case、char、const、int、do、while(2)运算符和界符= 、+、 -、 * 、/、%、,、;、(、)、?、#5.3 各种单词符号对应的种别码单词符号种别码单词符号种别码ID0sizeof24INT1static25auto2struct26break3switch27case4typedef28char5union29const6unsigned30continue7void31default8volatile32do9while33double10=34else11+35enum12-36e*tern 13*37float14/38for15%39goto16,40if17;41int18(42long19)43register20"44return21clear45short22#46signed23lettet(letter|digit)*47dight dight*485.3 状态转换图6.详细设计(数据结构,子程序)算法思想:首先设置3个变量:strToken用来存放构成单词符号的字符串;ch用来字符;struct keyType用来存放单词符号的种别码。扫描子程序主要部分流程如下图所示。子程序结构:子程序名功能GETCHAR()读一个字符到 ch 中GETBC()读一个非空白字符到ch 中CONCAT()把CHAR 中字符连接到strToken 之后LETTER()判断CHAR 中字符是否为字母DIGIT()判断ch 中字符是否为数字RESERVE()用strToken中的字符串查找保留字表,并返回保留字种别码,若返回零,则非保留字RETRACT()把CHAR 中字符回送到缓冲区7.程序清单/ ConsoleApplication1.cpp : 定义控制台应用程序的入口点。/#include"stdaf*.h"#include"stdio.h"#include"stdlib.h"#include"conio.h"#include"string.h"#defineN 47char ch;char strToken20;/存放构成单词符号的字符串char buffer1024;/字符缓冲区structkeyType char keyname256;int value;KeyN = "$ID",0 , "$INT",1 , "auto",2 , "break",3 , "case",4 , "char",5 , "const",6 , "continue",7 , "default",8 , "do",9 , "double",10 , "else",11 , "enum",12 , "e*tern",13 , "float",14 , "for",15 , "goto",16 , "if",17 , "int",18 , "long",19 , "register",20 , "return",21 , "short",22 , "signed",23 , "sizeof",24 , "static",25 , "struct",26 , "switch",27 , "typedef",28 , "union",29 , "unsigned",30 , "void",31 , "volatile",32 , "while",33 , "=",34 , "+",35 , "-",36 , "*",37 , "/",38 , "%",39 , ",",40 , "",41 , "(",42 , ")",43 , """,44 , "clear",45 , "#",46 ;void GetChar()/读一个字符到ch中int i;if (strlen(buffer)>0) ch = buffer0;for (i = 0; i<256; i+)bufferi = bufferi + 1;elsech = '0'void GetBC()/读一个非空白字符到ch中int i;while (strlen(buffer) i = 0;ch = bufferi;for (; i<256; i+) bufferi = bufferi + 1;if (ch != ' '&&ch != 'n'&&ch != '0')break;void ConCat()/把ch连接到strToken之后char temp2;temp0 = ch;temp1 = '0'strcat(strToken, temp);bool Letter()/判断ch是否为字母if (ch >= 'A'&&ch <= 'Z' | ch >= 'a'&&ch <= 'z')returntrue;elsereturnfalse;bool Digit()/判断ch是否为数字if (ch >= '0'&&ch <= '9')returntrue;elsereturnfalse;int Reserve()/用strToken中的字符查找保留字表,并返回保留字种别码,若返回0,则非保留字inti;for (i = 0; i<N; i+)if (strcmp(strToken, Keyi.keyname) = 0)return Keyi.value;return 0;void Retract()/把ch中的字符回送到缓冲区int i;if (ch != '0') buffer256 = '0'for (i = 255; i>0; i-)bufferi = bufferi - 1;buffer0 = ch;ch = '0'keyType ReturnWord()strcpy(strToken, "0");int c;keyType tempkey;GetBC();if (ch >= 'A'&&ch <= 'Z' | ch >= 'a'&&ch <= 'z') ConCat();GetChar();while (Letter() | Digit() ConCat();GetChar();Retract();c = Reserve();strcpy(tempkey.keyname, strToken);if (c = 0)tempkey.value = 0;elsetempkey.value = Keyc.value;elseif (ch >= '0'&&ch <= '9') ConCat();GetChar();while (Digit() ConCat();GetChar();Retract();strcpy(tempkey.keyname, strToken);tempkey.value = 1;else ConCat();strcpy(tempkey.keyname, strToken);tempkey.value = Reserve();return tempkey;/*主函数*/int main() /文件操作FILE *fp;if (fp = fopen("E:作业编译原理Ccode.t*t", "r") = NULL) printf("cannot open file/n"); e*it(1);while (!feof(fp) if (fgets(buffer, 250, fp) != NULL)printf("E:作业编译原理Ccode.t*tn"); keyType temp;printf("单词t种别号n");while (strlen(buffer) temp = ReturnWord();printf("%st %dnn", temp.keyname, temp.value);printf("the end!n"); getch();return 0;8.运行结果E:/作业/编译原理/Code.t*t运行结果九、 实验体会通过本次次法分析设计实验,我加深了对词法分析过程的理解。并在实际的设计过程深入的了解了编译原理思想。对编译原理课程有了更深的理解课程设计二:设计简单的语法分析器一、 题目设计简单的语法分析器二、 设计容用算符优先分析方法设计一个分析解释程序,对输入的赋值语句、输出语句、清除语句进行词法分析、语法分析、表达式求值并存储于指定变量中;若存在错误,提示错误相关信息。三、 设计目的了解掌握算符优先分析的基本方法、容;四、 设计环境语言环境:C语言CPU:i7HQ6700存:8G五、 概要设计5.1设计思路语法分析的任务: 把单词符号作为基本单位,分析程序是否为合法的程序.算符优先分析法是自下而上的语法分析方法,即根据文法,对输入字串进行归约,若能正确地归约为文法的初始符号,则表示输入字串是合法的.主要研究对输入的赋值语句、输出语句、清除语句进行词法分析、语法分析、表达式求值并存储于指定变量中;若存在错误,提示错误相关信息。文法表示: Sv=E|E"|clear EE+T|E-T|T TT*F|T/F|F F (E)|v|c 5.2 单词种别码设计符号种别码=1?2+3-4*5/6(7)8v9c10clear11#12N13六、 详细设计6.1 变量及函数说明变量及函数名表示容及操作int priorityNUMNUM优先关系矩阵struct WordType单词种别码结构struct VarWord变量表中的元素结构mainStack归约栈wordStack单词串GetwordStack()输入串转化成单词串GetWord()从单词串中取单词ClearwordStack()、ClearmainStack()清空单词串和归约栈CheckvarTable(char a)查看变量在变量表中的位置AddvarTable(VarWord a)变量表添加变量InitmainStack()初始化归约栈AddmainStack(WordType a)归约栈添加Handle()归约处理程序MainHandle()归约子程序七、 程序清单/ ConsoleApplication1.cpp : 定义控制台应用程序的入口点。/#include"stdaf*.h"#include"stdio.h"#include"stdlib.h"#include"conio.h"#include"string.h"#defineNUM 14#defineM 256#defineN 47/保留字个数char ch = '0'/存放最新读进的源程序字符char strToken20 = "0"/存放构成单词符号的字符串char buffer257 = "0"/字符缓冲区structkeyType char keyname256;int value;KeyN = "$ID",0 , "$INT",1 , "auto",2 , "break",3 , "case",4 , "char",5 , "const",6 , "continue",7 , "default",8 , "do",9 , "double",10 , "else",11 , "enum",12 , "e*tern",13 , "float",14 , "for",15 , "goto",16 , "if",17 , "int",18 , "long",19 , "register",20 , "return",21 , "short",22 , "signed",23 , "sizeof",24 , "static",25 , "struct",26 , "switch",27 , "typedef",28 , "union",29 , "unsigned",30 , "void",31 , "volatile",32 , "while",33 , "=",34 , "+",35 , "-",36 , "*",37 , "/",38 , "%",39 , ",",40 , "",41 , "(",42 , ")",43 , """,44 , "clear",45 , "#",46 ;/优先关系矩阵int priorityNUMNUM = 0,0,0,0,0,0,0,0,0,0,0,0,0,0 , 0,0,0,0,0,0,0,0,0,0,0,0,0,0 , 0,0,0,0,0,0,0,0,0,0,0,0,1,0 , 0,0,0,1,1,-1,-1,-1,1,-1,0,0,1,0 , 0,0,0,1,1,-1,-1,-1,1,-1,0,0,1,0 , 0,0,0,1,1,1,1,-1,1,-1,0,0,1,0 , 0,0,0,1,1,1,1,-1,1,-1,0,0,1,0 , 0,0,0,-1,-1,-1,-1,-1,2,-1,0,0,0,0 , 0,0,0,1,1,1,1,0,1,0,0,0,1,0 , 0,0,1,1,1,1,1,0,1,0,0,0,1,0 , 0,0,0,0,0,0,0,0,0,0,0,0,1,0 , 0,0,0,0,0,0,0,0,0,0,0,0,0,0 , 0,0,0,-1,-1,-1,-1,-1,0,0,0,0,3,0 , 0,0,1,0,0,0,0,0,0,0,0,0,1,0 ;structVarTable VarWord elemM;int len;varTable;structOperateStack WordType elemM;/单词元素int len;OperateStack mainStack;/归约栈OperateStack wordStack;structWordType char wordM;int value;wordTypeNUM = "error",0 , "=",1 , """,2 , "+",3 , "-",4 , "*",5 , "/",6 , "(",7 , ")",8 , "$i",9 , "$c",10 , "clear",11 , "#",12 , "$N",13 ;/* 变量表*/structVarWord char varnameM;/变量名char valueM; bool flag;void GetChar()/读一个字符到ch中int i;if (strlen(buffer)>0) ch = buffer0;for (i = 0; i<256; i+)bufferi = bufferi + 1;elsech = '0'void GetBC()/读一个非空白字符到ch中int i;while (strlen(buffer) i = 0;ch = bufferi;for (; i<256; i+) bufferi = bufferi + 1;if (ch != ' '&&ch != 'n'&&ch != '0')break;void ConCat()/把ch连接到strToken之后char temp2;temp0 = ch;temp1 = '0'strcat(strToken, temp);bool Letter()/判断ch是否为字母if (ch >= 'A'&&ch <= 'Z' | ch >= 'a'&&ch <= 'z')returntrue;elsereturnfalse;bool Digit()/判断ch是否为数字if (ch >= '0'&&ch <= '9')returntrue;elsereturnfalse;int Reserve()/用strToken中的字符查找保留字表,并返回保留字种别码,若返回0,则非保留字int i;for (i = 0; i<N; i+)if (strcmp(strToken, Keyi.keyname) = 0)return Keyi.value;return 0;void Retract()/把ch中的字符回送到缓冲区int i;if (ch != '0') buffer256 = '0'for (i = 255; i>0; i-)bufferi = bufferi - 1;buffer0 = ch;ch = '0'keyType ReturnWord()strcpy(strToken, "0");int c;keyType tempkey;GetBC();if (ch >= 'A'&&ch <= 'Z' | ch >= 'a'&&ch <= 'z') ConCat();GetChar();while (Letter() | Digit() ConCat();GetChar();Retract();c = Reserve();strcpy(tempkey.keyname, strToken);if (c = 0)tempkey.value = 0;elsetempkey.value = Keyc.value;elseif (ch >= '0'&&ch <= '9') ConCat();GetChar();while (Digit() ConCat();GetChar();Retract();strcpy(tempkey.keyname, strToken);tempkey.value = 1;else ConCat();strcpy(tempkey.keyname, strToken);tempkey.value = Reserve();return tempkey;bool GetwordStack() int i;wordStack.len = 0;keyType temp;while (strlen(buffer) temp = ReturnWord();/词法分析器获得一个分析词if (temp.value = 1)/常数("$c",10)strcpy(wordStack.elemwordStack.len.word, temp.keyname);wordStack.elemwordStack.len.value = 10;elseif (temp.value = 0)/变量("$i",9)strcpy(wordStack.elemwordStack.len.word, temp.keyname);wordStack.elemwordStack.len.value = 9;else for (i = 0; i<NUM; i+) if (strcmp(temp.keyname, wordTypei.word) = 0)/关键字wordStack.elemwordStack.len = wordTypei;break;elseif (i = NUM - 1) printf("输入串中出现未识别单词!n");returnfalse;wordStack.len+;wordStack.elemwordStack.len+ = wordType12;returntrue;/*从单词串中取单词*/WordType GetWord() WordType temp = wordStack.elem0;for (int i = 0; i<wordStack.len - 1; i+)wordStack.elemi = wordStack.elemi + 1;wordStack.len-;return temp;void ClearwordStack()/清空单词串wordStack.len = 0;void ClearmainStack()/清空归约栈mainStack.len = 0;/*查看变量在变量表中的位置*/int CheckvarTable(chara) for (int i = 0; i<M; i+)if (strcmp(a, varTable.elemi.varname) = 0)return i;elseif (i = M - 1)return -1;/*添加变量*/void AddvarTable(VarWorda) varTable.elemvarTable.len =a;varTable.len+;/*初始化归约栈*/void InitmainStack()mainStack.elem0 = wordType12;mainStack.len = 1;/*添加归约栈*/void AddmainStack(WordTypea)mainStack.elemmainStack.len =a;mainStack.len+;/*归约*/bool Handle()int i;/常量归约if (mainStack.elemmainStack.len - 1.value = 10) mainStack.elemmainStack.len - 1.value = 13;/变量归约elseif (mainStack.elemmainStack.len - 1.value = 9) mainStack.elemmainStack.len - 1.value = 13;i = CheckvarTable(mainStack.elemmainStack.len - 1.word);if (i<0) printf("n变量 %s 未定义!", mainStack.elemmainStack.len - 1.word);returnfalse;elsestrcpy(mainStack.elemmainStack.len - 1.word, varTable.elemi.value);/赋值归约elseif (mainStack.elemmainStack.len - 2.value = 1) if (mainStack.elemmainStack.len - 3.value = 9) i = CheckvarTable(mainStack.elemmainStack.len - 3.word);if (i<0) VarWord temp;strcpy(temp.varname, mainStack.elemmainStack.len - 3.word);strcpy(temp.value, mainStack.elemmainStack.len - 1.word);temp.flag = true;AddvarTable(temp);elsestrcpy(varTable.elemi.value, mainStack.elemmainStack.len - 1.word);strcpy(mainStack.elemmainStack.len - 3.word, mainStack.elemmainStack.len - 1.word);mainStack.elemmainStack.len - 3.value = 13;elseif (mainStack.elemmainStack.len - 3.value = 13)strcpy(mainStack.elemmainStack.len - 3.word, mainStack.elemmainStack.len - 1.word);mainStack.len = mainStack.len - 2;/运算归约elseif (mainStack.elemmainStack.len - 2.value = 3) int a, b;a = atoi(mainStack.elemmainStack.len - 1.word);b = atoi(mainStack.elemmainStack.len - 3.word);a = a + b;itoa(a, mainStack.elemmainStack.len - 3.word, 10);mainStack.len = mainStack.len - 2;elseif (mainStack.elemmainStack.len - 2.value = 5) int a, b;a = atoi(mainStack.elemmainStack.len - 1.word);b = atoi(mainStack.elemmainStack.len - 3.word);a = a*b;itoa(a, mainStack.elemmainStack.len - 3.word, 10);mainStack.len = mainStack.len - 2;/输出语句elseif (wordStack.elem0.value = 2 && mainStack.elemmainStack.len - 1.value = 13 && mainStack.elemmainStack.len - 2.value = 12) printf("n表达式的值为 %s", mainStack.elemmainStack.len - 1.word);mainStack.len = 0;/结束归约elseif (mainStack.elemmainStack.len - 2.value = 12 && wordStack.elem0.value = 12)mainStack.len = mainStack.len - 2;returntrue;bool MainHandle() while (wordStack.len)if (prioritymainStack.elemmainStack.len - 1.valuewordStack.elem0.value != 1)AddmainStack(GetWord();else if (mainStack.len) /printf("n");for (int i = 0; i<mainStack.len; i+)printf("(%s,%d)", mainStack.elemi.word, mainStack.elemi.value);Handle();break;if (mainStack.len)MainHandle();returntrue;/*主函数*/int main() int ok = 1;WordType temp;int ii = 0;while (ok) printf("n");printf("输入第 %d 语句串:",+ii);scanf("%s", buffer);printf("单词串:");if (!GetwordStack()return 0;for (int i = 0; i<wordStack.len; i+)printf("(%s,%d)", wordStack.elemi.word, wordStack.elemi.value);printf("n当前归约栈:");InitmainStack();MainHandle();printf("结束n");return 0;八、 运行结果九、 实验体会通过本次语法分析设计实验,我加深了对语法分析过程的理解。并在实际的设计过程深入的了解了编译原理思想。对编译原理课程有了更深的理解. z.