语义分析及中间代码生成程序设计原理与实现技术--实验报告及源代码北京交通大学
- 格式:doc
- 大小:149.50 KB
- 文档页数:24
实验报告封面课程名称:编译原理课程代码:SS2027任课老师:彭小娟实验指导老师: 彭小娟实验报告名称:实验十四:语义分析与中间代码生成1学生姓名:学号:教学班:递交日期:签收人:我申明,本报告内的实验已按要求完成,报告完全是由我个人完成,并没有抄袭行为。
我已经保留了这份实验报告的副本。
申明人(签名):实验报告评语与评分:评阅老师签名:彭小娟一、实验名称:语义分析与中间代码生成1二、实验日期: 年 月 日三、实验目的:1. 理解相关概念:中间代码、三地址码,各种语句的目标代码结构2. 掌握三地址码(三元式、四元式、DAG 图),3. 理解赋值语句三地址代码的翻译模式四、实验用的仪器和材料:(操作系统:CPU :内存:硬盘:软件:)硬件:PC 人手一台软件:office五、实验的步骤和方法:1. 给出下面中缀式的逆波兰表示(后缀式),后缀式的中缀式表示/*)(*)/(*++-+-+-++e d c ab d c b a e d c b anot A or not (C or not D)2. 请将表达式-(a+b)*(c+d)-(a+b+c)分别表示成三元式、四元式序列。
3. 按7.3节所说的方法,写出下面赋值句)A+=的自下而上语法制导B-(*:DC翻译过程。
给出所产生的三地址代码。
六、数据记录和计算:七、实验结果或结论:(总结)八、备注或说明:可写上实验成功或失败的原因,实验后的心得体会、建议等。
九、引用参考文献:即在本实验中所引用的之資料。
算符优先语法分析设计原理与实现技术XXX 1028XXX 计科1XXX 班功能描述能够有效识别以下算符优先文法E T E+T | E-TT T T*F | T/F | FF T (E) | i所描述算术表达式.主要数据结构描述程序结构描述设计方法2. 根据算符优先矩阵算数表达式的词法分析结果进行语法分析,分析算法为:数据结构:符号栈S ---存放所有读进的符号(计数i)K ---符号栈使用深度a ---工作单元R, Q ---变量分析算法:先找最左素短语的尾部(>)再找最左素短语的头部(<)以分析表达式i+i*i为例,详细过程如下:■算符优先关系矩阵例:舖入串i+i*i 的界苻优先分析过程(査界替优先关系矩体)1#N + N**<i■11# N + N*'■ 1#1#N + N J* N+<*># 接受# N + N#<+>## N结论:汁详iJt 文法的命法句子函数原型功能描述void in it()各种初始化操作,主要是建立符号与整 数、整数与行列号、整数与符号之间的映 射,也包括各全局变量的初始化void isVt(i nt )判断某整数所代表的符号是否是终结符##<i# i#<i>-l- #N#<+# N + +<i# N + i +<i>* # N+ N+<*分析栈优先关系号或’#'void comp(i nt a, int b) r比较两整数所代表的字符的优先关系—void adva nce() 从输入文件中读入一个词bool parser() 算符优先分析函数,根据算符优先矩阵进行语法分析int main (i nt argc, char *argv[]) 主函数,参数argv[1]代表输入文件函数调用关系程序执行图S(l)=#;i=l;k=Q;k~k+1: R=siiLrQ=SG); j=j-ij=j-i l| t=i 11i=讦丄;S(i)=R程序测试测试用例一:(a+b*c)+d+e+a*c/b 首先调用实验一的词法分析程序,得到如下分析结果:(19, '(')(12, 'a')(14, '+')(12, 'b')(16, '*')(12, 'c')(20, ')')(14, '+')(12, 'd')(14, '+')(12, 'e')(14, '+')(12, 'a')(16, '*')(12, 'c')(17, '/')(12, 'b')在以此分析结果作为本程序实验结果的输入,得到如下分析结果:taw Cf'v/indov^5\system32\cmd.exe该结果显示了详细的分析过程,且表明该表达式是一个符合该文法的表达式测试用例二:(a+b*c)+d*-a*c+(a+b同样调用实验--的词法分析程序,得到如下结果:(19, '(')(12, 'a')(14, '+')(12, 'b')(16, '*')(12, 'c')(20, ')')(14, '+') (12, 'd') (16, '*') (15, '-') (12, 'a') (16, '*') (12, 'c') (14, '+') (19, '(') (12, 'a') (14, '+') (12, 'b')以此分析结果作为本实验程序的输入,得到如下语法分析结果:实验结果表明,在分析过程中出现了错误,分析过程未完成,该样例是一个非法的表达式.学习总结按算符优先关系所确定的应被规约的子串恰好是当前举行的最左素短语.尽管算符优先分析也属于自底向上语法分析的范畴,但却不是严格的从左至右的规范分析,每步所得的句型自然也不是一个规范句型.采用上述策略进行算符优先分析时,尽管我们也指出了每一最左素短语应规约到的非终结符号,然而每次在查找最左素短语时,起主导作用的是终结符号间的优先关系,两终结符号之间究竟是哪个非终结符号无关宏旨.// operator_prior.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <stdio.h>#include <ctype.h>#include <map>#include <vector>#include <string>#define ID 12#define ADD 14#define SUB 15#define MUL 16#define DIV 17#define LP 19#define RP 20#define EOI 31#define SHARP 32#define EQ 0#define BT 1#define LT 2#define UD 3#define N_Base 1000 using namespace std;FILE *fp;int lookahead, yylineno;bool success;map<int, int> intToint; map<char, int> charToint; map<int, char> intTochar; string grammer[8] = {"E+T", "E-T", "T","T*F", "T/F", "F","(E)", n:n};int prior_matrix[9][9] = {{BT, BT, LT, LT, LT, BT, LT, BT},{BT, BT, LT, LT, LT, BT, LT, BT},{BT, BT, BT, BT, LT, BT, LT, BT},{BT, BT, BT, BT, LT, BT, LT, BT},{LT, LT, LT, LT, LT, EQ, LT, UD},{BT, BT, BT, BT, UD, BT, UD, BT},{BT, BT, BT, BT, UD, BT, UD, BT},{LT, LT, LT, LT, LT, UD, LT, EQ}};void init() {success = true;yylineno = 0;intToint[ADD] = 0; intToint[SUB] = 1;intToint[MUL] = 2; intToint[DIV] = 3;intToint[LP] = 4; intToint[RP] = 5;intToint[ID] = 6; intToint[SHARP] = 7;charToint['+'] = ADD; charToint['-'] = SUB;charToint['*'] = MUL; charToint['/'] = DIV;charToint['('] = LP; charToint[')'] = RP;charToint['i'] = ID;intTochar[ADD] = '+'; intTochar[SUB] = '-';intTochar[MUL] = '*'; intTochar[DIV] = '/';intTochar[LP] = '('; intTochar[RP] = ')';intTochar[ID] = 'i'; intTochar[SHARP] = '#';intTochar[N_Base] = 'N';}bool isVt(int a) {if (a >= N_Base) return false;else return true;}int comp(int a, int b) { int x = intToint[a];int y = intToint[b]; return prior_matrix[x][y]; }void advance() {if (fscanf(fp, "(%d", &lookahead) == EOF) { lookahead = SHARP;} else {char ch;do {ch = fgetc(fp);if (ch == '\n' || ch == EOF) break; } while (true);} yylineno++;}void parser() {int stack[100], top = 0;int i, j, k, ii, jj;stack[top++] = SHARP;advance();do {for (i = 0; i < top; i++) {printf("%c", intTochar[stack[i]]);}printf("\t%c\n", intTochar[lookahead]);for (i = top - 1; i >= 0; i--) { if (isVt(stack[i])) break;}int res = comp(stack[i], lookahead);if (res == LT || res == EQ) { stack[top++] = lookahead; advance();} else if (res == BT) {int temp = stack[i]; for (j = i - 1; j >= 0; j--) {if (isVt(stack[j])) {if (comp(stack[j], temp) == LT) {break;} else {temp = stack[j];}}}for (k = 0; k < 8; k++) {if ((int)grammer[k].length() == top - 1 - j) {ii = j + 1;jj = 0;do {if (grammer[k].at(jj) >= 'A' && grammer[k].at(jj) <= 'Z'){ if (isVt(stack[ii])) break;} else {if (charToint[grammer[k].at(jj)] != stack[ii]) break;}ii++;jj++;} while (ii < top && jj < (int)grammer[k].length());if (ii >= top) break;}}if (k >= 8) {success = false;return ;}top = j + 1;stack[top++] = N_Base;} else {success = false;return ;}if (stack[0] == SHARP && stack[1] == N_Base&& stack[2] == SHARP) { printf("#N#\n"); break;}} while (true);success = true;}int main(int argc, char *argv[]) {if (argc == 2) {fp = fopen(argv[1], "r");init();parser();if (success) printf("This is a legal expression."); else printf("Thisis a illegal expression.");} else {printf(" 参数错误!\n");}return 0;。
LL(1)语法分析设计原理与实现技术实验计科100X班 10284XXX程序设计功能实现LL(1)分析中控制程序(表驱动程序);完成以下描述算术表达式的LL(1)文法的LL(1)分析程序。
G[E]: E→TE′E′→ATE′|εT→FT′T′→MFT′|εF→(E)|iA→+|-M→*|/说明:终结符号i 为用户定义的简单变量,即标识符的定义。
主要数据结构描述由文法可得:对于E:FIRST( E )= {(, i }对于E’: FIRST( E’ ) ={+,−,ε}对于T: FIRST( T )= ={(, i }对于T’: FIRST( T’)= ={*,∕,ε}对于F: FIRST( F )= ={(, i }对于A: FIRST( A )= ={+, - }对于M: FIRST(M)= ={*, / }由此我们容易得出各非终结符的FOLLOW集合如下:FOLLOW( E )= { ),#}FOLLOW(E’) ={ ),#}FOLLOW( T ) ={+,−,),#}FOLLOW( T’ ) = FOLLOW( T ) ={+,−,),#}FOLLOW( F )=FIRST(T’)\ε∪FOLLOW(T’)={*,∕,+,−,),#}FOLLOW( A )= { (, i }FOLLOW( M )= { (, i}文法LL(1)的预测分析表(表1):表1. LL(1)预测分析表注:为编程方便,在程序中,将E’、T’改为G、S程序结构描述1.设计方法:程序通过从文本文档读入数据,将所读数据以空格、回车或者退格为标示符,分为字符串,对字符串进行词法分析,最后将所有字符串按序输出到结果文档中,并在结果文档中标明每个字符串的类别序号。
2、程序中主要函数定义和调用关系如下:函数:void print()作用:输出分析栈void print1();作用:输出剩余串int main();作用:主要逻辑功能程序执行图如下:实验结果测试用例1:i+i*i#测试用例2:i-i++#实验总结相对于递归下降分析法,LL(1)分析法更为有效.采用此种方法的分析器由一张预测分析表(LL(1)分析表)、一个控制程序(表驱动程序)和一个分析栈组成,预测分析表中个元素的含义是:或者指出当前推到所应使用过的产生式,或者指出输入符号串中存在语法错误.LL(1)分析法的局限在于:只能分析LL(1)文法或者某些非LL(1)文法,但需先将其改造成LL(1)文法。
语义分析及中间代码生成程序设计原理与实现技术XXX 1028XXX2 计科1XXX班1.程序功能描述完成以下描述赋值语句和算术表达式文法的语法制导生成中间代码四元式的过程。
G[A]:A→V:=EE→E+T∣E-T∣T→T*F∣T/F∣FF→(E)∣iV→i说明:终结符号i 为用户定义的简单变量,即标识符的定义。
2. 设计要求(1)给出每一产生式对应的语义动作;(2)设计中间代码四元式的结构(暂不与符号表有关)。
(3)输入串应是词法分析的输出二元式序列,即某算术表达式“实验项目一”的输出结果。
输出为输入串的四元式序列中间文件。
(4)设计两个测试用例(尽可能完备),并给出程序执行结果四元式序列。
3.主要数据结构描述:本程序采用的是算符优先文法,文法以及算符优先矩阵是根据第四次实验来修改的,所以主要的数据结构也跟第四次差不多,主要为文法的表示,FirstVT集和LastVT集以及算符优先矩阵:算符优先矩阵采用二维字符数组表示的:char mtr[9][9]; //算符优先矩阵4.程序结构描述:本程序一共有8功能函数:void get(); //获取文法void print(); //打印文法void fun(); //求FirstVT 和 LastVTvoid matrix(); //求算符优先矩阵void test(); //测试文法int cmp(char a,char b); 比较两个运算符的优先级 1 0 -1void out(char now,int avg1,int avg2); //打印四元式int ope(char op,int a,int b); //定义四元式计算方法5.实验代码详见附件6.程序测试6.1 功能测试程序运行显示如下功能菜单:选择打印文法:选择构造FirstVt集和LastVT集:选择构造算符优先矩阵:6.2 文法测试测试1:1+2*3测试2:2+3+4*5+(6/2)7.学习总结本次实验完成了语义及中间代码生成的设计原理与实现,所采用的方法为算符优先分析方法,首先根据文法求出此文法的FirstVT集和LastVT集,然后根据他们求出此文法的算符优先矩阵。
编译原理实验四语义分析及中间代码⽣成⼀、实验⽬的(1)通过上机实验,加深对语法制导翻译原理的理解,掌握将语法分析所识别的语法范畴变换为某种中间代码的语义翻译⽅法。
(2)掌握⽬前普遍采⽤的语义分析⽅法─语法制导翻译技术。
(3)给出 PL/0 ⽂法规范,要求在语法分析程序中添加语义处理,对于语法正确的表达式,输出其中间代码;对于语法正确的算术表达式,输出其计算值。
⼆、实验内容(1)语义分析对象重点考虑经过语法分析后已是正确的语法范畴,本实验重点是语义⼦程序。
已给 PL/0 语⾔⽂法,在实验⼆或实验三的表达式语法分析程序⾥,添加语义处理部分,输出表达式的中间代码,⽤四元式序列表⽰。
(2) PL/0 算术表达式的语义计算:PL/0 算术表达式,例如:2+35 作为输⼊。
输出: 17PL/0 表达式的中间代码表⽰:PL/0 表达式,例如: a(b+c)。
输出: (+,b,c,t1)(,a,t1,t2)三、设计思想1.原理属性⽂法:是在上下⽂⽆关⽂法的基础上为每个⽂法符号(终结符或⾮终结符)配备若⼲个相关的“值”(称为属性)。
属性:代表与⽂法符号相关的信息,和变量⼀样,可以进⾏计算和传递。
综合属性:⽤于“⾃下⽽上”传递信息。
在语法树中,⼀个结点的综合属性的值,由其⼦结点的属性值确定。
S—属性⽂法:仅仅使⽤综合属性的属性⽂法。
语义规则: 属性计算的过程即是语义处理的过程。
对于⽂法的每⼀个产⽣式配备⼀组属性的计算规则,则称为语义规则。
(1)终结符只有综合属性,它由词法分析器提供。
(2)⾮终结符既可以有综合属性也可以有继承属性,⽂法开始符号的所有继承属性作为属性计算前的初始值。
(3)产⽣式右边符号的继承属性和产⽣式左边符号的综合属性都必须提供⼀个计算规则。
(4)产⽣式左边符号的继承属性和产⽣式右边符号的综合属性由其它产⽣式的属性规则计算。
⼀遍扫描的处理⽅法: 与树遍历的属性计算⽅法不同,⼀遍扫描的处理⽅法是在语法分析的同时计算属性值,⽽不是语法分析构造语法树之后进⾏属性的计算,⽽且⽆需构造实际的语法树。
编译原理系列实验四语义分析与中间代码⽣成最后⼀次实验!⽬录实验四语义分析与中间代码⽣成实验⽬的通过上机实习,加深对语法制导翻译原理的理解,掌握将语法分析所识别的语法范畴变换为某种中间代码的语义翻译⽅法。
掌握⽬前普遍采⽤的语义分析⽅法──语法制导翻译技术。
给出 PL/0 ⽂法规范,要求在语法分析程序中添加语义处理,对于语法正确的表达式,输出其中间代码;对于语法正确的算术表达式,输出其计算值。
题⽬【问题描述】在实验⼆或实验三的表达式语法分析程序⾥,添加语义处理部分。
对于语法正确的表达式,输出其中间代码,⽤四元式序列表⽰;对于语法正确的算术表达式,输出其计算值。
例如:当输⼊为2+35时,程序输出为17;当输⼊为a(b+c)时,程序输出为四元式:(+,b,c,t1)(,a,t1,t2)要求源程序能智能判断这两种情况,并输出相应结果。
【输⼊形式】(1) PL/0算术表达式的语义计算。
PL/0算术表达式,例如:2+35作为输⼊。
(2)PL/0表达式的中间代码表⽰。
输⼊:PL/0表达式,例如: a*(b+c)。
【输出形式】2+35作为输⼊时,输出为17a(b+c)作为输⼊时,输出为(+,b,c,t1)(*,a,t1,t2)源程序#include <iostream>#include<bits/stdc++.h>using namespace std;/**词法分析及其结果存储**/pair<string, string> lexRes[50]; // 词法分析结果,每个pair的first如"ident",second如"a"int lexI = 0; // lexRes的指针void lexical()/*词法分析:读⼊⼀⾏字符串,处理该字符串的词法分析结果⾄lexRes*//*lexI终为lexRes的长度,即单词数*/{// 读⼊输⼊串string inputs; // 如,a*(b+c)cin >> inputs;// 初始化词典map<string,string> words;std::map<string,string>::iterator it;words["+"]="plus";words["-"]="minus";words["*"]="times";words["/"]="slash";words["="]="eql";words["("]="lparen";words[")"]="rparen";// 开始分析int insize=inputs.length();string word; // 输⼊符号,如"a"/"123"{// 空⽩符跳过while(inputs[i] == ' ' || inputs[i] == '\n')i++;// 标志符/基本字捕捉if(isalpha(inputs[i])){// 拿出⼀个标志符/基本字word = inputs[i++];while(isalpha(inputs[i]) || isdigit(inputs[i]))word += inputs[i++];// 在map中找到相应的词性,并输出it = words.find(word);if(it != words.end())lexRes[lexI++] = make_pair(words[word], word);// cout << "(" << words[word] << "," << word << ")" << endl; elselexRes[lexI++] = make_pair("ident", word);// cout << "(ident" << "," << word << ")" << endl;i--;}// 常数else if(isdigit(inputs[i])){// 拿出常数word=inputs[i++];while(isdigit(inputs[i]))word+=inputs[i++];lexRes[lexI++] = make_pair("number", word);//cout << "(number" << "," << word << ")" << endl;i--;}// <、<=号else if(inputs[i]=='<'){word=inputs[i++];if(inputs[i]=='>'){word+=inputs[i];lexRes[lexI++] = make_pair(words[word], word);// cout << "(" << words[word] << "," << word << ")" << endl; }else if(inputs[i]=='='){word+=inputs[i];lexRes[lexI++] = make_pair(words[word], word);// cout << "(" <<words[word] << "," << word << ")" << endl; }else if(inputs[i]!=' '||!isdigit(inputs[i])||!isalpha(inputs[i])){lexRes[lexI++] = make_pair(words[word], word);// cout << "(" << words[word] << "," << word << ")" << endl; }else{//cout << "error!" << endl;}i--;}// >、>=else if(inputs[i]=='>'){word=inputs[i++];if(inputs[i]=='='){word+=inputs[i];lexRes[lexI++] = make_pair(words[word], word);// cout<<"("<<words[word]<<","<<word<<")"<<endl;}else if(inputs[i]!=' '||!isdigit(inputs[i])||!isalpha(inputs[i])){lexRes[lexI++] = make_pair(words[word], word);// cout<<"("<<words[word]<<","<<word<<")"<<endl;}else{//cout<<"error!"<<endl;}i--;}//:=else if(inputs[i]==':'){word=inputs[i++];if(inputs[i]=='='){word+=inputs[i];lexRes[lexI++] = make_pair(words[word], word);// cout<<"("<<words[word]<<","<<word<<")"<<endl;}else{//cout<<"error!"<<endl;}//i--;}//其他的基本字word=inputs[i];it=words.find(word);if(it!=words.end()){lexRes[lexI++] = make_pair(words[word], word);// cout<<"("<<words[word]<<","<<word<<")"<<endl; }else{//cout<<"error!"<<endl;}}}}/**四元式相关,被调⽤**/struct quad{string result;string arg1;string arg2;string op;};struct quad quad[50]; // 四元式数组int quaI = 0; // 指向四元式的指针void emit(string op, string arg1, string arg2, string result)/*发射⼀⾏四元式*/{quad[quaI].op = op;quad[quaI].arg1 = arg1;quad[quaI].arg2 = arg2;quad[quaI].result = result;quaI++;}int tI = 1; // 记录当前是t1/t2...t⼏了string newT()/*产⽣⼀个t1/t2...*/{stringstream ss;ss << tI;string ti = "t" + ss.str();tI++;return ti;}/**⾮算数表达式的递归下降分析及四元式⽣成**/// 指针前进int sym=0; // 正在处理的单词void advance(){++sym;if(sym > lexI){cout << "ERROR!sym指针越界";exit(0);}}string E();string T();string F();string F()/*因⼦分析*/{string arg;if(lexRes[sym].first == "ident"){arg = lexRes[sym].second;advance();}else if(lexRes[sym].first == "number"){arg = lexRes[sym].second;advance();}else if(lexRes[sym].first == "lparen"){advance();arg = E();if(lexRes[sym].first == "rparen"){advance();}else{cout << "ERROR!未能匹配右括号!语法错误\n";exit(0);}}}string T()/*项分析*/{string op, arg1, arg2, result;arg1 = F();while(lexRes[sym].first == "times" || lexRes[sym].first == "slash"){ op = lexRes[sym].second;advance();arg2 = F();result = newT();emit(op, arg1, arg2, result);arg1 = result;}return arg1;}string E()/*表达式分析*/{string op, arg1, arg2, result;if(lexRes[sym].first == "plus" || lexRes[sym].first == "minus"){advance();}arg1 = T();while(lexRes[sym].first == "plus" || lexRes[sym].first == "minus"){ op = lexRes[sym].second;advance();arg2 = T();result = newT();emit(op, arg1, arg2, result);arg1 = result;}return arg1;}/**算数表达式的递归下降分析及四元式⽣成**/int E_();int T_();int F_();int F_(){int arg;if(lexRes[sym].first == "ident"){cout << "算数表达式含变量,⽆法计算\n";exit(0);}else if(lexRes[sym].first == "number"){arg = atoi(lexRes[sym].second.c_str());advance();}else if(lexRes[sym].first == "lparen"){advance();arg = E_();if(lexRes[sym].first == "rparen"){advance();}else{cout << "ERROR!未能匹配右括号!语法错误\n";exit(0);}}return arg;}int T_()/*项分析*/{string op;int arg1, arg2, result;arg1 = F_();while(lexRes[sym].first == "times" || lexRes[sym].first == "slash"){ op = lexRes[sym].second;advance();arg2 = F_();if(op == "*"){result = arg1 * arg2;arg1 = result;}else{result = arg1 / arg2;arg1 = result;}else {cout << "除数为0,出错!\n";exit(0);}}}return arg1;}int E_()/*表达式分析*/{string op;int arg1, arg2, result;if(lexRes[sym].first == "plus" || lexRes[sym].first == "minus"){advance();}arg1 = T_();while(lexRes[sym].first == "plus" || lexRes[sym].first == "minus"){op = lexRes[sym].second;advance();arg2 = T_();if(op == "+"){result = arg1 + arg2;arg1 = result;}else{result = arg1 - arg2;arg1 = result;}}return arg1;}int main(){lexical();if(lexRes[0].first == "number"){cout << E_();}else{E();for(int i=0; i<quaI; i++){cout<<'('<<quad[i].op<<','<<quad[i].arg1<<','<<quad[i].arg2<<','<<quad[i].result<<')'<<endl; }}return 0;}。
编译原理语义分析与中间代码生成实验报告专题6_语法制导翻译程序设计原理与实现技术***-***** 李若森计科1301一、实验目的语法制导的基本概念;目标代码结构分析的基本方法;赋值语句语法制导生成四元式的基本原理和方法;该过程包括语法分析和语义分析过程。
二、实验内容2.1 实验项目完成以下描述赋值语句和算术表达式文法的语法制导生成中间代码四元式的过程。
G[A]:A→V=EE→E+T|E-T|T T→T*F|T/F|F F→(E)|i V→i2.2 设计说明终结符号i为用户定义的简单变量,即标识符的定义。
2.3 设计要求(1) 设计语法制导翻译过程,给出每一产生式对应的语义动作;(2) 设计中间代码四元式的结构(暂不与符号表有关);(3) 输入串应是词法分析的输出二元式序列,即某算术表达式“专题1”的输出结果。
输出为输入串的四元式序列中间文件;(4) 设计两个测试用例(尽可能完备),并给出程序执行结果。
2.4 任务分析重点解决赋值语句文法的改写和语义动作的添加。
三、实现过程3.1 扩展文法G[s]:S→AA→V=EE→E+T|E-T|T T→T*F|T/F|F F→(E)|i V→i3.2 非终结符FOLLOW集FOLLOW(S) = { # } FOLLOW(A) = { # } FOLLOW(V) = { = }FOLLOW(E) = { +, -, ), # }FOLLOW(T) = { +, -, *, /, ), # } FOLLOW(F) = { +, -, *, /, ), # }3.3 LR(0)分析器的构造设DFA M的一个状态为i,该状态识别出的所有活前缀的有效项目集为Ci。
则DFA M的状态集Q={C0, C1, C2, … , Cn}=C。
C称为文法的LR(0)有效项目集规范族。
对Ci有三种操作:求文法的LR(0)有效项目集规范族C的算法:由上述算法可求得有效项目集规范族C={C0, C1, C2, … , C19}。
语义分析及中间代码生成程序设计原理与实现技术--实验报告及源代码北京交通大学语义分析及中间代码生成程序设计原理与实现技术XXX 1028XXX2 计科1XXX班1. 程序功能描述完成以下描述赋值语句和算术表达式文法的语法制导生成中间代码四元式的过程。
G[A]:A?V:=EE?E+T?E-T?T?T*F?T/F?FF?(E)?iV?i说明:终结符号i 为用户定义的简单变量,即标识符的定义。
2. 设计要求(1)给出每一产生式对应的语义动作;(2)设计中间代码四元式的结构(暂不与符号表有关)。
(3)输入串应是词法分析的输出二元式序列,即某算术表达式“实验项目一”的输出结果。
输出为输入串的四元式序列中间文件。
(4)设计两个测试用例(尽可能完备),并给出程序执行结果四元式序列。
3. 主要数据结构描述:本程序采用的是算符优先文法,文法以及算符优先矩阵是根据第四次实验来修改的,所以主要的数据结构也跟第四次差不多,主要为文法的表示,FirstVT集和LastVT集以及算符优先矩阵:struct info{char left;vector<string> right;vector<char> first;vector<char> last;};算符优先矩阵采用二维字符数组表示的:char mtr[9][9]; //算符优先矩阵4. 程序结构描述:本程序一共有8功能函数:void get(); //获取文法void print(); //打印文法void fun(); //求FirstVT 和 LastVTvoid matrix(); //求算符优先矩阵void test(); //测试文法int cmp(char a,char b); 比较两个运算符的优先级 1 0 -1void out(char now,int avg1,int avg2); //打印四元式a,int b); //定义四元式计算方法 int ope(char op,int 5. 实验代码详见附件6. 程序测试6.1 功能测试程序运行显示如下功能菜单:选择打印文法:选择构造FirstVt集和LastVT集:选择构造算符优先矩阵:6.2 文法测试测试1:1+2*3测试2:2+3+4*5+(6/2)7. 学习总结本次实验完成了语义及中间代码生成的设计原理与实现,所采用的方法为算符优先分析方法,首先根据文法求出此文法的FirstVT集和LastVT集,然后根据他们求出此文法的算符优先矩阵。
由于此文法和第四次文法基本相同,只是多了一条赋值语句,所以采用的规则和第四次基本相同。
在分析阶段,每当遇到有规约的项目,判断一下,打印出此部运算的四元式,这样一步一步分析,知道输入的算术表达式计算分析完毕。
由于本次实验部分代码和第四次实验的代码比较相似,只需增加一点四元式的分析计算打印过程,就能够顺利完成本次实验。
通过这次实验,我对语义分析以及中间代码部分有了一定的提高,对以后的学习有了一定程度上的帮助。
// lb6.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h" #include <iostream> #include <string> #include <VECTOR> #include <stack>using namespace std;struct info{char left;vector<string> right; vector<char> first; vector<char> last; };vector<info> lang; char mtr[9][9]; //算符优先矩阵stack<char> sta;void get(); //获取文法void print(); //打印文法void fun(); //求FirstVT 和 LastVT void matrix(); //求算符优先矩阵void test(); //测试文法int cmp(char a,char b); //比较两个运算符的优先级 10 -1void out(char now,int avg1,int avg2); //打印四元式int ope(char op,int a,int b); //定义四元式计算方法int main(){int choose;while(1){cout << "****************************************" << endl;cout << " 获取文法请按 1" << endl;cout << " 打印文法请按 2" << endl;cout << " 构造FirstVT集和LastVT集请按 3" << endl;cout << " 构造优先关系矩阵请按 4" << endl;cout << " 文法测试请按 5" << endl;cout << " 结束请按 0" << endl;cout << "****************************************" << endl; cout << endl;cin >> choose;if(choose == 0)break;switch(choose){case 1: get(); break;case 2: print(); break;case 3: fun(); break;case 4: matrix(); break;case 5: test(); break;default:break;}}return 0;}void get(){info temp,temp1,temp2;temp.left = 'E';temp.right.push_back("E+T");temp.right.push_back("E-T");temp.right.push_back("T");temp.right.push_back("i");temp1.left = 'T';temp1.right.push_back("T*F");temp1.right.push_back("T/F");temp1.right.push_back("F");temp2.left = 'F';temp2.right.push_back("(E)");temp2.right.push_back("i");lang.push_back(temp);lang.push_back(temp1);lang.push_back(temp2);cout << "****************************************" << endl; cout << " 文法获取完成" << endl;cout << "****************************************" << endl; cout << endl;}void print(){cout << "****************************************" << endl; for(int i = 0;i < lang.size();i ++){for(int j = 0;j < lang[i].right.size();j ++){cout << lang[i].left << " --> ";cout << lang[i].right[j] << endl;}}cout << "****************************************" << endl; cout << endl;}void fun(){int i,j,sign = 0,sign1 = 0;for(i = 0;i < lang.size();i ++){for(j = 0;j < lang[i].right.size();j ++){string temp = lang[i].right[j]; //获取右部if(temp[0] > 'Z' || temp[0] < 'A'){ //终结符lang[i].first.push_back(temp[0]);}else if(temp.length() >= 2){ //终结符if(temp[1] > 'Z' || temp[1] < 'A'){lang[i].first.push_back(temp[1]);}}}}for(i = 0;i < lang.size();i ++){for(j = 0;j < lang[i].right.size();j ++){string temp = lang[i].right[j]; //获取右部if((temp[0] > 'Z' || temp[0] < 'A') && temp.length() == 1){ // 终结符lang[i].last.push_back(temp[0]);}else if(temp.length() >= 3){ //终结符if(temp[1] > 'Z' || temp[1] < 'A')lang[i].last.push_back(temp[1]);else if(temp[2] > 'Z' || temp[2] < 'A') //终结符lang[i].last.push_back(temp[2]);}}}while(sign == 0){ //迭代FirstVTsign = 1;for(i = 0;i < lang.size();i ++){for(j = 0;j < lang[i].right.size();j ++){string temp = lang[i].right[j]; //获取右部if(temp.length() == 1 && (temp[0] <= 'Z' && temp[0] >= 'A')){//可以迭代for(int k = 0;k < lang.size();k ++){if(lang[k].left == temp[0]){ //找到了,添加元素for(int p = 0;p < lang[k].first.size();p ++){sign1 = 0;char ch = lang[k].first[p];for(int q = 0;q < lang[i].first.size();q++){if(lang[i].first[q] == ch){ //包含了sign1 = 1;}}if(sign1 == 0){lang[i].first.push_back(ch);sign = 0;}}}}}}}}sign = 0;while(sign == 0){ //迭代LastVTsign = 1;for(i = 0;i < lang.size();i ++){for(j = 0;j < lang[i].right.size();j ++){string temp = lang[i].right[j]; //获取右部if(temp.length() == 1 && (temp[0] <= 'Z' && temp[0] >= 'A')){//可以迭代for(int k = 0;k < lang.size();k ++){if(lang[k].left == temp[0]){ //找到了,添加元素for(int p = 0;p < lang[k].last.size();p ++){sign1 = 0;char ch = lang[k].last[p];for(int q = 0;q < lang[i].last.size();q++){if(lang[i].last[q] == ch){ //包含了sign1 = 1;}}if(sign1 == 0){lang[i].last.push_back(ch);sign = 0;}}}}}}}}cout << "****************************************" << endl; cout << "FirstVT:" << endl;for(i = 0;i < lang.size();i ++){cout << lang[i].left << " : ";for(j = 0;j < lang[i].first.size();j ++){cout << lang[i].first[j] << " ";}cout << endl;}cout << endl;cout << "LasttVT:" << endl;for(i = 0;i < lang.size();i ++){cout << lang[i].left << " : ";for(j = 0;j < lang[i].last.size();j ++){cout << lang[i].last[j] << " ";}cout << endl;}cout << "****************************************" << endl; cout << endl;}void matrix(){int i,j;for(i = 0;i < 9;i ++){ //初始化for(j = 0;j < 9;j ++){mtr[i][j] = 'n';}}string temp = "+-*/()i#";for(i = 1;i < 9;i ++){mtr[i][0] = temp[i - 1];mtr[0][i] = temp[i - 1]; }vector<string> str;for(i = 0;i < lang.size();i ++){ //aU a < FirstVT(U)for(j = 0;j < lang[i].right.size();j ++){string ss = lang[i].right[j];string ok = "";if(ss.length() > 2){if((ss[0] > 'Z' || ss[0] < 'A') && (ss[1] <= 'Z' && ss[1] >= 'A')){ //aUok = "";ok += ss[0];ok += ss[1];str.push_back(ok);}if((ss[1] > 'Z' || ss[1] < 'A') && (ss[2] <= 'Z' && ss[2] >= 'A')){ //aUok = "";ok += ss[1];ok += ss[2];str.push_back(ok);}}}}for(i = 0;i < str.size();i ++){for(j = 1;j < 9;j ++){if(mtr[j][0] == str[i][0]){ //Find a Then Find FirstVt(U) for(int k = 0;k < lang.size();k ++){if(lang[k].left == str[i][1]){ //Find Ufor(int p = 0;p < lang[k].first.size();p ++){for(int q = 1;q < 9;q ++){if(mtr[q][0] == lang[k].first[p]){mtr[j][q] = '<';}}}}}}}}str.clear();for(i = 0;i < lang.size();i ++){ //Ua LastVT(U) > afor(j = 0;j < lang[i].right.size();j ++){string ss = lang[i].right[j];string ok = "";if(ss.length() > 2){if((ss[1] > 'Z' || ss[1] < 'A') && (ss[0] <= 'Z' && ss[0] >= 'A')){ //Uaok = "";ok += ss[0];ok += ss[1];str.push_back(ok);}if((ss[2] > 'Z' || ss[2] < 'A') && (ss[1] <= 'Z' && ss[1] >= 'A')){ //Uaok = "";ok += ss[1];ok += ss[2];str.push_back(ok);}}}}for(i = 0;i < str.size();i ++){for(j = 1;j < 9;j ++){if(mtr[0][j] == str[i][1]){ //Find a Then Find LastVt(U)for(int k = 0;k < lang.size();k ++){if(lang[k].left == str[i][0]){ //Find Ufor(int p = 0;p < lang[k].last.size();p ++){for(int q = 1;q < 9;q ++){if(mtr[0][q] == lang[k].last[p]){mtr[q][j] = '>';}}}}}}}}str.clear();for(i = 0;i < lang.size();i ++){ //ab aUb a = bfor(j = 0;j < lang[i].right.size();j ++){string ss = lang[i].right[j];string ok = "";if(ss.length() > 2){if((ss[1] > 'Z' || ss[1] < 'A') && (ss[0] > 'Z' || ss[0] < 'A')){ //aaok = "";ok += ss[0];ok += ss[1];str.push_back(ok);}if((ss[2] > 'Z' || ss[2] < 'A') && (ss[1] > 'Z' || ss[1] < 'A')){ //aaok = "";ok += ss[1];ok += ss[2];str.push_back(ok);}if((ss[2] > 'Z' || ss[2] < 'A') && (ss[0] > 'Z' || ss[0] < 'A')){ //aUaok = "";ok += ss[0];ok += ss[2];str.push_back(ok);}}}}for(i = 0;i < str.size();i ++){for(j = 1;j < 9;j ++){if(str[i][0] == mtr[j][0]){for(int k = 1;k < 9;k ++){if(mtr[0][k] == str[i][1]){mtr[j][k] = '=';}}}}}for(i = 0;i < lang[0].first.size();i ++){ //#for(j = 1;j < 9;j ++){if(lang[0].first[i] == mtr[0][j]){mtr[8][j] = '<';}}}for(i = 0;i < lang[0].first.size();i ++){ //#for(j = 1;j < 9;j ++){if(lang[0].first[i] == mtr[j][0]){mtr[j][8] = '>';}}}mtr[8][8] = '=';cout << "****************************************" << endl; for(i = 0;i < 9;i ++){for(j = 0;j < 9;j ++){if(mtr[i][j] != 'n')cout << mtr[i][j] << " ";elsecout << " ";}cout << endl;}cout << "****************************************" << endl; cout << endl;}void test(){cout << "****************************************" << endl; cout << "请输入算术表达式:" << endl;string str;cin >> str;str += '#';int i,j,k;stack<int> data;stack<char> op;op.push('#');char now = 'n'; //记录当前栈顶操作符int sign = 0;for(i = 0;i < str.length();i ++){sign = 0;if(str[i] >= '0' && str[i] <= '9'){ //操作数int temp = str[i] - '0';data.push(temp);}else{ //运算符op.push(str[i]);sign = 1;}if(now != 'n' && sign == 1){ //有可比性,并且操作符栈有更新if(!op.empty()){char top = op.top(); //栈顶元素while(cmp(now,top) == 1){ //需要规约int avg1 = data.top();data.pop();int avg2 = data.top();data.pop();out(now,avg2,avg1); //打印四元式data.push(ope(now,avg2,avg1));op.pop();op.pop();if(!op.empty()){now = op.top();}else{now = 'n';}op.push(top);}if(cmp(now,top) == 0){ op.pop();op.pop();if(!op.empty()){now = op.top();}else{char temp = '=';if(!data.empty()){int da = data.top(); out(temp,da,0);}}}}}else{ //不需要比较if(!op.empty()){now = op.top();}}}}int cmp(char a,char b){int i,j;for(i = 1;i < 9;i ++){if(mtr[i][0] == a){for(j = 1;j < 9;j ++){if(mtr[0][j] == b){if(mtr[i][j] == '>'){ return 1;}else if(mtr[i][j] == '='){ return 0;}else if(mtr[i][j] == '<'){ return -1;}}}}}return 2;}void out(char now,int avg1,int avg2){cout << "****************************************" << endl;cout << now << " ," << avg1 << " ," << avg2 << " ," <<ope(now,avg1,avg2)<< endl;cout << "****************************************" << endl;cout << endl; }int ope(char op,int a,int b){if(op == '+'){return a + b; }if(op == '-'){return a - b;}if(op == '*'){return a * b; }if(op == '/'){return a / b; }if(op == '='){return a;}return 0;}。