LR(0)完整的语法分析方法(拓广文法、识别活前缀状态机、LR0表、识别字符串)内有word详细说明

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分析表的
在这里插入图片描述

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值