写在前面:本博客为本人原创,严禁任何形式的转载!本博客只允许放在博客园(.cnblogs.com),如果您在其他网站看到这篇博文,请通过下面这个唯一的合法链接转到原文!

本博客全网唯一合法URL:http://www.cnblogs.com/acm-icpcer/p/9173880.html

  基于C++语言实现的PL/0语言的算术表达式的自下而上的语法分析程序。该语言的其他语法实现思想与此一致,故不赘述。

  运行此程序前,必须先将代码通过:【编译原理】c++实现词法分析器的词法分析,生成词法表(词法表是txt文件,为了语法分析成功,务必删除文件中最后空着的一行,即文件末尾不可以留空白行)。生成的该词法表为此程序的必要输入。

  产生式:

  S->X(AX)*|AX(AX)*
    X->Y(MY)*
    Y->I|N|(S)
    A->+|-
    M->*|/
    C->=|#|<|<=|>|>=

  本次的代码主要是在【编译原理】c++实现自下而上语法分析器的基础上,伴随着归约的过程,增加了生成四元式的过程,也就是一边归约一边生成中间代码。

Talk is cheap, show you my source code:

/*
this code was first initiated by TZ,COI,HZAU
contact email:xmb028@163.com
personal website:wnm1503303791.github.io
personal blogs:www.cnblogs.com/acm-icpcer/
this code has been posted on my personal blog,checking url:www.cnblogs.com/acm-icpcer/p/9173880.html
Copyright 2018/6/12 TZ.
All Rights Reserved.
*/ #include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#include<fstream>
using namespace std; //预处理函数
bool preproccess(char *a,char *b,char *c)
{
int i1=,i2=;//i2为原串指针
memset(b,,'\0');
while(a[i2]!=',')
{
b[i1]=a[i2];
++i1,++i2;
}
b[i1]='\0'; i1=;i2++;
while(a[i2]!=')')
{
c[i1]=a[i2];
++i1,++i2;
}
c[i1]='\0';
//cout<<b<<endl;
return true;
} fstream f2("stack.txt", ios::out);//打开文件,供写
fstream f3("quaternary.txt", ios::out);//打开文件,供写
static int mcount=;//存储打印次数
//当移进或者归约时打印栈内情况,以供分析
bool outf(int head,char data[][],fstream &f)
{
f<<"times("<<mcount<<"),";
f<<"head is:"<<head<<endl;
for(int i=head;i>=;i--)
{
f<<data[i]<<endl;
}
mcount++;
f<<endl;
return true;
}
//四元式写入文件函数1
bool outf2(int top,char dt[][],fstream &f)
{
/*
char arg1[1024],arg2[1024],op[1024];
memset(arg1,sizeof(arg1),'\0');
strcpy(arg1,dt[top]);
memset(op,sizeof(op),'\0');
strcpy(op,dt[top-1]);
memset(arg2,sizeof(arg2),'\0');
strcpy(arg2,dt[top-2]); f<<"("<<op<<","<<arg1<<","<<arg2<<","<<"T"<<")"<<endl;
*/
f<<"("<<dt[top-]<<","<<dt[top]<<","<<dt[top-]<<","<<"T"<<")"<<endl;
return true;
}
//四元式写入文件函数2
bool outf3(int top,char dt[][],fstream &f)
{
f<<"("<<dt[top-]<<","<<dt[top]<<","<<"-"<<","<<"T"<<")"<<endl;
return true;
}
//四元式写入文件函数3
bool outf4(int top,char dt[][],fstream &f,char T)
{
f<<"("<<":="<<","<<dt[top]<<","<<"-"<<","<<T<<")"<<endl;
return true;
} //“策略”设计模式,面向对象方法
class presentation
{
private:
char data[][];//栈
char dt[][];//四元式栈
fstream *infile;//词法分析表
int head,top;//两个栈的栈顶指针
public:
//first initiated the object
presentation(fstream *in_f)
{
this->infile=in_f;
memset(data,sizeof(data),'\0');
memset(dt,sizeof(dt),'\0');
head=top=-;
}
bool push()
{
head++;
top++; infile->getline(data[head],);
char t1[],t2[];//存放字符标志
preproccess(data[head],t1,t2); cout<<data[head]<<","<<t1<<endl; memset(data[head],,'\0');
strcpy(data[head],t1); memset(dt[top],,'\0');
strcpy(dt[top],t2);
cout<<dt[top]<<","<<t2<<endl;
} /*
S->X(AX)*|AX(AX)*
X->Y(MY)*
Y->I|N|(S)
A->+|-
M->*|/
C->=|#|<|<=|>|>=
*/
//归约函数
bool reduce()
{
//S->X(AX)*|AX(AX)*
if( head>=&&
(!strcmp(data[head],"X"))&&
(!strcmp(data[head-],"plus")||!strcmp(data[head-],"minus"))&&
(!strcmp(data[head-],"X"))&&
(!strcmp(data[head-],"plus")||!strcmp(data[head-],"minus"))&&
(!strcmp(data[head-],"X"))
)
{
memset(data[head],,'\0');
memset(data[head-],,'\0');
memset(data[head-],,'\0');
memset(data[head-],,'\0');
memset(data[head-],,'\0');
head=head-+; strcpy(data[head],"S");//归约
/*
stack description:
top-> arg
op
top-2-> arg
op
arg
*/
if(outf2(top,dt,f3)&&outf2(top-,dt,f3))
{
top==-;
memset(dt,sizeof(dt),'\0');
} return true;
} if( head>=&&
(!strcmp(data[head],"X"))&&
(!strcmp(data[head-],"plus")||!strcmp(data[head-],"minus"))&&
(!strcmp(data[head-],"X"))
)
{
memset(data[head],,'\0');
memset(data[head-],,'\0');
memset(data[head-],,'\0');
head=head-+; strcpy(data[head],"S");
if(outf2(top,dt,f3))
{
top==-;
memset(dt,sizeof(dt),'\0');
} return true;
} if( head>=&&/*top>=3*/
(!strcmp(data[head],"plus")||!strcmp(data[head],"minus"))&&
(!strcmp(data[head-],"X"))&&
(!strcmp(data[head-],"plus")||!strcmp(data[head-],"minus"))&&
(!strcmp(data[head-],"X"))
)
{
memset(data[head],,'\0');
memset(data[head-],,'\0');
memset(data[head-],,'\0');
memset(data[head-],,'\0');
head=head-+; strcpy(data[head],"S");
if(outf3(top,dt,f3)&&outf3(top-,dt,f3))
{
top==-;
memset(dt,sizeof(dt),'\0');
} return true;
} if( head>=&&
(!strcmp(data[head],"plus")||!strcmp(data[head],"minus"))&&
(!strcmp(data[head-],"X"))
)
{
memset(data[head],,'\0');
memset(data[head-],,'\0');
head=head-+; strcpy(data[head],"S");
if(outf3(top,dt,f3))
{
top==-;
memset(dt,sizeof(dt),'\0');
} return true;
} //X->Y(MY)*
if( head>=&&
(!strcmp(data[head],"Y"))&&
(!strcmp(data[head-],"times")||!strcmp(data[head-],"slash"))&&
(!strcmp(data[head-],"Y"))&&
(!strcmp(data[head-],"times")||!strcmp(data[head-],"slash"))&&
(!strcmp(data[head-],"Y"))
)
{
memset(data[head],,'\0');
memset(data[head-],,'\0');
head=head-+; strcpy(data[head],"X");
/*
current stack description:
top-> arg
op
top-2-> arg
op
arg
*/
if(outf2(top,dt,f3)&&outf2(top-,dt,f3))
{
top==-;
memset(dt,sizeof(dt),'\0');
} return true;
} if( head>=&&
(!strcmp(data[head],"Y"))&&
(!strcmp(data[head-],"times")||!strcmp(data[head-],"slash"))&&
(!strcmp(data[head-],"Y"))
)
{
memset(data[head],,'\0');
memset(data[head-],,'\0');
memset(data[head-],,'\0');
head=head-+; strcpy(data[head],"X");
/*
current stack description:
top->arg
op
arg
*/
if(outf2(top,dt,f3))
{
top==-;
memset(dt,sizeof(dt),'\0');
} return true;
} if( head>=&&(!strcmp(data[head],"Y"))
)
{
memset(data[head],,'\0');
head=head-+; strcpy(data[head],"X");
if(outf4(top,dt,f3,'X'))
{
top==-;
memset(dt,sizeof(dt),'\0');
}
return true;
} //Y->I|N|(S)
if( head>=&&(!strcmp(data[head],"ident"))
)
{
memset(data[head],,'\0');
head=head-+; strcpy(data[head],"Y");
if(outf4(top,dt,f3,'Y'))
{
top==-;
memset(dt,sizeof(dt),'\0');
}
return true;
} if( head>=&&(!strcmp(data[head],"number"))
)
{
memset(data[head],,'\0');
head=head-+; strcpy(data[head],"Y");
if(outf4(top,dt,f3,'Y'))
{
top==-;
memset(dt,sizeof(dt),'\0');
}
return true;
} if( head>=&&
(!strcmp(data[head],"rparen"))&&
(!strcmp(data[head-],"S"))&&
(!strcmp(data[head-],"lparen"))
)
{
memset(data[head],,'\0');
memset(data[head-],,'\0');
memset(data[head-],,'\0');
head=head-+; strcpy(data[head],"Y");
return true;
} return false;
}
//遍历栈
bool visit_data()
{
cout<<"current stack:"<<endl;
for(int i=head;i>=;i--)
{
cout<<data[i]<<endl;
}
return true;
}
//主控函数
bool mainf()
{
while(!infile->eof())
{
push();
bool t=reduce();
outf(head,data,f2);
//每当移进结束时就检查一下是否有可规约串
while(t)//防止规约嵌套
{
t=reduce();
outf(head,data,f2);
}
//visit_data();
} visit_data(); bool flag=false;
for(int i=head;i>=;i--)
{
if(!strcmp(data[i],"S"))
{
flag=true;
}
if( strcmp(data[i],"S")&&
strcmp(data[i],"X")&&
strcmp(data[i],"A")&&
strcmp(data[i],"Y")&&
strcmp(data[i],"M")&&
strcmp(data[i],"C")
)
{
return false;
}
} return flag; /*
while(head>0)
{
bool t=reduce();
//每当移进结束时就检查一下是否有可规约串
while(t)//防止规约嵌套
{
t=reduce();
}
//visit_data();
outf(head,data,f2);
}
*/
}
}; int main()
{
fstream f1;
f1.open("lexical.txt", ios::in);//打开词法分析表,供读 presentation* s1=new presentation(&f1);
bool result=s1->mainf(); if(result)
cout<<"ACCEPTED!"<<endl;
else
cout<<"ERROR!"<<endl; f1.close();
f2.close();
return ;
}

