标签:
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