C/C++ > LR(0)完整的语法分析方法(拓广文法、识别活前缀状态机、LR0表、识别字符串)内有word详细说明
这里附上
因为我们老师教的和上面这张图的不太一样。这里我写一下我的。
整个代码600行如下(如果不想去下载的话)
// ConsoleApplication14.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include<stdio.h>
#include<string.h>
#include<vector>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<stack>
#include<iomanip>
#include<sstream>
using namespace std;
set<string> N_;
set<string> T_;
set<string> ALL_;
stack<string> s;
struct pragram
{
string left;
string right;
}pragram[200];
struct all
{
string left;
vector<string> right;
}all[20];
int n,count1=1;
int showVet(vector<string> a)
{
for(int i=0;i<a.size();i++)
{
cout<<a[i]<<" ";
}
cout<<endl;
}
int input() //拆解表达式
{
freopen("input.txt","r",stdin); //可以选择文件 1(PPT109页面) 121(PPT121页面) 118(PPT118页面)
cin >> n;
for (int i = 0; i < n; i++)
{
string left;
cin >> left;
char c;
int t=-1;
while (1)
{
scanf("%c",&c);
if(t==-1) {t++;continue;}
if (c == '#') break;
if(c=='|')
{
count1++;
t=0;
pragram[count1].left = left;
continue;
}
pragram[count1].left = left;
pragram[count1].right = pragram[count1].right+c;
t++;
}
count1++;
}
cout<<endl;
cout<<"拓广文法后:"<<endl;
string a=pragram[1].left; //拿到第一条表达式左部
a=a+"'";
pragram[0].left=a;
pragram[0].right=pragram[1].left;
for (int i =0;i< count1; i++)
{
cout << pragram[i].left<<"->";
cout<<pragram[i].right<<endl;
ALL_.insert(pragram[i].left);
ALL_.insert(pragram[i].right);
}
cout<<endl;
}
int N() //挑出非终极符号
{
cout<<"非终极符号"<<endl;
for(int i=0;i<count1;i++)
{
string P=pragram[i].left;
N_.insert(P);
}
set<string>::iterator it;
for(it=N_.begin();it!=N_.end();it++)
{
cout<<*it<<endl;
}
}
int split() //分离所有符号
{
string b,c;
set<string>::iterator it,it_N,it1;
for(it=ALL_.begin();it!=ALL_.end();)
{
int check=0;
string a=*it;
int t=a.find(" "); //空格拆分
if(t!=-1)
{
b=a.substr(0,t);
c=a.substr(t+1,a.length());
check=1;
}
if(check==1)
{
ALL_.erase(it);
ALL_.insert(b);
ALL_.insert(c);
it=ALL_.begin();
}
else
{
++it;
}
}
}
int T() //挑选终极符号
{
set<string>::iterator it,it_N,it1;
for(it=T_.begin();it!=T_.end();)
{
int check=0;
string a=*it; //拿到字符
for(it_N=N_.begin();it_N!=N_.end();it_N++)
{
string b=*it_N;
if(a==b)
{ check=1;
break;
}
}
if(check==1)
{
T_.erase(it++);
}
else{
it++;
}
}
cout<<"终极符号"<<endl;
for(it1=T_.begin();it1!=T_.end();it1++)
{
cout<<*it1<<endl;
}
}
int ALL_T() //转换
{
set<string>::iterator it,it_N,it1;
for(it=ALL_.begin();it!=ALL_.end();it++)
{
string a=*it;
T_.insert(a);
}
}
vector<string> split(string &str)
{
char ch=' ';
//存储分割以后的结果
vector<string> res;
//加入一个分割字符,方便操作
str += ch;
//分割的起始位置
int start = 0;
//分割的终止位置
int last = str.find(ch);
//找到最后一个分隔符,终止条件
while (last < str.size())
{
//如果字符串不为空,则添加到结果中
if (start != last)
res.push_back(str.substr(start, last - start));
//起始位置更新
start = last + 1;
//终止位置更新
last = str.find(ch, start);
}
//ShowVec(res);
return res;
}
int change_to_vector() //将右设置为vector 利于控制
{
for(int i=0;i<count1;i++)
{
all[i].left=pragram[i].left;
all[i].right=split(pragram[i].right);
}
}
int is_N(string a) //用来查找字符串 是终极符号返回1 不是返回4000
{
set< string >::iterator it_N;
for(it_N=N_.begin();it_N!=N_.end();it_N++)
{
if(*it_N==a)
{
return 1;
}
}
return 4000;
}
bool in_right_N(vector<string> temp,string temp_string) //判断是否字符串在里面 //如果在 返回1 //不在 返回0
{
vector<string> ::iterator it;
for(it=temp.begin();it!=temp.end();it++)
{
if(*it==temp_string)
{
return 1; //如果在 返回1
}
}
return 0; //不在 返回0
}
//首先是生成I0
struct temp_DFA
{
int now_point=0;
string left;
vector<string> right;
}a[20],temp_DFA,test;
struct DFA
{
struct temp_DFA a[20];
int a_size=0;
struct b //接下来的节点
{
string change_word;
int num=-1; //接下来的孩子节点编号
}b[20];
int b_size=0;
}DFA[20];
int creat_LR0_auto_I0()
{
string now_left=all[0].left; //拿到第一条产生式
vector<string> right_N; //有0个终极符号
right_N.push_back(now_left); //压入一个
vector<string>::iterator it;
for(it=right_N.begin();it!=right_N.end();)
{
string left=*it;
for(int i=0;i<count1;i++)
{
if(left==all[i].left&&is_N(all[i].right[0])!=4000&&in_right_N(right_N,all[i].right[0])==0) //找到对应的行 并且是非终极符号 并且 string里面没有
{
right_N.push_back(all[i].right[0]);
it=right_N.begin();
break;
}
if(i==count1-1)
it++;
}
}
int b=0;
cout<<"处理结果"<<endl;
for(it=right_N.begin();it!=right_N.end();it++)
{
string a=*it;
for(int i=0;i<count1;i++)
{
if(a==all[i].left)
{
DFA[0].a[b].now_point=0;
DFA[0].a[b].left=all[i].left;
//showVet(all[i].right);
DFA[0].a[b].right=all[i].right;
b++;
}
}
}
DFA[0].a_size=b;
for(int i=0;i<b;i++)
{
cout<<DFA[0].a[i].left<<"->";
showVet(DFA[0].a[i].right);
}
}
int create_node(int pos,int new_node_num, struct temp_DFA temp[],int temp_a,int son_num)
{
cout<<"new_node_num"<<new_node_num<<endl;
for(int i=0;i<temp_a;i++)
{
temp[i].now_point++; //每一个点都加1
//如果这个点 移动之后是最后一个 那么是规约式
if(temp[i].now_point==temp[i].right.size())
{
DFA[new_node_num].a[0]=temp[i];
DFA[new_node_num].a_size=-1;
cout<< DFA[new_node_num].a[0].left<<"规约->";
showVet(DFA[new_node_num].a[0].right);
for(int j=0;j<new_node_num;j++)
{
int check=0;
for(int i=0;i<1;i++)
{
/*cout<<DFA[new_node_num].a[i].now_point<<" "<<DFA[j].a[i].now_point<<endl;
cout<<DFA[new_node_num].a[i].left<<" "<<DFA[j].a[i].left<<endl;
showVet(DFA[pos].a[i].right);
showVet(DFA[new_node_num].a[i].right);*/
if(DFA[new_node_num].a[i].now_point == DFA[j].a[i].now_point&&DFA[new_node_num].a[i].left==DFA[j].a[i].left&&DFA[j].a[i].right==DFA[new_node_num].a[i].right)
{
check=1;
}
else
{
check=0;
break;
}
}
if(check==1)
{
cout<<"相同不插入"<<j<<endl;
DFA[new_node_num].a_size=0;
cout<<"son_num"<<son_num<<endl;
DFA[pos].b[son_num].num=j;
break;
}
}
return 0;
}
}
int t=0;
//不是规约式的话
for(int i=0;i<temp_a;i++)
{
DFA[new_node_num].a[t].now_point=temp[i].now_point;
cout<<"temp[i].now_point"<<temp[i].now_point<<endl;
DFA[new_node_num].a[t].left=temp[i].left;
DFA[new_node_num].a[t].right=temp[i].right;
cout<< DFA[new_node_num].a[t].left<<"->";
showVet(DFA[new_node_num].a[t].right);
DFA[new_node_num].a_size++;
t++;
if( is_N(temp[i].right[temp[i].now_point] ) ) //是非终极符号的话
{
string N_temp=temp[i].right[temp[i].now_point];
for(int j=0;j<count1;j++)
{
if(N_temp==all[j].left)
{
DFA[new_node_num].a[t].now_point=0;
DFA[new_node_num].a[t].left=all[j].left;
DFA[new_node_num].a[t].right=all[j].right;
cout<<"temp[i].now_point"<<DFA[new_node_num].a[t].now_point<<endl;
cout<< DFA[new_node_num].a[t].left<<"非终极符号引入->";
showVet(DFA[new_node_num].a[t].right);
DFA[new_node_num].a_size++;
t++;
}
}
}
}
for(int j=0;j<new_node_num;j++)
{
int check=0;
for(int i=0;i<t;i++)
{
/*cout<<DFA[new_node_num].a[i].now_point<<" "<<DFA[j].a[i].now_point<<endl;
cout<<DFA[new_node_num].a[i].left<<" "<<DFA[j].a[i].left<<endl;
showVet(DFA[pos].a[i].right);
showVet(DFA[new_node_num].a[i].right);*/
if(DFA[new_node_num].a[i].now_point == DFA[j].a[i].now_point&&DFA[new_node_num].a[i].left==DFA[j].a[i].left&&DFA[j].a[i].right==DFA[new_node_num].a[i].right)
{
check=1;
}
else
{
check=0;
break;
}
}
if(check==1)
{
cout<<"相同不插入"<<j<<endl;
DFA[new_node_num].a_size=0;
DFA[pos].b[son_num].num=j;
break;
}
}
}
int temp(int pos,string change_string,int new_node_num,int son_num)
{
cout<<"转换字符"<<change_string<<endl;
struct temp_DFA temp[20];
int a=0;
cout<<DFA[pos].a_size<<endl;
for(int i=0;i<DFA[pos].a_size;i++)
{
cout<<DFA[pos].a[i].right[DFA[pos].a[i].now_point]<<endl;
if(change_string==DFA[pos].a[i].right[DFA[pos].a[i].now_point])
{
temp[a]=DFA[pos].a[i];
cout<<temp[a].left<<"转换字符->";
showVet(temp[a].right);
a++;
}
}
create_node(pos,new_node_num,temp,a,son_num);
}
int create_next(int pos) //生成子节点
{
cout<<"当前处理节点"<<pos<<endl;
vector<string> change_string;
for(int i=0;i<DFA[pos].a_size;i++)
{
if(in_right_N(change_string,DFA[pos].a[i].right[DFA[pos].a[i].now_point])==0) //在这里面吗 不在的话
{
cout<<"找到压入的值为"<<DFA[pos].a[i].right[DFA[pos].a[i].now_point]<<endl;
change_string.push_back(DFA[pos].a[i].right[DFA[pos].a[i].now_point]); //不在的话 压入
}
}
DFA[pos].b_size=change_string.size(); //接下来节点的数
for(int i=0;i<change_string.size();i++) //声明接下来的子节点的位置
{
DFA[pos].b[i].change_word=change_string[i];
for(int j=pos+1+i;j<20;)
{
cout<<"当前测试节点:"<<j<<" "<<DFA[j].a_size<<endl;
if( DFA[j].a_size==0 )
{
DFA[pos].b[i].num=j;
temp(pos,change_string[i],j,i);
break;
}
else
{
j++;
}
}
}
}
int all_count=0;
int table[20][20];
int ini_table()
{
for(int i=0;i<20;i++)
{
for(int j=0;j<20;j++)
table[i][j]=0;
}
}
int find_all(string a)
{
set<string> ::iterator it;
int tt=0;
for(it=ALL_.begin();it!=ALL_.end();it++)
{
string b=*it;
if(b==a)
return tt;
else
tt++;
}
}
int find_exprision(string left,vector<string> temp)
{
for(int i=0;i<count1;i++)
{
if(left==all[i].left&&temp==all[i].right)
{
cout<<"find"<<left<<endl;
cout<<i<<endl;
return i;
}
}
}
int create_table()
{
set<string> ::iterator it;
ALL_.insert("$");
cout<<all_count<<endl;
for(int i=0;i<all_count;i++)
{
cout<<"当前处理行"<<i<<endl;
if(DFA[i].b_size==0)
{
if(i==1) continue;
int pos=find_exprision(DFA[i].a[0].left,DFA[i].a[0].right);
cout<<"规约行"<<pos<<endl;
for(int j=0;j<ALL_.size();j++)
table[i][j]=pos+200;
continue;
}
for(int j=0;j<DFA[i].b_size;j++)
{
cout<<"当前处理字母"<<endl;
cout<<DFA[i].b[j].change_word<<endl;
if(is_N(DFA[i].b[j].change_word)!=4000)
{
//如果不是终极符号
int pos= find_all(DFA[i].b[j].change_word);
cout<<"非终极符号"<<pos<<endl;
table[i][pos]=DFA[i].b[j].num;
}
else
{
int pos= find_all(DFA[i].b[j].change_word);
cout<<"终极符号"<<pos<<endl;
table[i][pos]=DFA[i].b[j].num;
}
}
}
int pos=find_all("$");
table[1][pos]=666;
for(it=ALL_.begin();it!=ALL_.end();it++)
{
cout<<*it<<"\t";
}
cout<<endl;
for(int i=0;i<all_count;i++)
{
for(int j=0;j<ALL_.size();j++)
{
cout<<table[i][j]<<"\t";
}
cout<<endl;
}
}
int showstack(stack<string> a)
{
stack<string> temp_a; //倒叙输出 才符合人类思维
while( a.size() )
{
temp_a.push(a.top());
a.pop();
}
while( temp_a.size() )
{
cout<<temp_a.top();
temp_a.pop();
}
cout<<endl;
}
int to_check_string() //分析过程
{
//string input_string="abbcde$"; //1 2 移入 100 规约200+
string input_string_a="a b b c d e $";
// string input_string_a="a b b c a e $";
stack<string> input_stack;
vector<string> input_string=split(input_string_a);
for(int i=input_string.size()-1;i>=0;i--)
{
cout<<input_string[i]<<endl;
input_stack.push(input_string[i]);
}
s.push("0");
for(int i=0;i<20;i++)
{
string str_top = s.top(); //取出当前状态 0
int a = atoi(str_top.c_str()); //转换int
cout<<"当前状态"<<a<<endl;
string str_input = input_stack.top(); //取出待输入的字符一个
int pos = find_all( str_input ); //拿到表中位置
cout<< " 当前字符 :"<<str_input<<"表中位置:"<<pos<<endl;
int temp_=table[a][pos]; //拿到表中状态
if(temp_==666)
{
cout<<"!!!处理完毕,字符串可接受!!!"<<endl;
return 0;
}
if(temp_>=200&&temp_<300) //规约
{
cout<<"进入规约"<<endl;
temp_=temp_%200;
for(int j=0;j<all[temp_].right.size()*2;j++)
{
cout<<"出栈"<<s.top()<<endl;
s.pop();
}
cout<<"压入"<<all[temp_].left<<endl;
string b = s.top();
a = atoi(b.c_str()); //转换int
s.push(all[temp_].left);
pos = find_all( all[temp_].left );
temp_=table[a][pos];
stringstream ss;
string temp_string;
ss<<temp_;
temp_string=ss.str();
s.push(temp_string);
cout<<"压入"<<temp_string<<endl;
cout<<"规约处理完毕"<<endl;
}
else if(temp_==0)
{
cout<<"!!!!不可接受!!!!"<<endl;
return 0;
}
else //移入
{
s.push(str_input); //先压入字符
string temp_string; //压入状态
stringstream ss;
ss<<temp_;
temp_string=ss.str();
s.push(temp_string);
cout<<"压入字符"<<str_input<<"压入状态"<<temp_string<<endl;
input_stack.pop();
cout<<"移除待输入字符"<<str_input<<endl;
}
cout<<"当前状态栈 :";showstack(s);
cout<<"当前输入栈/串 :";showstack(input_stack);
}
}
int main()
{
input();
N();
split();
ALL_T();
T();
change_to_vector() ;
creat_LR0_auto_I0();
create_next(0);
cout<<""<<endl<<endl;
create_next(2);
for(int i=0;i<=4;i++)
{
cout<<"***"<<i<<endl;
cout<<"拥有表达式个数:"<<DFA[i].a_size<<endl;
for(int j=0;j<DFA[i].a_size;j++)
{
cout<<"点位置"<<DFA[i].a[j].now_point<<endl;
cout<<DFA[i].a[j].left<<"->";
showVet(DFA[i].a[j].right);
}
cout<<endl;
}
cout<<""<<endl<<endl;
/* create_next(3);
create_next(4);
create_next(5);
create_next(6);
create_next(7);
create_next(8);
create_next(9);*/
for(int i=1;i<20;i++)
create_next(i);
cout<<"自动机生成完毕"<<endl;
for(int i=0;i<20;i++)
{
if(DFA[i].a_size!=0) all_count++;
if(DFA[i].b_size==0) continue;
cout<<"i"<<i<<endl;
for(int j=0;j<DFA[i].b_size;j++)
{
cout<<DFA[i].b[j].change_word<<" ";
cout<<DFA[i].b[j].num<<" ";
}
cout<<endl;
}
cout<<all_count<<endl;
ini_table();
create_table();
to_check_string();
}
创建一个input.txt文件 像下面那样写入就好了
4
S a A c B e#
A b#
A A b#
B d#
输入判别的字符串在这里改 576行
源代码+详解zip
有疑惑可以联系 我们一起学习。(要复习了呀哈哈哈)
还有LL1分析表的