LR(0)算法的模拟实现

一、实验目的

通过设计、编写和构造LR(0)项目集规范簇(识别文法全部活前缀的DFA)和LR 分析表、对给定的符号串进行LR 分析的程序,了解构造LR(0)分析表的步骤,对文法的要求,能够从文法G 出发生成LR(0) 分析表,并对给定的符号串进行分析。要求以表格或图形的方式实现。

二、实验内容

 三、实验要求

1.给定一个上下文无关文法,求出其项目集规范簇,结果以图形或表格的形式输出;

2.构造该文法的LR(0)分析表,以表格形式输出,并判定给定的文法是否是LR(0)文法;

3.输入一个符号串,实现对该串的LR(0)分析过程,并将过程以表格形式输出。

  1. 补充说明:

(1)本次实验任务,分三个层次实现,最低要求完成第1个实验要求。其余根据个人情况,尽力完成即可(比如可以完成到2,也可以全部都实现)

(2)编程语言不限。

、实验原理

  1. 构造LR(0)项目集规范簇

    1. 问题描述

.给定一个上下文无关文法,求出其项目集规范簇,结果以图形或表格的形式输出;

  1. 算法描述

对文法G,首先求出其所有的LR(0)项目,然后根据项目求出其LR(0)项目集规范簇及构造出识别活前缀的DFA。算法如下:

1. 置C={closure({S’->.S})} //C为项目集簇(状态点集合) ,初值为初态

2. 对于C中的每个项目集(状态点)和每个文法符号X,做如下处理:

If  GO(I,X)非空且不属于C then

{

把GO(I,X)加入C中;

在I和GO(I,X)之间画弧线,并标记为X;

}

  1. 重复步骤2直至C不再增大为止。
    1. 基本要求
  1. 输入的文法,可以直接输入,也可以读入文件;
  2. 以表格形式输出项目集规范簇及识别活前缀的DFA;

G[E]:       E→Aa∣Bb

A→Ca∣d

B→Cb∣d

比如,对于测试用例文法

构造出来的DFA如下,

但在程序处理的时候,可以按以下表格形式输出:

状态

项目集

后继符号

后继状态

S0

S→·E

E→·Aa

E→·Bb

E

a

b

S1

S2

S3

S1

S→E·

#

接受态

……

……

……

……

S11

B→d·

#

归约

    1. 实现提示
  1. 建议用链表来存储项目集簇
  2. 存储产生式

Struct sponser{

Char vn;

Char option[MAX];

Struct sponser *next;

}

  1. 存储来源关系

Struct condition{

Int form;// 来自哪一个结点

Char input;// 转换条件,也就是输入字符

Condition  * next;}

  1. 存储LR(0)项目集

Struct LRstate{

Int snum;// 结点编号,也就是状态编号

Sponser * state;//结点中有哪些项目

Condition *transfer;//来源关系

LRstate * next;

}

2.构造该文法的LR(0)分析表,以表格形式输出

  1. 问题描述

利用上一阶段得到的项目集规范簇,求出其LR(0)分析表,以表格形式输出,并判定所给的文法是否是LR(0)文法。

  1. 算法描述

LR(0)分析表的构造算法为:

LR(0)文法的判定算法为:

Flag:=true;

For 项目集规范簇中的每个项目集 i ,DO

FOR 文法G’中的每个文法符号 DO

IF action[i,X]或goto[i,X]的值多于一个 then

Flag:=false;

If flag then 文法G是LR(0)文法

Else 文法G不是LR(0)文法;

    1. 基本要求
  1. 输入的文法,可以直接输入,也可以读入文件;
  2. 输出项目集规范簇,可直接调用上一阶段的结果;
  3. 输出LR(0)分析表

3. LR分析过程实现

  1. 问题描述

利用上一阶段结果,输入一个符号串,实现对该串的LR分析过程,并以表格形式输出该分析过程。

  1. 算法描述

LR分析器的工作在总控程序的控制下进行,其算法流程图可描述如下:

