标签:
LR1文法全智能分析
// by hfut yzk
#include "stdafx.h"
#include<fstream>
#include<string>
#include<map>
#include<vector>
#include<stack>
#include<set>
#include<cstring>
#include<queue>
using namespace std;
#pragma region vars
struct xiangmu //一个项目
{
int nump; //产生式编号
int id; //.的位置
string fst; //集合
};
map<char,int>getnum;
char getchars[100]; //获得对应字符
vector<string>proce; //产生式
int table[30][30]; //预测分析表 -1
int tb_s_r[30][30]; //是移进项还是规约项,-1,-2.
int num=0;int numvt=0; //numvt是终结符集合,0是‘#’,numvt表空字
string first[100]; //每个符号的first集
bool gotfirst[100]; //是否已经完成FIRST集合
string getp[100]; //获得某终结符在左边的产生式集合
vector<vector<xiangmu> >v; //项目集族
int e[100][3];
int head[100];
int nume=0; //链式前向星项目集族图
fstream cin ("H:/课程设计/编译原理2015/lr(1)/in.txt");
fstream cout ("H:/课程设计/编译原理2015/lr(1)/out.txt");
fstream cout2 ("H:/课程设计/编译原理2015/lr(1)/out2.txt");
#pragma endregion
#pragma region functions
void readin();
void getpp();
void dfsgetfirst(int nv,int nump);
void get_first();
void clear() ;
void addegde(int from,int to,int w) ;
inline bool xmeq(xiangmu a,xiangmu b);
bool isin(xiangmu a,vector<xiangmu> b) ; //xm a is in xmji b
bool xmjieq(vector<xiangmu> a,vector<xiangmu> b) ; //两个项目集是否相等
vector<xiangmu> hebing(vector<xiangmu>a ,vector<xiangmu>b) ; //合并项目集 a,b 复给 a
int xmji_isin_xmjizu(vector<xiangmu>a,vector<vector<xiangmu> >b) ; //查找项目集,若有,则返回编号,一举俩得
vector<xiangmu> get_close(xiangmu t) ; //对项目 T作闭包
void get_xiangmujizu() ; //获得项目集族
void print_xmjizu() ; //打印项目集族
bool get_table();
void print_table();
void print_now_state(int count,stack<int>state,stack<int>wd,int i);
bool analyze();
#pragma endregion
/*******************************************读入vt,vn,编号1-num,读入所有产生式*********************************************/
void readin()
{
memset(table,-1,sizeof(table));
getnum['#']=0;
getchars[0]='#';
//cout<<"请输入所有终结符:"<<endl;
char x;
do
{
cin>>x;
getnum[x]=++num;
getchars[num]=x;
}while(cin.peek()!='\n');
numvt=++num;
getnum['@']=numvt; //kong zi
getchars[num]=('@');
// cout<<"请输入非终结符集:"<<endl;
do
{
cin>>x;
getnum[x]=++num;
getchars[num]=x;
}while(cin.peek()!='\n');
// cout<<"输入所有产生式(空字用‘@’表示),以‘end’结束:"<<endl;
string pro;
while(cin>>pro&&pro!="end")
{
string ss;
ss+=pro[0];
for(int i=3;i<pro.size();i++)
{
if(pro[i]=='|')
{
proce.push_back(ss);
ss.clear();ss+=pro[0];
}
else
{
ss+=pro[i];
}
}
proce.push_back(ss);
}
}
void getpp()
{
for(int i=0;i<proce.size();i++)
{
int temp=getnum[proce[i][0]];
getp[temp]+=char('0'+i);
}
}
/****************************************************获得first集************************************************************/
void dfsgetfirst(int nv,int nump) //当前的符号,和对应产生式编号
{
int temp=getnum[proce[nump][1]]; //产生式推出来的首符
gotfirst[nump]=1; //标记
if(temp<=numvt)first[nv]+=char('0'+temp); //是终结符
else
{
for(int i=0;i<getp[temp].size();i++) //所有temp可以推出来的符号对应的产生式
{
if(proce[nump][0]==proce[nump][1])continue; //左递归的产生式不用不影响求fisrt集
dfsgetfirst(temp,getp[temp][i]-'0');
}
first[nv]+=first[temp]; //回溯时候沿途保存
}
}
void get_first()
{
for(int i=1;i<=numvt;i++) // 终结符first集合是它自己.
{
first[i]=char('0'+i);
}
for(int i=0;i<proce.size();i++)
{
if(proce[i][0]==proce[i][1])continue; //左递归的产生式不用不影响求fisrt集
if(gotfirst[i])continue; //已经生成。
int temp=getnum[proce[i][0]];
dfsgetfirst(temp,i);
}
}
/***************************************************添加边*****************************************************************/
void addegde(int from,int to,int w)
{
e[nume][0]=to;e[nume][1]=head[from];head[from]=nume;
e[nume++][2]=w;
}
/******************************************************初始化函数*********************************************************/
void clear()
{
for(int i=0;i<100;i++)
head[i]=-1;
for(int i=0;i<30;i++)
for(int j=0;j<30;j++)
tb_s_r[i][j]=table[i][j]=-1;
nume=0;
}
/******************************************************获得项目集族*******************************************************/
inline bool xmeq(xiangmu a,xiangmu b)
{
if(a.fst==b.fst&&a.id==b.id&&a.nump==b.nump)return 1;
return 0;
}
bool isin(xiangmu a,vector<xiangmu> b) //xm a is in xmji b
{
for(int i=0;i<b.size();i++)
{
if(xmeq(a,b[i]))return 1;
}
return 0;
}
vector<xiangmu> hebing(vector<xiangmu>a ,vector<xiangmu>b) //合并项目集 a,b 复给 a
{
for(int i=0;i<b.size();i++)
{
if(isin(b[i],a))continue;
else
a.push_back(b[i]);
}
return a;
}
bool xmjieq(vector<xiangmu> a,vector<xiangmu> b) //两个项目集是否相等
{
if(a.size()!=b.size())return 0;
for(int i=0;i<a.size();i++)
{
if(!isin(a[i],b))return 0;
}
return 1;
}
int xmji_isin_xmjizu(vector<xiangmu>a,vector<vector<xiangmu> >b) //查找项目集,若有,则返回编号,一举俩得
{
for(int i=0;i<b.size();i++)
{
if(xmjieq(a,b[i]))return i;
}
return -1;
}
vector<xiangmu> get_close(xiangmu t) //对项目 T作闭包
{
vector<xiangmu> temp;
temp.push_back(t);
queue<xiangmu> q; //bfs完成闭包
q.push(t);
while(!q.empty())
{
xiangmu cur=q.front();
q.pop();
if(cur.id==proce[cur.nump].size()) //归约项舍去
continue;
int tt=getnum[proce[cur.nump][cur.id]]; //tt is thm num of '.'zhihoudefuhao
if(tt<=numvt) continue ; //若是终结符,则不必找了
for(int i=0;i<getp[tt].size();i++) //对应产生式的编号
{
xiangmu c;
c.id=1; //
c.nump=getp[tt][i]-'0'; //
if(proce[cur.nump].size()-cur.id==1) // the last : A->BC.D,a/b
c.fst+=cur.fst;
else //not the last :A->B.CFb,a/b
{
int tttnum=getnum[proce[cur.nump][cur.id+1]];
c.fst+=first[tttnum];
}
if(!isin(c,temp)) //排重,新的项目就加入。
{
q.push(c);
temp.push_back(c);
}
}
}
return temp;
}
void get_xiangmujizu() //获得项目集族
{
vector<xiangmu>temp;
xiangmu t;
t.nump=0;t.id=1;t.fst+='0'; //初始的项目集:0
temp=get_close(t);
queue<vector<xiangmu> >q; //bfs法获得
q.push(temp);
v.push_back(temp); //第一个入
while(!q.empty())
{
vector<xiangmu> cur=q.front();
q.pop();
for(int i=1;i<=num;i++) //所有符号
{
if(i==numvt)continue; //'#'
vector<xiangmu> temp;
for(int j=0;j<cur.size();j++) //该项目集中的所有项目
{
if(cur[j].id==proce[cur[j].nump].size())continue; //是规约项目,无法再读入了
int tt=getnum[proce[cur[j].nump][cur[j].id]];
if(tt==i) //can read in 符号i
{
xiangmu tempt;
tempt.fst=cur[j].fst;
tempt.id=cur[j].id+1;
tempt.nump=cur[j].nump;
temp=hebing(temp,get_close(tempt));
}
}
if(temp.size()==0)continue; //该符号无法读入。
int numcur=xmji_isin_xmjizu(cur,v); //当前节点标号
int tttnum=xmji_isin_xmjizu(temp,v); //新目标标号
if(tttnum==-1) //新的项目集
{
v.push_back(temp);
q.push(temp);
addegde(numcur,v.size()-1,i) ; //添加边,权为读入的符号
}
else //老的项目集
{
addegde(numcur,tttnum,i);
}
}
}
}
/************************************************项目集族打印*********************************************************/
void print_xmjizu() //打印项目集族
{
for(int i=0;i<v.size();i++)
{
cout<<"项目集"<<i<<":"<<endl;
for(int j=0;j<v[i].size();j++)
{
cout<<proce[v[i][j].nump]<<" "<<v[i][j].id<<" "<<v[i][j].fst<<endl;
}
cout<<endl;
}
for(int i=0;i<v.size();i++)
{
for(int j=head[i];j!=-1;j=e[j][1])
{
cout<<" "<<getchars[e[j][2]]<<endl;
cout<<i<<"--->"<<e[j][0]<<endl;
}
}
}
/*********************************获得LR1分析表*************************************************************************/
bool get_table() //获得分析表table[i][j]=w:状态i-->j,读入符号W。
{
for(int i=0;i<v.size();i++) //遍历图
{
for(int j=head[i];j!=-1;j=e[j][1])
{
if(table[i][e[j][2]]!=-1)return 0; //多重入口,报错.
table[i][e[j][2]]=e[j][0];
tb_s_r[i][e[j][2]]=-1; //移近项-1。
}
}
for(int i=0;i<v.size();i++) //遍历所有项目
{
for(int j=0;j<v[i].size();j++)
{
if(v[i][j].id==proce[v[i][j].nump].size()) //归约项
{
for(int k=0;k<v[i][j].fst.size();k++)
{
if(table[i][(v[i][j].fst)[k]-'0']!=-1)return 0; //多重入口,报错.
if( (v[i][j].fst)[k]=='0'&&v[i][j].nump==0)
table[i][(v[i][j].fst)[k]-'0']=-3 ; //接受态。
else
{
table[i][(v[i][j].fst)[k]-'0']=v[i][j].nump;
tb_s_r[i][(v[i][j].fst)[k]-'0']=-2; //归约态
}
}
}
}
}
return 1;
}
void print_table()
{
// cout<<"LR(1)分析表:"<<endl;
// cout<<"状态 "<<" actoin "<<endl;
cout<<num<<" "<<v.size()<<endl;
for(int j=0;j<=num;j++)
{
if(j==numvt)continue;
cout<<" "<<getchars[j];
}
cout<<endl;
for(int i=0;i<v.size();i++)
{
cout<<i<<" ";
for(int j=0;j<=num;j++)
{
if(j==numvt)continue;
if(j<numvt)
{
if(table[i][j]==-3) cout<<"acc"<<" "; //接受
else if(table[i][j]==-1)cout<<"X "; //空
else if(tb_s_r[i][j]==-1)cout<<"s"<<table[i][j]<<" "; //移近
else if(tb_s_r[i][j]==-2)cout<<"r"<<table[i][j]<<" "; //归约
}
else
{
if(table[i][j]==-3) cout<<"acc"<<" "; //接受
else if(table[i][j]==-1)cout<<"X "; //空
else if(tb_s_r[i][j]==-1)cout<<""<<table[i][j]<<" "; //移近
else if(tb_s_r[i][j]==-2)cout<<""<<table[i][j]<<" "; //归约
}
}
cout<<endl;
}
}
string word;
void print_now_state(int count,stack<int>state,stack<int>wd,int i)
{
cout2<<count<<'\t'<<'\t';
stack<int>temp;
while(!state.empty())
{
temp.push(state.top());
state.pop();
}
while(!temp.empty())
{
cout2<<temp.top();
temp.pop();
}
cout2<<'\t'<<'\t';
while(!wd.empty())
{
temp.push(wd.top());
wd.pop();
}
while(!temp.empty())
{
cout2<<getchars[temp.top()];
temp.pop();
}
cout2<<'\t'<<'\t';
for(int j=i;j<word.size();j++)
cout2<<word[j];
cout2<<'\t'<<'\t';
}
/*********************************************分析程序**************************************************************/
bool analyze()
{
cout2<<" "<<word<<"的分析过程"<<endl;
cout2<<"步骤\t\t"<<"状态栈\t\t"<<"符号栈\t\t"<<"输入串\t\t"<<"动作说明"<<endl;
stack<int>state; //俩个栈:状态栈和符号栈
stack<int>wd;
int count=0;
state.push(0); //初始化
wd.push(0); //'#'
for(int i=0;;) //i,读入文本的
{
int cur=state.top();
if(table[cur][getnum[word[i]]]==-1) // 空白,报错误
return 0;
if(table[cur][getnum[word[i]]]==-3) //接受态
{
print_now_state(count++,state,wd,i);
cout2<<" 恭喜!acc!"<<endl;
return 1;
}
if(tb_s_r[cur][getnum[word[i]]]==-1) //移进项
{
print_now_state(count++,state,wd,i);
int newstate=table[cur][getnum[word[i]]];
cout2<<"action["<<cur<<","<<getnum[word[i]]<<"]="<<newstate;
cout2<<",状态"<<newstate<<"入栈"<<endl;
wd.push(getnum[word[i]]);
state.push(newstate);
i++;
}
else if(tb_s_r[cur][getnum[word[i]]]==-2) //归约
{
print_now_state(count++,state,wd,i);
int numpro=table[cur][getnum[word[i]]]; //用该产生式归约
int len=proce[numpro].size()-1;
for(int ii=0;ii<len;ii++) //弹栈
{
wd.pop();
state.pop();
}
wd.push(getnum[proce[numpro][0]]); //新入
int cur=state.top();
cout2<<"用"<<proce[numpro][0]<<"->";
for(int ii=1;ii<=len;ii++)
cout2<<proce[numpro][ii];
cout2<<"进行归约,"<<"goto["<<cur<<","<<getnum[word[i]]<<"]="<<table[cur][getnum[proce[numpro][0]]];
cout2<<"入栈"<<endl;
state.push(table[cur][getnum[proce[numpro][0]]]);
}
}
return 1;
}
int _tmain(int argc, _TCHAR* argv[])
{
clear();
readin();
getpp();
get_first();
get_xiangmujizu();
if(!get_table())
{
// cout<<"此文法在生成分析表时候有多重入口,非LR(1)文法!"<<endl;
cout<<-1<<endl;
return 0;
}
// print_xmjizu();
print_table();
//cout<<"请输入字:"<<endl;
cin>>word;
word+='#';
if(!analyze())
cout2<<"error!"<<endl;
else;
return 0;
}
import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.GeneralPath;
import java.lang.Thread;
import java.lang.Runnable;
public class LR1 extends JFrame
{
JButton go_table;
JButton go_ana;
public LR1() throws Exception //初始化构造函数
{
setBounds(0, 0, 1380, 800); //设定大小
this.setBackground(Color.WHITE); //背景色
this.setTitle("LR(1)文法分析");
this.setLayout(null);
readin();
JLabel title= new JLabel("LR1 文 法 分 析",JLabel.CENTER);
title.setFont(new Font("长城行楷体", Font.BOLD, 80)); //标签相关设置
title.setForeground(new Color(0,0,0));
title. setBounds(0,0,1380,100);
add(title);
go_table=new JButton("LR1分析表=>");
go_ana=new JButton("LR1分析器=>");
go_table.setBounds(700, 150, 400, 100);
go_ana.setBounds(700, 400, 400, 100);
Font f=new Font("长城行楷体",Font.BOLD,40);
go_table.setFont(f);
go_ana.setFont(f);
go_table.addActionListener(new presslistener1());
go_ana.addActionListener(new presslistener2());
add(go_table);
add(go_ana);
this.setVisible(true);
}
void readin()throws Exception
{
java.io.File file= new java.io.File("H:/课程设计/编译原理2015/lr(1)/in.txt"); //读入数据
Scanner input =new Scanner(file);
JLabel vt= new JLabel("终结符:");
vt.setFont(new Font("长城行楷体", Font.BOLD, 20)); //标签相关设置
vt.setOpaque(true);
vt.setForeground(new Color(0,0,0));
vt. setBounds(0,100,200,50);
add(vt);
String ss=input.nextLine();
JTextField temp0=new JTextField(ss);
temp0. setBounds(0,150,500,50);
temp0.setFont(new Font("长城行楷体", Font.BOLD, 15));
this.add(temp0);
JLabel vn= new JLabel("非终结符:");
vn.setFont(new Font("长城行楷体", Font.BOLD, 20)); //标签相关设置
vn.setOpaque(true);
vn.setForeground(new Color(0,0,0));
vn. setBounds(0,200,200,50);
add(vn);
ss=input.nextLine();
JTextField temp1=new JTextField(ss);
temp1. setBounds(0,250,500,50);
temp1.setFont(new Font("长城行楷体", Font.BOLD, 15));
this.add(temp1);
JLabel pro= new JLabel("产生式: ");
pro.setFont(new Font("长城行楷体", Font.BOLD, 20)); //标签相关设置
pro.setOpaque(true);
pro.setForeground(new Color(0,0,0));
pro. setBounds(0,300,200,50);
add(pro);
int cnt=0;
do
{
ss=input.next();
if(ss.equals("end"))break;
JTextField temp=new JTextField(ss);
temp. setBounds(0,350+cnt*50,500,50);
temp.setFont(new Font("长城行楷体", Font.BOLD, 15));
this.add(temp);
cnt++;
}while(true);
}
class presslistener1 implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
//LR1.this .setVisible(false);
try {
show_table mytable =new show_table();
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
class presslistener2 implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
//LR1.this .setVisible(false);
try {
show_ana mytable =new show_ana();
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
}import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.GeneralPath;
import java.lang.Thread;
import java.lang.Runnable;
public class show_ana extends JFrame {
int col;
int row;
public show_ana() throws Exception
{
setBounds(0, 0, 1380, 800); //设定大小
this.setBackground(Color.WHITE); //背景色
this.setTitle("LR(1)文法分析过程");
this.setLayout(null);
readin();
this.setVisible(true);
}
public void readin ()throws Exception //读入图函数
{
java.io.File file= new java.io.File("H:/课程设计/编译原理2015/lr(1)/out2.txt"); //读入数据
Scanner input =new Scanner(file);
String ss=input.next();
/* JLabel table= new JLabel(ss,JLabel.CENTER);
table.setFont(new Font("长城行楷体", Font.BOLD, 20)); //标签相关设置
table.setOpaque(true);
table.setForeground(new Color(0,0,0));
table. setBounds(0,0,1380,50);
add(table); */
col=5;
row=100;
int curcol=1380/col;
int currow=25;
for(int i=0;i<col;i++)
{
JTextField temp=new JTextField(input.next());
temp. setBounds(1380/col*i,50,curcol,currow);
temp.setFont(new Font("长城行楷体", Font.BOLD, 15));
this.add(temp);
}
for(int i=0;i<row;i++)
for(int j=0;j<col;j++)
{
if(!input.hasNext()){i=1000;break;}
String s= input.next();
JTextField temp=new JTextField(s);
temp. setBounds(1380/col*j,50+(i+1)*currow,curcol,currow);
temp.setFont(new Font("长城行楷体", Font.BOLD, 15));
this.add(temp);
}
input.close();
}
}
import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.GeneralPath;
import java.lang.Thread;
import java.lang.Runnable;
public class show_table extends JFrame {
int col;
int row;
public show_table() throws Exception
{
setBounds(0, 0, 1380, 800); //设定大小
this.setBackground(Color.WHITE); //背景色
this.setTitle("LR(1)文法分析");
this.setLayout(null);
readin();
this.setVisible(true);
}
public void readin ()throws Exception //读入图函数
{
JLabel table= new JLabel(" 状态 ACTION GO ");
table.setFont(new Font("长城行楷体", Font.BOLD, 20)); //标签相关设置
table.setOpaque(true);
table.setForeground(new Color(0,0,0));
table. setBounds(0,0,1380,50);
add(table);
java.io.File file= new java.io.File("H:/课程设计/编译原理2015/lr(1)/out.txt"); //读入数据
Scanner input =new Scanner(file);
col=input.nextInt();
col++;
row=input.nextInt();
int curcol=1380/col;
int currow=600/row;
if(col==-1) //多重入口
{
JOptionPane.showMessageDialog(null, "此文法在生成分析表时候有多重入口,非LR(1)文法!");
System.out.println("此文法在生成分析表时候有多重入口,非LR(1)文法!\n");
return ;
}
JTextField temp0=new JTextField();
temp0. setBounds(0,50,curcol,currow);
this.add(temp0);
for(int i=0;i<col-1;i++)
{
JTextField temp=new JTextField(input.next());
temp. setBounds(1380/col*(i+1),50,curcol,currow);
temp.setFont(new Font("长城行楷体", Font.BOLD, 15));
this.add(temp);
}
for(int i=0;i<row;i++)
for(int j=0;j<col;j++)
{
String s= input.next();
if(s.equals("X"))s="";
JTextField temp=new JTextField(s);
temp. setBounds(1380/col*j,50+(i+1)*currow,curcol,currow);
temp.setFont(new Font("长城行楷体", Font.BOLD, 15));
this.add(temp);
}
input.close();
}
}
import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.GeneralPath;
import java.lang.Thread;
import java.lang.Runnable;
public class start {
public static void main(String[] args) throws Exception
{
LR1 lr1= new LR1();
//show_table mytable =new show_table();
// show_ana myana= new show_ana();
}
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/u011498819/article/details/47165227