运行示例:

(1)合法的语句:

(2)不合法的语句:

tz@COI HZAU

2018/6/12

【编译原理】c++实现自下而上语法分析及中间代码(四元式)生成的更多相关文章

  1. 现代编译原理——第二章:语法分析之LL(K)

    转自: http://www.cnblogs.com/BlackWalnut/p/4472122.html LL(K)语法分析技术是建立在预测分析的技术之上的.我们先来了解预测分析技术.考虑以下文法: ...

  2. 编译原理 #04# 中缀表达式转化为四元式(JavaScript实现)

    // 实验存档 运行截图: 代码中的总体转化流程:中缀表达式字符串→tokens→逆波兰tokens(即后缀表达式)→四元式. 由后缀表达式写出四元式非常容易,比较繁琐的地方在于中缀转逆波兰,这里采用 ...

  3. 编译原理实验之SLR1文法分析

    ---内容开始--- 这是一份编译原理实验报告,分析表是手动造的,可以作为借鉴. 基于  SLR(1) 分析法的语法制导翻译及中间代码生成程序设计原理与实现1 .理论传授语法制导的基本概念,目标代码结 ...

  4. 编译原理(一)绪论概念&文法与语言

    绪论概念&文法与语言 以老师PPT为标准,借鉴部分教材内容,AlvinZH学习笔记. 绪论基本概念 1. 低级语言:字位码.机器语言.汇编语言.与特定的机器有关,功效高,但使用复杂.繁琐.费时 ...

  5. MOOC 编译原理笔记(一):编译原理概述以及程序设计语言的定义

    编译原理概述 什么是编译程序 编译程序指:把某一种高级语言程序等价地转换成另一张低级语言程序(如汇编语言或机器代码)的程序. 高级语言程序-翻译->机器语言程序-运行->结果. 其中编译程 ...

  6. 编译原理_P1004

    龙书相关知识点总结 //*************************引论***********************************// 1. 编译器(compiler):从一中语言( ...

  7. python实现算术表达式的词法语法语义分析(编译原理应用)

    本学期编译原理的一个大作业,我的选题是算术表达式的词法语法语义分析,当时由于学得比较渣,只用了递归下降的方法进行了分析. 首先,用户输入算术表达式,其中算术表达式可以包含基本运算符,括号,数字,以及用 ...

  8. 《编译原理》控制流语句 if 和 while 语句的翻译 - 例题解析

    <编译原理>控制流语句 if 和 while 语句的翻译 - 例题解析 将 if 和 while 语句翻译成四元式 注:不同教材会有小差异,使用 _ 或者 - ,如果是 -,请注意区分 - ...

  9. Java 实现《编译原理》中间代码生成 -逆波兰式生成与计算 - 程序解析

    Java 实现<编译原理>中间代码生成 -逆波兰式生成与计算 - 程序解析 编译原理学习笔记 (一)逆波兰式是什么? 逆波兰式(Reverse Polish notation,RPN,或逆 ...

随机推荐

  1. request.GetResponse()超时的解决办法

    var request = (HttpWebRequest)WebRequest.Create(url); request.Timeout = Timeout.Infinite; request.Ke ...

  2. 如何修改mac的root密码

    mac如果密码忘了,可以同过几个命令重置root密码.前提是你有执行sudo权限的用户: jackdeMacBook-Air:~ jack$ sudo bash jackdeMacBook-Air:~ ...

  3. jquery ui autocomplete输入中文不自动完成的问题

    因为输入法或浏览器的问题,在输入中文后并没有触发自动完成,要再按多一下键盘才触发,查看发现它是用keydown来实现.bind("keydown.autocomplete", fu ...

  4. Java知多少(69)面向字节的输入输出流

    字节流以字节为传输单位,用来读写8位的数据,除了能够处理纯文本文件之外,还能用来处理二进制文件的数据.InputStream类和OutputStream类是所有字节流的父类. InputStream类 ...

  5. Java知多少(91)对话框

    对话框是为了人机对话过程提供交互模式的工具.应用程序通过对话框,或给用户提供信息,或从用户获得信息.对话框是一个临时窗口,可以在其中放置用于得到用户输入的控件.在Swing中,有两个对话框类,它们是J ...

  6. 【转】WPF自定义控件与样式(4)-CheckBox/RadioButton自定义样式

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等 本文主要内容: CheckBox复选框的自定义样式,有两种不同的风格实现: RadioB ...

  7. centos7 centos中apache运行php需要连接mysql一直连不上,telnet访问mysql出错Connection closed by foreign host

    执行命令: getsebool -a|grep httpd 发现 httpd_can_network_connect off 解决:  setsebool httpd_can_network_conn ...

  8. .net core 开发接口前端调用时提示错误 405

    解决方法: 在StartUp.cs文件中Configure(IApplicationBuilder app, IHostingEnvironment env)方法中添加如下代码: //跨域 app.U ...

  9. javascript +new Date()

    最近学习JavaScript时,看到Date的一个有意思的用法就是+new Date(),结果跟Date对象的getTime(),valueOf()是一样的,他们返回的都是1970年1月1日午夜以来的 ...

  10. 启动mysqld报 mysql the server quit without updating pid file

    查看mysql服务器的错误日志有一句: InnoDB: mmap(137363456 bytes) failed; errno 12 原来是内存不够用(需要131MB)呀,把my.cnf中的innod ...