算法描述如下:

  1. 0入状态栈;
  2. #入符号栈;
  3. 置ip指向w#的第一个符号;
  4. 重复执行如下过程

  {

   令S是状态栈栈顶;

     a是ip所指向的符号;

     if(action[S,a]==Sj)  //移进

        {

          a入符号栈;

          状态j入状态栈;

          ip指向下一个符号;

        }

else if(action[S,a]==rj  //用A→β归约

       {输出此时文法符号栈中的全部内容即,在归约前,把可归前缀输出

         输出β即,输出当前句型句柄

        从符号栈弹出|β|个符号;

        从状态栈弹出|β|个符号;

        令S是状态栈栈顶;

         A入符号栈;

         goto[S,A]入状态栈;

         输出产生式A→β;

        }

 else if(action[S,a]==accept) return; //成功

                             

 else error();  //调出错函数

重复直到(ip指向输入串的尾部# && 符号栈栈顶为S‘);

结束。

    1. 基本要求
  1. 输入一个符号串,以#结束;
  2. 调用分析表,处理输出对应的LR分析过程,结果以表格形式呈现
  3. 输出归约过程中,所有出现的可归前缀及其对应句柄。

注:也可以同步输出最左归约过程(用横式表达),如果可以实现图形化界面设计,也可输出其语法树结构图。

四.实验代码设计与实现

代码如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cctype>
#include <vector>
#include <string>
#include <queue>
#include <map>
#include <sstream>
#define MAX 507
#define DEBUG

using namespace std;

class WF
{
    public:
    string left,right;
    int back;
    int id;
    WF ( char s1[] , char s2[] , int x , int y )
    {
        left = s1;
        right = s2;
        back = x;
        id = y;
    }
    WF ( const string& s1 , const string& s2 , int x , int y )
    {
        left = s1;
        right = s2;
        back = x;
        id = y;
    }
    bool operator < ( const WF& a ) const 
    {
        if ( left == a.left ) 
            return right < a.right;
        return left < a.left;
    }
    bool operator == ( const WF& a ) const 
    {
        return ( left == a.left )&& ( right == a.right );
    }
    void print ( )
    {
        printf ( "%s->%s\n" , left.c_str() , right.c_str() );
    }
};

class Closure
{
    public:
    vector<WF> element; 
    void print ( string str )
    {
        printf ( "%-15s%-15s\n" , "" , str.c_str());
        for ( int i = 0 ; i < element.size() ; i++ )
            element[i].print();
    }
    bool operator == ( const Closure& a ) const 
    {
        if ( a.element.size() != element.size() ) return false;
        for ( int i = 0 ; i < a.element.size() ; i++ )
            if ( element[i] == a.element[i] ) continue;
            else return false;
        return true;
    }
};

struct Content
{
    int type;
    int num;
    string out;
    Content(){ type = -1; }
    Content ( int a , int b )
        :type(a),num(b){}
};

vector<WF> wf;
map<string,vector<int> > dic;
string start = "S";
vector<Closure> collection;
vector<WF> items;
char CH = '$';
int go[MAX][MAX];
int to[MAX];
vector<char> V;
bool used[MAX];
Content action[MAX][MAX];
int Goto[MAX][MAX];

void make_item ( )
{
    memset ( to , -1 , sizeof ( -1 ) );
    for ( int i = 0 ; i < wf.size() ; i++ )
        for ( int j = 0 ; j <= wf[i].right.length() ; j++ )
        {
            string temp = wf[i].right;
            temp.insert ( temp.begin()+j , CH );
            dic[wf[i].left].push_back ( items.size() );
            if ( j )
                to[items.size()-1] = items.size();
            items.push_back ( WF ( wf[i].left , temp , i , items.size()) );
        }
#ifdef DEBUG
    puts("-------------------------项目表-------------------------");
    for ( int i = 0 ; i < items.size() ; i++ )
        printf ( "%s->%s\n" , items[i].left.c_str() , items[i].right.c_str() );
    puts("--------------------------------------------------------");
#endif
}

void make_set ( )
{
    bool has[MAX];
    for ( int i = 0 ; i < items.size() ; i++ )
        if ( items[i].left[0] == 'S' && items[i].right[0] == CH )
        {
            Closure temp;
            string& str = items[i].right;
            vector<WF>& element = temp.element;
            element.push_back ( items[i] );
            int x = 0;
            for ( x = 0 ; x < str.length() ; x++ )
                if ( str[x] == CH )
                    break;
            /*if ( x != str.length()-1 )
            {
                string tt = str.substr(x+1,1);
                vector<int>& id = dic[tt];
                for ( int j = 0 ; j < id.size() ; j++ )
                {
                    int tx = id[j];
                    //items[tx].print();
                    if ( items[tx].right[0] == CH )
                        element.push_back ( items[tx] );
                }
            }*/
            memset ( has , 0 , sizeof ( has ) );
            has[i] = 1;
            if ( x != str.length()-1 )
            {
                queue<string> q;
                q.push( str.substr(x+1,1) );
                while ( !q.empty() )
                {
                    string u = q.front();
                    q.pop();
                    vector<int>& id = dic[u];
                    for( int j = 0 ; j < id.size() ; j++ )
                    {
                        int tx = id[j];
                        if ( items[tx].right[0] == CH )
                        {   
                            if ( has[tx] ) continue;
                            has[tx] = 1;
                            if ( isupper(items[tx].right[1] ) )
                                q.push ( items[tx].right.substr(1,1));
                            element.push_back ( items[tx] );
                        }    
                    }
                }
            }
            collection.push_back ( temp );
        }
    for ( int i = 0 ; i < collection.size() ; i++ )
    {
        map<int,Closure> temp;
        for ( int j = 0 ; j < collection[i].element.size() ; j++ )
        {
            string str = collection[i].element[j].right;
            int x = 0;
            for ( ; x < str.length() ; x++ )
               if ( str[x] == CH ) break;
            if ( x == str.length()-1 ) 
                continue;
            int y = str[x+1];
            int ii;
            //cout << i << "previous: " << str << endl;
            str.erase ( str.begin()+x);
            str.insert ( str.begin()+x+1 , CH );
            //cout << i <<"after: " << str << endl;
            WF cmp = WF ( collection[i].element[j].left , str , -1 , -1 );
            for ( int k = 0 ; k< items.size() ; k++ )
                if ( items[k] == cmp )
                {
                    ii = k;
                    break;
                }
             //string& str1 = items[ii].right;
             memset ( has , 0 , sizeof ( has ) );
             vector<WF>& element = temp[y].element;
             element.push_back ( items[ii] );
             has[ii] = 1;
             x++;
             /*if ( x != str.length()-1 )
             {
                 string tt = str.substr(x+1,1);
                 vector<int>& id = dic[tt];
                 for ( int j = 0 ; j < id.size() ; j++ )
                 {
                    int tx = id[j];
                    //items[tx].print();
                    if ( items[tx].right[0] == CH )
                        element.push_back ( items[tx] );
                 } 
             }*/
            if ( x != str.length()-1 )
            {
                queue<string> q;
                q.push( str.substr(x+1,1) );
                while ( !q.empty() )
                {
                    string u = q.front();
                    q.pop();
                    vector<int>& id = dic[u];
                    for( int j = 0 ; j < id.size() ; j++ )
                    {
                        int tx = id[j];
                        if ( items[tx].right[0] == CH )
                        {   
                            if ( has[tx] ) continue;
                            has[tx] = 1;
                            if ( isupper(items[tx].right[1] ) )
                                q.push ( items[tx].right.substr(1,1));
                            element.push_back ( items[tx] );
                        }    
                    }
                }
            }
        }
        map<int,Closure>::iterator it = temp.begin();
        for ( ; it != temp.end() ; it++ )
                collection.push_back ( it->second );
        for ( int i = 0 ; i < collection.size() ; i++ )
            sort ( collection[i].element.begin() , collection[i].element.end() );
        for ( int i = 0 ; i < collection.size() ; i++ )
            for ( int j = i+1 ; j < collection.size() ; j++ )
                if ( collection[i] == collection[j] )
                    collection.erase ( collection.begin()+j );
    }
#ifdef DEBUG
    puts ("-------------CLOSURE---------------------");
    stringstream sin;
    for ( int i = 0 ; i < collection.size() ; i++ )
    {
        sin.clear();
        string out;
        sin <<"closure-I" << i;
        sin >> out;
        collection[i].print ( out );
    }
    puts("");
#endif  
}

void make_V ( )
{
    memset ( used , 0 , sizeof ( used ) );
    for ( int i = 0 ; i < wf.size() ; i++ )
    {
        string& str = wf[i].left;
        for ( int j = 0 ; j < str.length() ; j++ )
        {
            if ( used[str[j]] ) continue;
            used[str[j]] = 1;
            V.push_back ( str[j] );
        }
        string& str1 = wf[i].right;
        for ( int j = 0 ; j < str1.length() ; j++ )
        {
            if ( used[str1[j]] ) continue;
            used[str1[j]] = 1;
            V.push_back ( str1[j] );
        }
    }
    sort ( V.begin() , V.end() );
    V.push_back ( '#' );
}

void make_cmp ( vector<WF>& cmp1 , int i  , char ch )
{
    for ( int j = 0 ; j < collection[i].element.size() ; j++ )
    {
        string str = collection[i].element[j].right;
        int k;
        for ( k = 0 ; k < str.length() ; k++ )
            if ( str[k] == CH ) 
                break;
        if ( k != str.length() - 1 && str[k+1] == ch  )
        {
            str.erase ( str.begin()+k);
            str.insert ( str.begin()+k+1 , CH );
            cmp1.push_back ( WF ( collection[i].element[j].left , str , -1 , -1 ) );
        }
    }
    sort ( cmp1.begin() , cmp1.end() );
}

void make_go ( )
{
    memset ( go , -1 , sizeof ( go ) );
    int m = collection.size();
    /*for ( int i = 0 ; i < m ; i++ )
        for ( int j = 0 ; j < collection[i].element.size() ; j++ )
        {
            string left = collection[i].element[j].left;
            string str = collection[i].element[j].right;
            int x = 0;
            for ( ; x < str.length() ; x++ )
               if ( str[x] == CH ) break;
            if ( x == str.length()-1 ) 
                continue;
            int y = str[x+1];
           //cout << "before : " << str << endl;
            str.erase ( str.begin()+x);
            str.insert ( str.begin()+x+1 , CH );
           //cout << "after : " << str << endl;
            WF cmp = WF ( collection[i].element[j].left , str , -1 , -1 );
            for ( int k = 0 ; k < m ; k++ )
            {
                bool flag = false;
                for ( int t = 0 ; t < collection[k].element.size() ; t++ )
                {
                    if ( cmp == collection[k].element[t] )
                    {                        
                        flag = true;
                        break;
                    }
                }
                if ( flag )
                {
                    go[i][y] = k;
                }
            }
        }*/
    for ( int t = 0 ; t < V.size() ; t++ )
    {
        char ch = V[t];
        for ( int i = 0 ; i < m ; i++ )
        {
            vector<WF> cmp1;
            make_cmp ( cmp1 , i , ch );
            cout << cmp1.size() << endl;
            if ( cmp1.size() == 0 ) continue;
            for ( int j = 0 ; j < m ; j++ )
            {
                vector<WF> cmp2;
                for ( int k = 0 ; k < collection[j].element.size() ; k++ )
                {
                    string& str = collection[j].element[k].right;
                    int x;
                    for ( x = 0 ; x < str.length() ; x++ )
                        if ( str[x] == CH )
                            break;
                    if ( x && str[x-1] == ch )
                       cmp2.push_back ( WF( collection[j].element[k].left , str , -1 , -1 ) ); 
                }
                sort ( cmp2.begin() , cmp2.end() );
                cout << cmp2.size() << endl;
                bool flag = true;
                if ( cmp2.size() != cmp1.size() ) continue;
                cout << cmp1.size() << endl;
                for ( int k = 0 ; k < cmp1.size() ; k++ )
                    if ( cmp1[k] == cmp2[k] ) continue; 
                    else flag = false;
                cout << "out " << endl;
                if ( flag ) 
                    go[i][ch] = j;
            }
            //cout << "YES" << endl;
        }

}
#ifdef DEBUG
    puts ("---------------EDGE----------------------");
    stringstream sin;
    string out;
    for ( int i = 0 ; i < m ; i++ )
        for ( int j = 0 ; j < m ; j++ )
            for ( int k = 0 ; k < MAX ; k++ )
                if ( go[i][k] == j )
                {
                    sin.clear();
                    sin << "I" << i << "--" <<(char)(k)<<"--I"<<j;
                    sin >> out;
                    printf ( "%s\n" , out.c_str() );     
                }   
#endif
}

void make_table ( )
{
    memset ( Goto , -1 , sizeof ( Goto ) );
    /*memset ( used , 0 , sizeof ( used ) );
    for ( int i = 0 ; i < wf.size() ; i++ )
    {
        string& str = wf[i].left;
        for ( int j = 0 ; j < str.length() ; j++ )
        {
            if ( used[str[j]] ) continue;
            used[str[j]] = 1;
            V.push_back ( str[j] );
        }
        string& str1 = wf[i].right;
        for ( int j = 0 ; j < str1.length() ; j++ )
        {
            if ( used[str1[j]] ) continue;
            used[str1[j]] = 1;
            V.push_back ( str1[j] );
        }
    }
    sort ( V.begin() , V.end() );
    V.push_back ( '#' );*/
    //write s to the table 
    for( int i = 0 ; i < collection.size() ; i++ )
        for ( int j = 0 ; j < V.size() ; j++ )
        {
            char ch = V[j];
            int x = go[i][ch];
            if ( x == -1 ) continue;
            if ( !isupper(ch) )
                action[i][ch] = Content ( 0 , x );
            else 
                Goto[i][ch] = x;
        }
    //write r and acc to the table 
    for ( int i = 0 ; i < collection.size() ; i++ )
        for ( int j = 0 ; j < collection[i].element.size() ; j++ )
        {
            WF& tt = collection[i].element[j];
            if ( tt.right[tt.right.length()-1] == CH )
            {
                if ( tt.left[0] == 'S' )
                    action[i]['#'] = Content ( 2 , -1 );
                else 
                    for ( int k = 0 ; k < V.size() ; k++ )
                    {
                        int y = V[k];
                        //cout << "YES " << endl;
                        action[i][y] = Content ( 1, tt.back );
                    }
            }
        }
#ifdef DEBUG
    puts ( "------------------------------------------LR(0)分析表--------------------------------------------------------" );
    printf ( "%10s%5c%5s" , "|" , V[0]  , "|");
    for ( int i = 1 ; i < V.size() ; i++ )
        printf ( "%5c%5s" , V[i] , "|" );
    puts ("");
    for ( int i = 0 ; i < (V.size()+1)*10 ; i++ )
        printf ( "-" );
    puts("");
    stringstream sin;
    for ( int i = 0 ; i < collection.size() ; i++ )
    {
        printf ( "%5d%5s" , i , "|" );
        for ( int j = 0 ; j < V.size() ; j++ )
        {
            char ch = V[j];
            if ( isupper(ch) )
            {
                if ( Goto[i][ch] == -1 )
                    printf ( "%10s" , "|" );
                else 
                    printf ( "%5d%5s" , Goto[i][ch] , "|" );
            }
            else
            {
                sin.clear();
                if ( action[i][ch].type == -1 ) 
                    printf ( "%10s" , "|" ); 
                else 
                {
                    Content& temp = action[i][ch];
                    if ( temp.type == 0 ) 
                        sin << "S";
                    if ( temp.type == 1 ) 
                        sin << "R";
                    if ( temp.type == 2 )
                        sin << "acc";
                    if ( temp.num != -1 )
                        sin << temp.num;
                    sin >> temp.out;
                    printf ( "%7s%3s" , temp.out.c_str() , "|" );
                }
            }
        }
        puts ("");
    }
    for ( int i = 0 ; i < (V.size()+1)*10 ; i++ )
        printf ( "-" );
    puts("");
#endif
}

void print ( string s1 , string s2 , string s3 , string s4 , string s5 , string s6 , string s7 )
{
    printf ( "%-15s|%-15s%-15s%-20s|%-15s%-15s%-15s\n" , s1.c_str() , s2.c_str() , s3.c_str() ,s4.c_str(),s5.c_str(),
                                                        s6.c_str() , s7.c_str() );                            
}

string get_steps ( int x )
{
    stringstream sin;
    sin << x;
    string ret;
    sin >> ret;
    return ret;
}

template<class T>
string get_stk ( vector<T> stk )
{
    stringstream sin;
    for ( int i = 0 ; i < stk.size() ; i++ )
        sin << stk[i];
    string ret;
    sin >> ret;
    return ret;
}

string get_shift ( WF& temp )
{
    stringstream sin;
    sin << "reduce(" << temp.left << "->" << temp.right <<")";
    string out;
    sin >> out;
    return out;
}

void analyse ( string src )
{
    print ( "steps","op-stack" ,"input","operation","state-stack" , "ACTION" , "GOTO" );
    vector<char> op_stack;
    vector<int> st_stack;
    src+= "#";
    op_stack.push_back ( '#' );
    st_stack.push_back ( 0 );
    int steps= 1;
    for ( int i = 0 ; i < src.length() ; i++ )
    {
        char u = src[i];
        int top = st_stack[st_stack.size()-1];
        Content& act = action[top][u];
        //cout << "YES : " << i << " " << u << " " << top << " " << act.type << endl;
        if ( act.type == 0 )
        {
            print ( get_steps ( steps++ ) , get_stk ( op_stack ) , src.substr(i), "shift",  get_stk( st_stack ) , act.out , "" );
            op_stack.push_back ( u );
            st_stack.push_back ( act.num );
        }
        else if ( act.type == 1 )
        {
            WF& tt = wf[act.num];
            int y = st_stack[st_stack.size()-tt.right.length()-1];
            int x = Goto[y][tt.left[0]];
            //cout << y << " " << tt.left[0] << " " << x << endl;
            print ( get_steps ( steps++ ) , get_stk ( op_stack ) , src.substr(i) , get_shift(tt) ,get_stk( st_stack),act.out,get_steps(x));
            for ( int j = 0 ; j < tt.right.length() ; j++ )
            {
                st_stack.pop_back();
                op_stack.pop_back();
            }
            op_stack.push_back ( tt.left[0] );
            st_stack.push_back ( x );
            i--;
        }
        else if ( act.type == 2 )
        {
            print ( get_steps( steps++ ), get_stk( op_stack ) , src.substr(i) , "Accept" , get_stk(st_stack) , act.out , "" );
            //i--;
        }
        else continue;
    }
}

int main ( )
{
    int n;
    char s[MAX];
    while ( ~scanf ( "%d" , &n ) )
    {
        for ( int i = 0 ; i < n ; i++ )
        {
            scanf ( "%s" , s );
            int len = strlen(s),j;
            for ( j = 0 ; j < len ; j++ )
                if ( s[j] == '-' ) break;
            s[j] = 0;
            wf.push_back ( WF ( s , s+j+2 ,-1 , -1 ) );
#ifdef DEBUG
            wf[wf.size()-1].print();
#endif
        }
        make_item();
        make_set();
    make_V();
        make_go();
        make_table();
        analyse ( "abbcde" );
    }
}

、实验结果及分析

算法描述

项目集构造算法

枚举每个规范句型,然后枚举”.”的位置,获得所有的项目

项目集规范族构造算法

假定I是文法G’的任一项目集,定义和构造I的闭包CLOSURE(I)的办法是:

I的任何项目都属于CLOSURE(I);

若A→α•Bβ属于CLOSURE(I),那么,对任何关于B的产生式B→γ,项目B→•γ也属于CLOSURE(I);

重复执行上述两步骤直至CLOSURE(I)不再增大为止。

Go(I,a)函数构造算法

遍历所有的项目,如果任意两个项目之间存在边(有向),那么这两个项目所在的项目规范族之间连上对应的有向边。

LR(0)分析表构造算法

假定项目集规范族C={I0,I1,…,In}。令每一个项目集Ik的下标k作为分析器的状态。分析表的ACTION子表和GOTO子表可按如下方法构造

令那个包含项目S’→•S的集合Ik的下标k为分析器的初态。

若项目A→α•aβ属于Ik且GO(Ik , a)= Ij,a为终结符,置ACTION[k,a]为“把(j,a)移进栈”,简记为“sj”。

若项目A→α•属于Ik,对任何终结符a(或结束符#),置ACTION[k,a]为“用产生式A→α进行归约”,简记为“rj”(假定产生式A→α是文法G’的第j个产生式)。

若项目S’→S•属于Ik,则置ACTION[k,#]为“接受”,简记为“acc”。

若GO(Ik , A)= Ij,A为非终结符,则置GOTO[k,A]=j。

分析表中凡不能用规则1至4填入信息的空白格均填上“报错标志”。

LR(0)分析法的分析过程

遍历输入字符串,对于每一个字符,获取当前状态栈的顶部的状态值,通过查询action表获取的当前的操作是移进、规约还是接受

如果当前操作是移进,将新的状态放入状态栈当中,当移入的字符放入符号栈中。

如果当前操作是规约,那么将需要规约的部分的状态从状态栈中弹出,将规约后的状态放入状态栈,将规约后的左部放入符号栈,当前的字符不向下推进

如果接收,则结束

————————————————

6.实验结果图

、实验体会、问题讨论

代码中值得改进的地方

make_set函数和make_go函数的更正:

- 错误主要源自于自己对于概念的模糊,make_set过程中如果加入的新的产生式的右侧”⋅⋅”之后依旧是没有出现过的非终结符,那么也要把以它为左部的”$cdot”在首位的项目加入当前的项目规范族

- make_go是在对规范族之间建边时,一定是通过一个字符的移进,所有与其相关的式子都符合才能建边,而不是只要有两个规范族中有符合要求的规范式就能建边

————————————————

做的较好的地方

1.LR(0)分析表构造算法

假定项目集规范族C={I0,I1,…,In}。令每一个项目集Ik的下标k作为分析器的状态。分析表的ACTION子表和GOTO子表可按如下方法构造

令那个包含项目S’→•S的集合Ik的下标k为分析器的初态。

若项目A→α•aβ属于Ik且GO(Ik , a)= Ij,a为终结符,置ACTION[k,a]为“把(j,a)移进栈”,简记为“sj”。

若项目A→α•属于Ik,对任何终结符a(或结束符#),置ACTION[k,a]为“用产生式A→α进行归约”,简记为“rj”(假定产生式A→α是文法G’的第j个产生式)。

若项目S’→S•属于Ik,则置ACTION[k,#]为“接受”,简记为“acc”。

若GO(Ik , A)= Ij,A为非终结符,则置GOTO[k,A]=j。

分析表中凡不能用规则1至4填入信息的空白格均填上“报错标志”。

2.

LR(0)分析法的分析过程

遍历输入字符串,对于每一个字符,获取当前状态栈的顶部的状态值,通过查询action表获取的当前的操作是移进、规约还是接受

如果当前操作是移进,将新的状态放入状态栈当中,当移入的字符放入符号栈中。

如果当前操作是规约,那么将需要规约的部分的状态从状态栈中弹出,将规约后的状态放入状态栈,将规约后的左部放入符号栈,当前的字符不向下推进

如果接收,则结束

————————————————

总结

通过这次LR(O)分析器的实验,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,进一步掌握了LR语法分析的方法。对于LR (O)方法有了更深刻的了解,不单单只是纸上谈兵,实验的完成,也就是实践的过程。虽然在这个实践的过程中遇到了一些困难,但是在努力下,通过后续的努力,终能够将LR(O)分析器完整实现。收获很多。

【LR(0)分析】LR(0)算法的分析与设计相关推荐

  1. 【算法设计与分析】排序算法性能分析

    github:项目地址 一.实验目的 掌握选择排序.冒泡排序.合并排序.快速排序.插入排序算法原理 掌握不同排序算法时间效率的经验分析方法,验证理论分析与经验分析的一致性. 二.实验概述 排序问题要求 ...

  2. 关联分析:FP-Growth算法

    转载自  关联分析:FP-Growth算法 关联分析又称关联挖掘,就是在交易数据.关系数据或其他信息载体中,查找存在于项目集合或对象集合之间的频繁模式.关联.相关性或因果结构.关联分析的一个典型例子是 ...

  3. 算法设计与分析——Johnson Trotter算法

    目录 前言 一.算法思想分析 二.算法效率分析 三.算法代码 C语言代码 后记 前言 排列与组合问题,无论是在我们生活中还是项目实际运用中,都说非常之常见的.那么,如何去运用算法思想生成全排列(一组元 ...

  4. LR(0)项目集规范族和分析表的构造

    1. LR分析 LR分析是干什么用的?简单来说就是你在编程时编译器用来判断你输入的符号串是否合法以及时哪一种类型.官方的说法时LR分析是一种能根据当前分析栈中的符号串和向右顺序查看输入串的k个符号就能 ...

  5. [编译原理]构造LR分析器和SLR移进归约分析表

    目录 目标 1.基础知识引入 1.1 文法 1.2 拓广文法 1.3 全部的项目集 2. 计算文法的LR(0)项目集的.识别活前缀的DFA 2.1 分析得到各个项目集 2.2 构建SLR分析表中的移进 ...

  6. 【转】PBOC3.0和PBOC2.0标准规范异同分析

    2013年2月,中国人民银行发布了<中国金融集成电路(IC)卡规范(V3.0)>(以下简称PBOC3.0),PBOC3.0是在中国人民银行2005年颁布的<中国金融集成电路(IC)卡 ...

  7. 聚焦可信AI与产业应用,百度联合发起千言计划实现情感分析2.0升级

    数据集是推动自然语言处理技术进步的基石.为应对自然语言处理技术应用中面临的多领域.多场景等诸多挑战,百度联合中国计算机学会.中国中文信息学会,于2020年8月共同发起中文自然语言处理数据共建计划--& ...

  8. opencv2.2.0源代码(include文件)分析

    由于openCV2.2.0源文件很庞大,这里我只分析openCV2.2.0文件组织结构的各个模块的include文件(重点分析各个模块下引用的算法和实现的功能),而不是src文件.这里分析各个模块有助 ...

  9. Blueprint代码详细分析-Android10.0编译系统(七)

    摘要:Blueprint解析Android.bp到ninja的代码流程时如何走的? 阅读本文大约需要花费18分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Andro ...

最新文章

  1. centos 7 lvs 负载均衡搭建部署
  2. opencv cuda使用笔记
  3. SQL SERVER大话存储结构:数据库数据文件
  4. 菜鸟教程:SQL 通用数据类型
  5. 老外听到哪些中式英文是崩溃的?(转自外贸Jackson)
  6. 图解Android 内存分析工具之Mat使用教程
  7. jQuery+css3实现新年贺卡
  8. SQL Server2005还原数据库攻略
  9. 手机游戏量产引擎研发手记-导读
  10. 在 Mac 上如何使用 iCloud 钥匙串保护信息安全?
  11. ajajx请求php能设置cookie,为什么在AJAX请求返回后浏览器没有设置cookie?
  12. NEXTCHIP图像品牌ISP和AHD都是有哪些功能?型号有多少型号?
  13. 10月SCI/SSCI/EI刊源更新,新增1区TOP,2022年仅剩不到三个月,还在观望吗?
  14. 服务器维修责合同,2021年服务器维护委托合同样本.doc
  15. 音乐频率的划分及播放器均衡器设置
  16. 点餐app的初步总结
  17. 【Dilated Conv】《Multi-Scale Context Aggregation by Dilated Convolutions》
  18. 20190915招商银行信用卡
  19. tensorflow: bn层 的 decay参数项
  20. Kettle--java代码组件实现密码加密(BCryptPasswordEncoder)

热门文章

  1. python2020安装教程_PyCharm 2020.2.2 x64 下载并安装的详细教程
  2. uefi引导gpt安装win10_【UEFI+GPT amp; Legacy+MBR】如何安装系统
  3. 一个未完成的文字rpg打怪小游戏。。。(难得写点东西)
  4. 汇龙安卓豆瓣顶贴软件的注意事项
  5. [嘭嘭养成记]4. 使用已有诸多动作数据,统计关节的活动范围
  6. 英语思维导图大全 形容词和副词(五)
  7. 自制ST-LINK V2 ,ST-LINK 固件
  8. 产销平衡的运输问题上机实验matlab_在产销平衡的运输问题中,下列说法 错误 的是( )_学小易找答案...
  9. MySQL 创建表 CREATE TABLE 语法
  10. mysql 创建相同数据库_mysql数据库找出相同数据MySQL常用操作