《编译原理》课程设计报告姓名:熊齐超(1208060220)姓名:刘畅(1208060221)姓名:袁青伟(1208060222)姓名:张文(1208060223)班级:软件121班专业:软件工程指导教师:陈晓明时间:2015/6/14项目名称:算术表达式的语法及语义分析贵州大学计算机科学与信息学院目录一、课程设计目的 (3)二、课程设计题目描述和要求 (3)1、算术表达式的文法的描述: (3)2、课程设计的要求描述: (3)3、实现的功能描述: (4)4、分析器的使用描述 (4)三、课程设计实现描述 (4)1、实现平台 (4)2、课程设计的基本思路描述 (5)3、自顶向下与递归下降分析方法的基本原理描述 (5)4、程序运行的最后界面 (6)5、演示分析 (8)四、课程设计总结 (8)五、参考文献及小组分工 (9)六、核心代码 (10)一、课程设计目的通过设计、编制、调试一个算术表达式的语法及语义分析程序,加深对语法及语义分析原理的理解,并实现词法分析程序对单词序列的词法检查和分析。
加深对文法分析器的知识的掌握,掌握计算机语言的语法分析的过程。
以及掌握计算机语言的语法分析程序设计与文法应用的实现方法。
能够熟练运用一种分析方法,自上而下或自下而上的方法分析一个给定的文法,我使用的是自上而下的分析方法。
以及通过思考以及动手制作分析器的过程来锻炼自己的编程能力和逻辑思维能力,体会计算机编译器的奥妙之处。
二、课程设计题目描述和要求1、算术表达式的文法的描述:〈无符号整数〉∷=〈数字〉{〈数字〉}〈标识符〉∷=〈字母〉{〈字母〉|〈数字〉}〈表达式〉∷=〈项〉{〈加法运算符〉〈项〉}〈项〉∷=〈因子〉{〈乘法运算符〉〈因子〉}〈因子〉∷=〈标志符〉|〈无符号整数〉〈加法运算符〉∷=+|-〈乘法运算符〉∷=*|/〈字母〉∷= a | b | … | z〈数字〉∷= 0 | 1 | … | 92、课程设计的要求描述:1)在递归下降法、LL(1)、算符优先分析法或者LR法中选择其中一种方法完成以上任务,中间代码选用四元式。
2)编制分析程序,设计若干用例,并上机测试。
3)书写课程设计报告。
4)要求提供单步运行,让用户跟踪分析器工作的每一个步骤。
3、实现的功能描述:1)选定一种分析方法,本分析器采用递归下降分析方法进行语法分析2)允许用户手动输入算术表达式(每个项的长度不大于10)3)对输入的算术表达式进行词法、语法、语义分析4)分别对词法、语法、语义分析输出相应的执行结果5)对语法分析可输出递归下降分析的步骤,以及相应步骤所使用的产生式,对语义分析采用自顶向下分析方法,可输出四元式表示的中间代码。
4、分析器的使用描述对于一个给定的算术表达式,在此分析器中可直接点击词法分析按钮,得到结果如左下角的第一个显示框所示。
在运行分析器的过程中,输入的是相对应于文法所能够产生的算术表达式进行分析,如果是不符合文法的输入串,那么就会提示错误信息。
首先在输入表达式所对应的编辑框中输入所要分析的表达式,单击词法分析,在词法分析输出结果中可以查看算术表达式中使用的符号是否正确。
之后单击语法分析按钮,在语法分析框中会出现相应的递归下降分析步骤(包括分析过程中所使用的产生式)。
单击语义分析按钮,在分析结果栏中,显示以四元式表示的中间代码。
分析结束时,如果所输入的算术表达式是属于该文法的,那么语法分析输出结果框中显示:“输入串是该文法的一个句子!语法分析结束”若不属于该文法,那么语法分析输出结果框中显示:“输入串不是该文法的一个句子!语法分析结束”。
如果所输入的算术表达式中接有错误的字符,那么词法分析输出结果框中显示:“接错误后缀,出错”。
三、课程设计实现描述1、实现平台Microsoft Windows 7 / Microsoft Visual C++ 6.02、课程设计的基本思路描述首先应该把用文字表示的文法改写为数学符号。
(其中关于无符号整数和标识符,由于可以在词法分析的过程中给以确定,所以就不必抽象其表达式。
)设:indentifer :标识符 digit : 无符号整数E:表达式 T:项 F:因子则一个简单的术表达式的文法G1中包含以下产生式:E -> E+E | E-E | E*E | E/E | (E) | indentifer | digit为了明确运算符的优先权(括号的优先权高于乘除法,乘除法的优先权高于加减法),可改写文法G1如下:改写后的文法G2:E -> E+T | E-T | TT -> T*F | T/F | FF -> (E) | indentifer | digit为了避免左递归的发生,可进一步将文法改成:文法G[E]:(1)E -> [+|-]TG(2)G -> +TG|—TG(3)G -> ε(4)T -> FS(5)S -> *FS|/FS(6)S -> ε(7)F -> (E)(8)F -> indentifer | digit3、自顶向下与递归下降分析方法的基本原理描述自顶向下分析原理:自顶向下分析就是从文法的开始符号出发,向下推导,推出句子。
分为:带“回溯”的分析方法、不带回溯的递归子程序(递归下降)分析方法。
自顶向下分析的主旨:对任何输入串,试图用一切可能的办法,从文法开始符号(根结点)出发,自上而下、从左到右地为输入串建立一棵分析树。
或者说,为输入串寻找一个最左推导。
其分析是一种试探的过程,是反复使用不同产生式谋求与输入序列匹配的过程。
递归下降分析原理:递归的预测分析是为每一个非终结符写一个分析过程,这些过程可能是递归的在处理输入串时,首先执行的是对应开始符号的过程,然后根据产生式右部出现的非终结符,依次调用相应的过程,这种逐步下降的过程调用序列隐含地定义了输入串的分析树。
4、测试1. 当测试用例的算术表达式为1+4*(3+4*2+9/3)+7时,测试结果截图如下:当测试用例的算术表达式为6+!时,测试结果截图如下:当测试用例的算术表达式为2+(3+*)^时,测试结果截图如下:5、对句子的分析例如:对句子a+a+a*a的分析:设计该分析器的基本思路:输入算术表达式→给出词法分析结果→给出语法分析结果→给出语义分析结果由于程序在执行的过程中分为词法、语法、语义,故在程序设计的时候也按照这种方式,把整个程序分成三个大的部分,即词法分析部分,语法分析部分和语义分析部分。
而且在各个部分的内部采用模块化设计,再分成各个小块,各自完成其相对应的功能。
四、课程设计总结每一次课程设计,都有不一样的感受,通过课程设计,对我而言,得到的不仅仅是知识,更是获得知识的方法,这显得更加的重要。
通过本次对算术表达式的语法分析及语义分析器的设计,使我加深了对文法分析器的知识的掌握,掌握了计算机语言的语法分析的过程。
以及掌握了计算机语言的语法分析程序设计与文法应用的实现方法。
能够熟练运用递归下降分析方法,我使用的是自上而下的分析方法。
以及通过思考以及动手制作分析器的过程锻炼了自己的编程能力和逻辑思维能力。
并通过设计、编制、调试一个算术表达式的语法及语义分析程序,使我加深了对语法及语义分析原理的理解,并实现词法分析程序对单词序列的词法检查和分析。
我认为做好一个可视化的程序首先要做的工作是设计它界面,应为一个好的界面设计好了,那么在设计界面的过程中可能会激发起编程的思路。
做好一个项目的最主要的是要有恒心,虽然在做分析器的过程中遇到了很多的问题,刚开始做的时候没有什么头绪,经过和同学讨论和在网上搜集相关问题的答案,终于基本的问题都能够解决。
在课程设计的过程中,曾遇到过很多的问题,如对表达式的处理,单词的识别,还有很多细节的问题。
在遇到问题时,首先想到的是自己思考,分析过程,查找资料,上网百度,通过自己的努力还没有解决时,这是首先需要问的是自己旁边的同学,和同学讨论,有时还争得面红耳赤,如果最后将此不下,就再百度。
这课程设计的过程中,我几乎所有的问题处理流程就是这个样子的。
我感觉这就是一种学习的方法,在学习中遇到难题时的学习方法,要把这种学习的方法变成一种习惯,这才是每次课程设计应达到的一种效果。
课程设计提供了这样一种学习的机会,可以随时随地向同学请教,和老师交流的一个机会,和同学互相讨论的机会。
课程设计教会了我,如何用计算机程序来处理现实中的实际问题。
将现实中的实际问题先转化为数学模型,然后将数学模型用程序解决的一种能力。
经过这次课程设计,对语法分析有了更深入的了解,巩固了上课期间所学的知识。
对编译原理的基本原理也有了一定的了解。
五、参考文献及小组分工【1】编译原理………………………… Alfred.Aho(哥伦比亚大学) 、Monica m(斯坦福大学)、Ravi Sethi(Avaya实验室) Jeffrey D.Ullman……………机械工业出版社组长:熊齐超(1208060220)主要负责程序的组织、调试和语法分析和部分词法分析。
组员:刘畅(1208060221)主要负责词法分析部分组员:袁青伟(1208060222)主要负责收集资料和撰写实验报告组员:张文(1208060223)主要负责语义分析六、核心代码a.词法分析代码:int Bds::cifa_main() //词法分析主函数{int f;cifa_head = new cifa;cifa_head -> type = -1;cifa_head -> next = NULL;cifa_end = cifa_head;((CMATHDlg*)m_pWnd)->InfoAdd4("单词种类定义如下:");((CMATHDlg*)m_pWnd)->InfoAdd4("");((CMATHDlg*)m_pWnd)->InfoAdd4("标识符的种类编码 1 :");((CMATHDlg*)m_pWnd)->InfoAdd4("");((CMATHDlg*)m_pWnd)->InfoAdd4("常数的种类编码 2 :");((CMATHDlg*)m_pWnd)->InfoAdd4("");((CMATHDlg*)m_pWnd)->InfoAdd4("运算的种类编码 3 :+ ,- ,* ,/ ");((CMATHDlg*)m_pWnd)->InfoAdd4("");((CMATHDlg*)m_pWnd)->InfoAdd4("界限符的种类编码 4 : (,),;");GetChar();notock();//空格跳过((CMATHDlg*)m_pWnd)->InfoAdd1("词法分析结果如下:");while ( nn < 100 && ch != '^'){if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ) f=alph(); //字母串else if (ch >= '0' && ch <= '9') f=number(); //数字串else f=test();//其他符号if (f == 0) return (0);}cifa_disp(cifa_head);((CMATHDlg*)m_pWnd)->InfoAdd1("词法分析结束.");return (1);}int Bds::test() //识别相关符号{char temp[3];int i=0;int type;switch (ch){case ';' : //识别 ';'{temp[i++] = ch;GetChar();if (ch ==' ' ) temp[i++] =' ';temp[i] = '\0';type = 4;break;}case '+' : //识别 '+'{temp[i++] = ch;GetChar();if (ch ==' ' ) temp[i++] =' ';temp[i] = '\0';type = 3;break;}case '-' : //识别 '-'{temp[i++] = ch;GetChar();if (ch ==' ' ) temp[i++] =' ';temp[i] = '\0';type = 3;break;}case '*' : //识别 '*'{temp[i++] = ch;GetChar();if (ch ==' ' )temp[i++] =' ';temp[i] = '\0';type = 3;break;}case '/' : //识别 '/'{temp[i++] = ch;GetChar();if (ch ==' ' )temp[i++] =' ';temp[i] = '\0';type = 3;break;}case '(' : //识别 '('{temp[i++] = ch;GetChar();if (ch ==' ' )temp[i++] =' ';temp[i] = '\0';type = 4;break;}case ')' : // 识别')'{temp[i++] = ch;GetChar();if (ch ==' ' )temp[i++] =' ';temp[i] = '\0';type = 4;break;}default :{CString report;report.Format("%c",ch);((CMATHDlg*)m_pWnd)->InfoAdd1(report);((CMATHDlg*)m_pWnd)->InfoAdd1("无法识别,出错!");GetChar();if (ch == ' ')notock();return (0);}}if (ch == ' ') notock(); // 空格跳过cifa *p;p = new cifa;p -> next = NULL;p -> type = type;strcpy(p->word,temp);cifa_add(p);return (1);}int Bds::number() //识别数字{int type=2;int i=0;char temp[10];while('0'<= ch && ch <= '9'){temp[i] = ch;i++;GetChar();}temp[i]='\0';if (ch == ' ') notock(); //空格跳过else if (ch != '^' && ch != '+' && ch != '-' && ch != ';' && ch != '*' && ch != '/' && ch != '('&& ch != ')'){((CMATHDlg*)m_pWnd)->InfoAdd1("接错误后缀,出错");return (0);}if (ch == ' ') notock();cifa *p;p = new cifa;p -> next = NULL;p -> type = type;strcpy(p->word,temp);cifa_add(p);return (1);}int Bds::alph() //识别标识符{int i=0;char temp[10];int type = 1;temp[i] = ch;i++;GetChar();while ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >='0' && ch <= '9')){temp[i] = ch;i++;GetChar();}temp[i] = '\0';if (ch == ' ') notock();else if (ch != '^' && ch != '+' && ch != '-' && ch != ';' &&ch != '*' && ch != '/' && ch != '('&& ch != ')'){((CMATHDlg*)m_pWnd)->InfoAdd1("接错误后缀,出错");return 0;}cifa *p;p = new cifa;p -> next = NULL;p -> type = type;strcpy(p->word,temp);cifa_add(p);return (1);}cifa * Bds::cifa_add(cifa *p) //在分析结果列表尾添加一个新接点{cifa_end -> next = p;cifa_end = cifa_end -> next;return cifa_head;}void Bds::cifa_disp(cifa *cifa_head) //输出词法分析结果{cifa *p;p = cifa_head -> next ;while ( p != NULL){CString report;report.Format("(%2d , %s)",p->type,p->word);((CMATHDlg*)m_pWnd)->InfoAdd1(report);p = p ->next;}}void Bds::GetChar() //取字符{ch = str[nn];nn++;void Bds::notock() //去掉空格{if ( ch == ' ' )while ( ch == ' ' )GetChar();}void Bds::SetWnd(CDialog *pWnd){//设置窗口指针m_pWnd=pWnd;}b.语法分析代码:int Bds::yufa_main() //语法分析主程序{int n;cifa *p = new cifa;strcpy(p -> word ,"#"); //对词法分析产生的结果链表进行处理p -> type =-1;p -> next = NULL;cifa_add(p);cifa_p = cifa_head;((CMATHDlg*)m_pWnd)->InfoAdd2("算术表达式的递归分析过程如下:");((CMATHDlg*)m_pWnd)->InfoAdd2("步骤产生式");advance();n = E();if (n == 0){CString report;report.Format("%2d 输入串不是该文法的一个句子!",f);((CMATHDlg*)m_pWnd)->InfoAdd2(report);((CMATHDlg*)m_pWnd)->InfoAdd2("语法分析结束.");return (0);}else if (n == 1){CString report;report.Format("%2d 输入串是该文法的一个句子!",f);((CMATHDlg*)m_pWnd)->InfoAdd2(report);((CMATHDlg*)m_pWnd)->InfoAdd2("语法分析结束.");return (1);}void Bds::advance() //取词法分析产生列表中的结点作语法分析{cifa_p = cifa_p -> next;}int Bds::E() // E -> [+|-]TG 子函数{int t,g;if ((strcmp(cifa_p->word,"+") == 0)|| (strcmp(cifa_p->word,"-") == 0)) advance();CString report;report.Format("%2d E -> [+|-]TG",f++);((CMATHDlg*)m_pWnd)->InfoAdd2(report);t = T();if (t == 0) return (0);g = G();if (g == 0) return (0);else return (1);}int Bds::F() // F -> (E) | 标识符 | 无符号整数子函数{int m;if ((strcmp(cifa_p->word,"(") == 0 ) ){CString report;report.Format("%2d F -> (E)",f++);((CMATHDlg*)m_pWnd)->InfoAdd2(report);advance();m =E();if (m==0) return (0);if ((strcmp(cifa_p->word,")") == 0 ) ){advance();return (1);}else{((CMATHDlg*)m_pWnd)->InfoAdd2("ERROR.");return (0);}}else if ( cifa_p->type == 1 || cifa_p->type == 2) //数字或是标识符{CString report;report.Format("%2d F -> 标识符|无符号整数",f++);((CMATHDlg*)m_pWnd)->InfoAdd2(report);advance();return (1);}else return 0;}int Bds::S() // S -> *FS | /FS |ε子函数{int t,g;if (strcmp(cifa_p->word,"*") == 0){CString report;report.Format("%2d S -> *FS",f++);((CMATHDlg*)m_pWnd)->InfoAdd2(report);advance();t = F();if (t== 0) return 0;g = S();if (g == 0) return 0;return(1);}else if (strcmp(cifa_p->word,"/") == 0){CString report;report.Format("%2d S -> /FS",f++);((CMATHDlg*)m_pWnd)->InfoAdd2(report);advance();t = F();if (t== 0) return 0;g = S();if (g == 0) return 0;return(1);}else if (strcmp(cifa_p->word,"+") == 0 ||(strcmp(cifa_p->word,"-") == 0)||(strcmp(cifa_p->word,"#") == 0)||(strcmp(cifa_p->word,")") == 0)){CString report;report.Format("%2d S -> ε",f++);((CMATHDlg*)m_pWnd)->InfoAdd2(report);return(1);}return (0);}int Bds::T() // T -> FS 子函数{int t,g;CString report;report.Format("%2d T -> FS",f++);((CMATHDlg*)m_pWnd)->InfoAdd2(report);t = F();if (t== 0) return 0;g = S();if (g == 0) return 0;return(1);}int Bds::G() // G -〉+TG | -TG |ε子函数{int t,g;if (strcmp(cifa_p->word,"+") == 0){CString report;report.Format("%2d G -> +TG",f++);((CMATHDlg*)m_pWnd)->InfoAdd2(report);advance();t=T();if (t == 0) return(0);g=G();if ( g== 0) return (0);return (1);}else if (strcmp(cifa_p->word,"-") == 0){CString report;report.Format("%2d G -> -TG",f++);((CMATHDlg*)m_pWnd)->InfoAdd2(report);advance();t=T();if (t == 0) return(0);g=G();if (g == 0) return (0);return(1);}else if (strcmp(cifa_p->word,")") == 0 || strcmp(cifa_p->word,"#") == 0){CString report;report.Format("%2d G -> ε",f++);((CMATHDlg*)m_pWnd)->InfoAdd2(report);return(1);}return (0);}c.语义分析代码:void Bds::yuyi_main(){cifa_p = cifa_head;yuyi_head = new yuyi;yuyi_head -> next = NULL;yuyi_end = yuyi_head;((CMATHDlg*)m_pWnd)->InfoAdd3("语义分析产生的四元式如下:");advance();E1();yuyi_sys_disp();((CMATHDlg*)m_pWnd)->InfoAdd3("语义分析结束.");}yuyi *Bds::yuyi_add(yuyi *p) //在四元式链表末添加一个结点{yuyi_end->next = p ;yuyi_end = p;return yuyi_head;}void Bds::yuyi_sys_disp() //输出四元式链表{yuyi *p;p = yuyi_head->next;while(p!=NULL){CString report;report.Format("(%c ,%s ,%s ,%s)",p->op,p->op1,p->op2,p->result );((CMATHDlg*)m_pWnd)->InfoAdd3(report);p = p->next;}//cout<<endl;}int Bds::E1() //E -> T+E | T-E | T{yuyi *p = new yuyi;T1();strcpy(p->op1,T_name);if (strcmp(cifa_p->word,"+") == 0){advance();E1();p->next =NULL;p->op = '+';strcpy(p->op2,E_name);E_name[0] = 't';E_name[1] = ++count;E_name[2] = '\0';strcpy(p->result,E_name);yuyi_add(p);return (1);}else if (strcmp(cifa_p->word,"-") == 0){advance();E1();p->next =NULL;p->op = '-';strcpy(p->op2,E_name);E_name[0] = 't';E_name[1] = ++count;E_name[2] = '\0';strcpy(p->result,E_name);yuyi_add(p);return(1);}else{strcpy(E_name,T_name);return(1);}}int Bds::F1() //F -> (E) | 标识符 | 无符号整数{if ((strcmp(cifa_p->word,"(") == 0 ) ){advance();strcpy(F_name,cifa_p->word);strcpy(E_name,F_name);E1();if ((strcmp(cifa_p->word,")") == 0 ) ){advance();strcpy(F_name,E_name);return (1);}else{((CMATHDlg*)m_pWnd)->InfoAdd2("ERROR.");return (0);}}else if ( cifa_p->type == 1 || cifa_p->type == 2) {strcpy(F_name,cifa_p->word);advance();return (1);}else return 0;}int Bds::T1() //T -> F*T | F/T | F{yuyi *p = new yuyi;F1();strcpy(p->op1,F_name);if (strcmp(cifa_p->word,"*") == 0){advance();T1();p->next =NULL;p->op = '*';strcpy(p->op2,T_name);T_name[0] = 't';T_name[1] = ++count;T_name[2] = '\0';strcpy(p->result,T_name);yuyi_add(p);return(1);}else if (strcmp(cifa_p->word,"/") == 0) {advance();T1();p->next =NULL;p->op = '/';strcpy(p->op2,T_name);T_name[0] = 't';T_name[1] = ++count;T_name[2] = '\0';strcpy(p->result,T_name);yuyi_add(p);return(1);}else{strcpy(T_name,F_name);return(1);}}。