编译原理课程设计算术表达式forwhile语句转换为四元式Word下载.docx
《编译原理课程设计算术表达式forwhile语句转换为四元式Word下载.docx》由会员分享,可在线阅读,更多相关《编译原理课程设计算术表达式forwhile语句转换为四元式Word下载.docx(37页珍藏版)》请在冰豆网上搜索。
id<
c
G->
id++
X->
id>
c
Y->
id––
H->
id1=id2+id3
id1=id2+c
id1=c+id2
其中c表示常数const,f表示关键字for,id表示一般标识符。
for循环体内部的表达式一般为算术表达式,而算术表达式转换为四元式的方法在第一部分已给出,此处H只考虑比较简单的情况。
2.for语句的LR(0)分析表如下:
3.基本算法流程:
本算法定义声明了两个结构体:
一个是Node结构体,其中char型的type中存储当前符号的类型,CString型的sValue中存储的为当前符号,int型的eValue只有在符号类型为数字的情况下才进行存储,存储数字的大小;
另一个为stack结构体,这个结构体是实现语法分析中的符号栈和状态栈使用的,并未这两个栈分别定义了各自的pop函数和push函数。
除此之外,本算法中的LR(0)分析表通过二维数组存储。
其中分为action表和goto表。
action表中的状态转换符号,用2-44表示,规约的符号,用101-110表示。
具体的算法流程图如下:
(三)while语句转换为四元式
1.while语句的文法如下:
(1)S->
while(B){E}
(2)E->
AE
(3)E->
A
(4)A->
iPA
(5)A->
i
(6)B->
iTi
(7)B->
其中while、(、)、{、}、P、T、;
和i均为终结符,而S、A、B、E这些大写字母均为非终结符。
T表示比较运算符,P表示算术运算符,i表示合法标识符。
2.While语句的LR(0)分析表如下:
3.基本算法流程:
本算法的基本思想与for语句转换成四元式的思想比较相似,都是对读入的语句进行词法分析,后再通过LR(0)分析表对语句进行语法分析,并同时输出四元式。
与for语句转换成四元式不同的是,while语句转换为四元式在结构体定义等方面做了改进。
首先是LR(0)分析表的存储方式进行了改进,本算法中为LR(0)分析表定义了一个table的结构体,将action和goto两个部分全部存入table的结构体中,是查表的时候更加方便。
除此之外,还定义了obj结构体,此结构体主要是为了存储所要输出的四元式,定义了此结构体之后,程序的调理变得更为清晰了。
本算法中符号栈以及状态栈的部分主要调用了c++中原有的stack结构体,使用其本身定义的pop函数以及push函数,简化的代码。
以下为算法的流程图:
(四)输入、输出以及界面设计
1.输入:
本程序的输入均为语句或表达式,若每次测试程序均输入表达式,则会输入大量式子,浪费时间。
所以本程序采用文件读入的形式,只需要在指定位置输入文件名即可。
2.输出:
本程序输出的四元式全部在MFC界面的文本框中显示。
可以复制,方便之后的使用。
3.界面设计:
本程序为了方便使用以及界面美观,使用了MFC中的TabControl控件,界面设计如下:
图中当前标签为“while语句”,显示的界面为“while语句转换为四元式”。
通过若点击其他标签按钮,界面也会切换到相应的界面。
每个界面都是一个对话框,如下图所示:
(1)CompilerDesignDlg.cpp作为主要的文件,去调用其他的对话框。
首先对每一个对话框(IDD_DIALOG1-3)进行设置,样式:
下层;
边框:
无。
如下图所示:
(2)后在CompilerDesignDlg.h文件中添加每个对话框的头文件,以及申明每个对话框,代码如下:
#include"
Dlg1.h"
Dlg2.h"
Dlg3.h"
CDlg1page1;
CDlg2page2;
CDlg3page3;
(3)在初始化函数CCompilerDesignDlg:
:
OnInitDialog()中编写相关代码:
m_tabCtrl.InsertItem(0,"
算术表达式"
);
m_tabCtrl.InsertItem(1,"
for语句"
m_tabCtrl.InsertItem(2,"
while语句"
page1.Create(IDD_DIALOG1,&
m_tabCtrl);
page2.Create(IDD_DIALOG2,&
page3.Create(IDD_DIALOG3,&
CRectrc;
m_tabCtrl.GetClientRect(&
rc);
rc.top+=22;
rc.bottom-=3;
rc.left+=2;
rc.right-=3;
//设置子对话框尺寸并移动到指定位置
page1.MoveWindow(&
page2.MoveWindow(&
page3.MoveWindow(&
page1.ShowWindow(true);
page2.ShowWindow(false);
page3.ShowWindow(false);
m_tabCtrl.SetCurSel(0);
(4)填写按钮响应函数,即实现点击按钮切换到相应界面的功能,双击Tab控件,创建函数,函数内代码实现如下:
voidCCompilerDesignDlg:
OnSelchangeTab1(NMHDR*pNMHDR,LRESULT*pResult)
{
intCurSel=m_tabCtrl.GetCurSel();
switch(CurSel)
{
case0:
page1.ShowWindow(true);
page2.ShowWindow(false);
page3.ShowWindow(false);
break;
case1:
page1.ShowWindow(false);
page2.ShowWindow(true);
case2:
page3.ShowWindow(true);
}
*pResult=0;
三、核心代码
(一)算术表达式转化为四元式
1.first_cc函数:
对括号中的乘除法进行处理。
voidCDlg1:
first_cc(inti,intm)
i++;
for(;
i<
=m-1;
i++)//处理乘除运算
if(str[i]=='
*'
||str[i]=='
/'
)
{
CStringstr00;
CStringstrget;
GetDlgItemText(IDC_OUT,strget);
CStringstr01=str[i];
CStringstr02=str[i-1];
CStringstr03=str[i+1];
CStringstr04=JG;
str00=str0+str01+str1+str02+str1+str03+str1+str04+str2;
SetDlgItemText(IDC_OUT,strget+str00);
change(i-1);
str[i-1]=str[i]=str[i+1]=JG;
sum--;
JG=(char)(int)JG++;
}
2.first_jj函数:
对括号内的加减法进行处理。
first_jj(intj,intm)
j++;
j<
j++)//处理加减运算
if(str[j]=='
+'
||str[j]=='
-'
CStringstr01=str[j];
CStringstr02=str[j-1];
CStringstr03=str[j+1];
change(j-1);
str[j-1]=str[j]=str[j+1]=JG;
3.scan函数:
用于从文件中读入表达式,并处理空格、回车、换行等。
并对表达式中的括号进行处理。
scan(FILE*fin)
intp[MAX];
charch='
a'
;
intc=-1,q=0;
while(ch!
=EOF)
ch=getc(fin);
while(ch=='
'
||ch=='
\n'
\t'
ch=getc(fin);
//消除空格和换行符
str[m++]=ch;
if(ch=='
='
)//统计含有以上字符的符号
sum++;
elseif(ch=='
('
p[++c]=m-1;
)'
q=m-1;
first_cc(p[c],q);
//从左括号处理到又括号
first_jj(p[c],q);
JG=(char)(int)JG--;
str[p[c]]=str[m-1]=JG;
c--;
4.tans_simple函数:
用于处理经过scan函数处理后的式子,根据其优先级的不同分别处理,并输出四元式。
trans_simple()
for(inti=0;
CStringstr01=str[i];
for(intj=0;
for(intk=0;
k<
k++)//处理赋值运算
if(str[k]=='
JG=(char)(int)--JG;
CStringstr01=str[k];
CStringstr02=str[k-1];
CStringstr03=str[k+1];
str00=str0+str01+str1+str03+str1+str1+str1+str02+str2;
change(k+1);
str[k-1]=JG;
work函数:
主要用于根据LR(0)分析表进行语法分析,并输出四元式。
voidCDlg2:
work()
CStringstr0="
("
CStringstr1="
"
CStringstr2="
)\r\n"
CStringzf;
charch,y;
intx,e,u,ok=1;
inti=0,index=0;
inth=0;
intr;
intk1=0;
charst[40];
CStringah[40];
stacks;
stackt;
SetDlgItemText(IDC_OUT,"
"
CStringin_s;
charin_c[100];
GetDlgItemText(IDC_FILENAME,in_s);
ifstreamiii(in_s);
iii>
>
in_c;
zf=in_c;
SetDlgItemText(IDC_DISPLAY,zf);
getSym(zf,i);
r=nodeSize;
CStringstr_cf;
CStringstr_c;
CStringstr_i;
intcount=0;
for(i=0;
i<
r;
i++)
st[i]=node[i].type;
if(st[i]=='
f'
GetDlgItemText(IDC_CF,str_cf);
CStringtemp_str3="
关键字:
for\r\n"
SetDlgItemText(IDC_CF,str_cf+temp_str3);
elseif(st[i]=='
i'
CStringtemp_str3=node[i].sValue;
str_i=str_i+temp_str3+"
elseif(st[i]=='
c'
str_c=str_c+temp_str3+"
number[count++]=node[i].sValue;
GetDlgItemText(IDC_CF,str_cf);
SetDlgItemText(IDC_CF,str_cf+"
符号:
+str_i+"
\r\n"
+"
常数:
+str_c+"
i++){
ah[i]=node[i].sValue;
//测试
Initstack(s);
Initstack(t);
push(s,'
#'
push2(t,0);
SetDlgItemText(IDC_YF,"
动作符号GOTO\r\n"
while(ok==1)
ch=st[index];
index++;
y=ch;
}'
){
y='
k1=action(1,14,y);
pop2(t,&
q);
push2(t,q);
u=action(q,14,y);
if(action(q,14,y)>
0&
&
action(q,14,y)<
45){
GetDlgItemText(IDC_YF,strget);
push(s,ch);
push2(t,zh);
CStringtemp_str1=ch;
CStringtemp_str2;
temp_str2.Format("
%d"
zh);
str00="
移进"
+temp_str1+"
+temp_str2+"
SetDlgItemText(IDC_YF,strget+str00);
100&
action(q,14,y)<
=110)
SetDlgItemText(IDC_YF,strget+"
进行规约\r\n"
switch(zh){
case101:
for(i=0;
12;
pop(s,&
y);
pop2(t,&
x);
}
push(s,'
S'
pop2(t,&
e);
push2(t,e);
go(e,7,'
//查询GOTO表
push2(t,sh);
//替换后的数字
index--;
break;
case102:
case103:
{
chara[3];
h=h+1;
3;
a[i]=pop(s,&
pop2(t,&
E'
CStringstr00;
CStringstrget;
GetDlgItemText(IDC_OUT,strget);
CStringstr01=a[1];
CStringstr02=a[0];
CStringstr03=a[2];
str00=str0+str01+str1+number[0]+str1+str1+str1+