写在前面:本博客为本人原创,严禁任何形式的转载!本博客只允许放在博客园(.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. MeasureSpec 的三中类型

    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools=&qu ...

  2. FTP实验

    一.安装 sudo apt-get install vsftpd service vsftpd start 启动vsftpd服务 如果在不设置任何的情况下,可以以匿名的方式访问该ftp. 这时候你可以 ...

  3. 跟Python打包相关的一些文章

    6 things I learned about setuptools Python 101: easy_install or how to create eggs « The Mouse Vs. T ...

  4. Android——Android和SVN::::SVN+delete项目

    SVN使用笔记(比较详细) http://www.cnblogs.com/merray/p/4182380.html 删除项目 http://jingyan.baidu.com/article/c74 ...

  5. JVM内存管理及垃圾回收【转】

    很多Java面试的时候,都会问到有关Java垃圾回收的问题,提到垃圾回收肯定要涉及到JVM内存管理机制,Java语言的执行效率一直被C.C++程序员所嘲笑,其实,事实就是这样,Java在执行效率方面确 ...

  6. Entity Framework定义外键,限制通过migration命令自动更改字段名称

    1.问题 在定义一个表的外键时,通过add-migration命令生成,并通过update-database更新到数据库,发现外键名称发生了重命名.举例说明: 人员表[User](Id,Name,Pa ...

  7. 导出表结构sql语句

    -- C:/dba必需是已经存在的目录 -- create or replace directory UTL_DIR as 'C:\dba'; --用sys用户登录给要访问的用户指定访问目录的权限gr ...

  8. Java知多少(36)内部类及其实例化

    在 Java 中,允许在一个类(或方法.语句块)的内部定义另一个类,称为内部类(Inner Class),有时也称为嵌套类(Nested Class). 内部类和外层封装它的类之间存在逻辑上的所属关系 ...

  9. python3二元Logistics Regression 回归分析(LogisticRegression)

    纲要 boss说增加项目平台分析方法: T检验(独立样本T检验).线性回归.二元Logistics回归.因子分析.可靠性分析 根本不懂,一脸懵逼状态,分析部确实有人才,反正我是一脸懵 首先解释什么是二 ...

  10. windows下svn钩子实现每次提交更新至web目录

    目的 找 到SVN Server中的仓库(Repositories)文件夹的位置,在相应的项目文件夹中找到hooks文件夹.在该文件夹中添加一个post- commit文件:当有commit动作发生时 ...