. - -
电力学院
编译原理 课程实验报告
实验名称: 实验三 自下而上语法分析及语义分析
院 系: 计算机科学与技术学院 专业年级: 学生: 学号:
指导老师:
实验日期:
. 可修编-
. - -
实验三自上而下的语法分析
一、实验目的:
通过本实验掌握LR分析器的构造过程,并根据语法制导翻译,掌握属性文法的自下而上计算的过程。 二、实验学时:
4学时。 三、实验容
根据给出的简单表达式的语法构成规则(见五),编制LR分析程序,要求能对用给定的语法规则书写的源程序进行语法分析和语义分析。
对于正确的表达式,给出表达式的值。 对于错误的表达式,给出出错位置。 四、实验方法
采用LR分析法。
首先给出S-属性文法的定义(为简便起见,每个文法符号只设置一个综合属性,即该文法符号所代表的表达式的值。属性文法的定义可参照书137页表6.1),并将其改造成用LR分析实现时的语义分析动作(可参照书145页表6.5)。
接下来给出LR分析表。 然后程序的具体实现:
? LR分析表可用二维数组(或其他)实现。 ? 添加一个val栈作为语义分析实现的工具。
. 可修编-
. - -
? 编写总控程序,实现语法分析和语义分析的过程。
注:对于整数的识别可以借助实验1。 五、文法定义
简单的表达式文法如下: (1)E->E+T (2)E->E-T (3)E->T (4)T->T*F (5)T->T/F (6)T->F (7)F->(E) (8)F->i
状态 i 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 S5 S5 S5 S5 S5 S5 + S6 R3 R6 R8 S6 R1 R4 R7 R2 R5 - S12 R3 R6 R8 R12 R1 R4 R7 R2 R5 ACTION(动作) GOTO(转换) * S7 R6 R8 S7 R4 R7 S7 R5 / S13 R6 R8 S13 R4 R7 S13 R5 ( S4 S4 S4 S4 S4 S4 ) R3 R6 R8 S11 R1 R4 R7 R2 R5 # acc R3 R6 R8 R1 R4 R7 R2 R5 E 1 8 T 2 2 9 14 F 3 3 3 10 3 15 . 可修编-
. - -
五、处理程序例和处理结果例
示例1:20133191*(20133191+3191)+ 3191#
六、源代码
【cifa.h】
//cifa.h #include
//单词结构定义
. 可修编-
. - -
struct WordType{ int code; string pro;
};
//函数声明 WordType get_w(); void getch(); void getBC(); bool isLetter(); bool isDigit(); void retract(); int Reserve(string str); string concat(string str); 【Table.action.h】 //table_action.h class Table_action { int row_num,line_num; int lineName[8];
string tableData[16][8]; public:
. 可修编-
. - -
Table_action() { row_num=16; line_num=8; lineName[0]=30; lineName[1]=7; lineName[2]=13; lineName[3]=8; lineName[4]=14; lineName[5]=1; lineName[6]=2; lineName[7]=15; lineName[8]=0;
for(int m=0;m tableData[m][n]=\ tableData[0][0]=\ tableData[0][5]=\ tableData[1][1]=\ tableData[1][2]=\ tableData[1][7]=\ tableData[2][1]=\ . 可修编- . - - tableData[2][2]=\ tableData[2][3]=\ tableData[2][4]=\ tableData[2][6]=\ tableData[2][7]=\ tableData[3][1]=\ tableData[3][2]=\ tableData[3][3]=\ tableData[3][4]=\ tableData[3][6]=\ tableData[3][7]=\ tableData[4][0]=\ tableData[4][5]=\ tableData[5][1]=\ tableData[5][2]=\ tableData[5][3]=\ tableData[5][4]=\ tableData[5][6]=\ tableData[5][7]=\ tableData[6][0]=\ tableData[6][5]=\ tableData[7][0]=\ . 可修编- . - - tableData[7][5]=\ tableData[8][1]=\ tableData[8][2]=\ tableData[8][6]=\ tableData[9][1]=\ tableData[9][2]=\ tableData[9][3]=\ tableData[9][4]=\ tableData[9][6]=\ tableData[9][7]=\ tableData[10][1]=\ tableData[10][2]=\ tableData[10][3]=\ tableData[10][4]=\ tableData[10][6]=\ tableData[10][7]=\ tableData[11][1]=\ tableData[11][2]=\ tableData[11][3]=\ tableData[11][4]=\ tableData[11][6]=\ tableData[11][7]=\ . 可修编- . - - tableData[12][0]=\ tableData[12][5]=\ tableData[13][0]=\ tableData[13][5]=\ tableData[14][1]=\ tableData[14][2]=\ tableData[14][3]=\ tableData[14][4]=\ tableData[14][6]=\ tableData[14][7]=\ tableData[15][1]=\ tableData[15][2]=\ tableData[15][3]=\ tableData[15][4]=\ tableData[15][5]=\ tableData[15][6]=\ tableData[15][7]=\ } string getCell(int rowN,int lineN) { int row=rowN; int line=getLineNumber(lineN); . 可修编- . - - if(row>=0&&row return tableData[row][line]; else return\ } int getLineNumber(int lineN) { for(int i=0;i return i; return -1; } }; 【Table_go.h】 //table_go.h class Table_go { int row_num,line_num;//行数、列数 string lineName[3]; int tableData[16][3]; public: . 可修编- . - - Table_go(){ row_num=16; line_num=3; lineName[0]=\ lineName[1]=\ lineName[2]=\ for(int m=0;m tableData[m][n]=0; tableData[0][0]=1; tableData[0][1]=2; tableData[0][2]=3; tableData[4][0]=8; tableData[4][1]=2; tableData[4][2]=3; tableData[6][1]=9; tableData[6][2]=3; tableData[7][2]=10; tableData[12][1]=14; tableData[12][2]=3; . 可修编- . - - tableData[13][2]=15; } int getCell(int rowN,string lineNa) { int row=rowN; int line=getLineNumber(lineNa); if(row>=0&&row return tableData[row][line]; else return -1; } int getLineNumber(string lineNa) { for(int i=0;i return i; return -1; } }; 【Stack_num.h】 class Stack_num . 可修编- . - - { int i; //栈顶标记 int *data; //栈结构 public: Stack_num() //构造函数 { data=new int[100]; i=-1; } int push(int m) //进栈操作 { i++; data[i]=m; return i; } int pop() //出栈操作 { i--; return data[i+1]; } int getTop() //返回栈顶 { . 可修编- . - - return data[i]; } ~Stack_num() //析构函数 { delete []data; } int topNumber() { return i; } void outStack() { for(int m=0;m<=i;m++) cout< }; 【Stack_str.h】 class Stack_str { int i; //栈顶标记 string *data; //栈结构 public: . 可修编- . - - Stack_str() //构造函数 { data=new string[50]; i=-1; } int push(string m) //进栈操作{ i++; data[i]=m; return i; } int pop() //出栈操作 { data[i]=\ i--; return i; } string getTop() //返回栈顶 { return data[i]; } ~Stack_str() //析构函数 . 可修编- . - - { delete []data; } int topNumber() { return i; } void outStack() { for(int m=0;m<=i;m++) cout< }; 【cifa.cpp】 //cifa.cpp #include //关键字表和对应的编码 . 可修编- . - - string codestring[10]={\int codebook[10]={26,21,22,23,24,25,27,28,29}; //全局变量 char ch; int flag=0; /*//主函数 int main() { WordType word; cout<<\请输入源程序序列:\ word=get_w(); while(word.pro!=\为自己设置的结束标志 { cout<<\,\“\”\ word=get_w(); }; return 0; }*/ WordType get_w() . 可修编- . - - string str=\int code; WordType wordtmp; getch();//读一个字符 getBC();//去掉空白符 if(isLetter()){ //以字母开头 while(isLetter()||isDigit()){ str=concat(str); getch(); } retract(); code=Reserve(str); if(code==-1){wordtmp.code=0;wordtmp.pro=str;}//不是关键字 else{wordtmp.code=code;wordtmp.pro=str;}//是关键字 } else if(isDigit()){ //以数字开头 while(isDigit()){ str=concat(str); getch(); } retract(); . 可修编- { . - - wordtmp.code=30; wordtmp.pro=str; } else if(ch=='(') {wordtmp.code=1;wordtmp.pro=\ else if(ch==')') {wordtmp.code=2;wordtmp.pro=\else if(ch=='{') {wordtmp.code=3;wordtmp.pro=\else if(ch=='}') {wordtmp.code=4;wordtmp.pro=\else if(ch==';') {wordtmp.code=5;wordtmp.pro=\else if(ch=='=') {wordtmp.code=6;wordtmp.pro=\else if(ch=='+') {wordtmp.code=7;wordtmp.pro=\else if(ch=='*') {wordtmp.code=8;wordtmp.pro=\else if(ch=='>') {wordtmp.code=9;wordtmp.pro=\else if(ch=='<') {wordtmp.code=10;wordtmp.pro=\else if(ch==',') {wordtmp.code=11;wordtmp.pro=\else if(ch=='\\'') {wordtmp.code=12;wordtmp.pro=\else if(ch=='-') {wordtmp.code=13;wordtmp.pro=\ else if(ch=='/') {wordtmp.code=14;wordtmp.pro=\else if(ch=='#') {wordtmp.code=15;wordtmp.pro=\else if(ch=='|') {wordtmp.code=16;wordtmp.pro=\ else {wordtmp.code=100;wordtmp.pro=ch;} . 可修编- . - - return wordtmp; } void getch(){ if(flag==0) //没有回退的字符 ch=getchar(); else //有回退字符,用回退字符,并设置标志 flag=0; } void getBC(){ while(ch==' '||ch=='\\t'||ch=='\\n') ch=getchar(); } bool isLetter(){ if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z') return true; else return false; } bool isDigit(){ if(ch>='0'&&ch<='9') return true; else . 可修编- . - - return false; } string concat(string str){ return str+ch; } void retract(){ flag=1; } int Reserve(string str){ int i; for(i=0;i<=8;i++){ if(codestring[i]==str) //是某个关键字,返回对应的编码 return codebook[i]; } if(i==9) //不是关键字 return -1; } 【LR.cpp】 #include . 可修编- . - - #include\#include\#include\#include%using namespace std; void process(){ int stepNum=1; int topStat; Stack_num statusSTK; //状态栈 Stack_str symbolSTK; //符号栈 Stack_num valueSTK; //值栈 WordType word; Table_action actionTAB; //行为表 Table_go goTAB; //转向表 cout<<\请输入源程序,以#结束:\ word=get_w(); //总控程序初始化操作 symbolSTK.push(\ statusSTK.push(0); valueSTK.push(0); . 可修编- . - - cout<<\步骤\\t状态栈\\t符号栈\\t值栈\\t当前词\\t动作\\t转向\//分析 while(1) { topStat=statusSTK.getTop(); //当前状态栈顶 string act=actionTAB.getCell(topStat,word.code);//根据状态栈顶和当前单词 查到的动作 //输出 cout< statusSTK.outStack(); cout<<\symbolSTK.outStack(); cout<<\valueSTK.outStack(); cout<<\cout< //行为为“acc”,且当前处理的单词为#,且状态栈里就两个状态 //说明正常分析结束 if(act==\{ cout< cout<<\分析成功!\ cout<<\结果为:\return; . 可修编- . - - } //读到act表里标记为错误的单元格 else if(act==\{ cout< } //移进动作 else if(act[0]=='S') { int newstat=atoi(act.substr(1).c_str()); statusSTK.push(newstat); symbolSTK.push(word.pro); if(word.code==30)//整数,压入其值 valueSTK.push(atoi(word.pro.c_str())); else //其他单词,压入0占位 valueSTK.push(0); //输出 word=get_w(); cout< } . 可修编- . - - //规约动作 else if(act[0]=='R') { cout< string sn=act.substr(1);//产生式编号 //根据规约使用的产生式更新各个栈 if(sn==\ { statusSTK.pop();statusSTK.pop();statusSTK.pop(); symbolSTK.pop();symbolSTK.pop();symbolSTK.pop(); symbolSTK.push(\ int right_digit=valueSTK.pop(); valueSTK.pop(); int left_digit=valueSTK.pop(); int new_value=left_digit+right_digit; valueSTK.push(new_value); } else if(sn==\ { statusSTK.pop();statusSTK.pop();statusSTK.pop(); symbolSTK.pop();symbolSTK.pop();symbolSTK.pop(); symbolSTK.push(\ . 可修编- . - - int right_digit=valueSTK.pop(); valueSTK.pop(); int left_digit=valueSTK.pop(); int new_value=left_digit-right_digit; valueSTK.push(new_value); } else if(sn==\ { statusSTK.pop();statusSTK.pop();statusSTK.pop(); symbolSTK.pop();symbolSTK.pop();symbolSTK.pop(); symbolSTK.push(\ int right_digit=valueSTK.pop(); valueSTK.pop(); int left_digit=valueSTK.pop(); int new_value=left_digit*right_digit; valueSTK.push(new_value); } else if(sn==\ { statusSTK.pop();statusSTK.pop();statusSTK.pop(); symbolSTK.pop();symbolSTK.pop();symbolSTK.pop(); symbolSTK.push(\ . 可修编- . - - int right_digit=valueSTK.pop(); valueSTK.pop(); int left_digit=valueSTK.pop(); int new_value=left_digit/right_digit; valueSTK.push(new_value); } else if(sn==\ { statusSTK.pop(); symbolSTK.pop(); symbolSTK.push(\ } else if(sn==\ { statusSTK.pop(); symbolSTK.pop(); symbolSTK.push(\ } else if(sn==\ { statusSTK.pop();statusSTK.pop();statusSTK.pop(); symbolSTK.pop();symbolSTK.pop();symbolSTK.pop(); . 可修编- . - - } symbolSTK.push(\valueSTK.pop(); int digit_val=valueSTK.pop(); valueSTK.pop(); valueSTK.push(digit_val); else if(sn==\{ } else { } //实施go表中的动作 int next_status=goTAB.getCell(statusSTK.getTop(),symbolSTK.getTop()); statusSTK.push(next_status); //输出 cout< cout<<\分析程序出错!\return; statusSTK.pop(); symbolSTK.pop(); symbolSTK.push(\ . 可修编- . - - } else { cout<<\分析程序出错。\ return ; } } } int main() { char ch; do { system(\ process(); cout< cin>>ch; }while(ch=='y'); return 0; } . 可修编-