• SLR(1)语法分析


    一、题目

      对下列文法,用SLR(1)分析法对任意输入的符号串进行分析:

      (1)S->E

      (2)E->E+T

      (3)E->T

      (4)T->T*F

      (5)T->F

      (6)F->(E)

      (7)F->i

    二、设计思路

    (1)总控程序,也可以称为驱动程序。对所有的LR分析器总控程序都是相同的。

    (2)分析表或分析函数,不同的文法分析表将不同,同一个文法采用的LR分析器不同时,分析表将不同,分析表又可以分为动作表(ACTION)和状态转换(GOTO)表两个部分,它们都可用二维数组表示。

    (3)分析栈,包括文法符号栈和相应的状态栈,它们均是先进后出栈。

    分析器的动作就是由栈顶状态和当前输入符号所决定。

     LR分析器由三个部分组成:

    其中:SP为栈指针,S[i]为状态栈,X[i]为文法符号栈。状态转换表用GOTO[i,X]=j表示,规定当栈顶状态为i,遇到当前文法符号为X时应转向状态j,X为终结符或非终结符。

     ACTION[i,a]规定了栈顶状态为i时遇到输入符号a应执行。动作有四种可能:

    (1)移进:

        action[i,a]= Sj:状态j移入到状态栈,把a移入到文法符号栈,其中i,j表示状态号。

    (2)归约:

        action[i,a]=rk:当在栈顶形成句柄时,则归约为相应的非终结符A,即文法中有A- B的产生式,若B的长度为R(即|B|=R),则从状态栈和文法符号栈中自顶向下去掉R个符号,即栈指针SP减去R,并把A移入文法符号栈内,j=GOTO[i,A]移进状态栈,其中i为修改指针后的栈顶状态。

    (3)接受acc:

        当归约到文法符号栈中只剩文法的开始符号S时,并且输入符号串已结束即当前输入符是'#',则为分析成功。

    (4)报错:

    当遇到状态栈顶为某一状态下出现不该遇到的文法符号时,则报错,说明输入端不是该文法能接受的符号串。

    三、源代码

    #include<bits/stdc++.h>
    using namespace std;
    
    char vt[6] = { 'i', '+', '*', '(', ')', '#' }; //终结符
    char vn[3] = { 'E', 'T', 'F' }; //非终结符
    
    //文法
    string wf[7] =
    {
        "S->E",
        "E->E+T",
        "E->T",
        "T->T*F",
        "T->F",
        "F->(E)",
        "F->i"
    };
    
    //action表
    string action[12][6] =
    {
        "s5", "^", "^", "s4", "^", "^",
        "^", "s6", "^", "^", "^", "acc",
        "^", "r2", "s7", "^", "r2", "r2",
        "^", "r4", "r4", "^", "r4", "r4",
        "s5", "^", "^", "s4", "^", "^",
        "^", "r6", "r6", "^", "r6", "r6",
        "s5", "^", "^", "s4", "^", "^",
        "s5", "^", "^", "s4", "^", "^",
        "^", "s6", "^", "^", "s11", "^",
        "^", "r1", "s7", "^", "r1", "r1",
        "^", "r3", "r3", "^", "r3", "r3",
        "^", "r5", "r5", "^", "r5", "r5"
    };
    
    //goto表
    int goto_[12][3] =
    {
        1, 2, 3,
        0, 0, 0,
        0, 0, 0,
        0, 0, 0,
        8, 2, 3,
        0, 0, 0,
        0, 9, 3,
        0, 0, 10,
        0, 0, 0,
        0, 0, 0,
        0, 0, 0,
        0, 0, 0
    };
    
    //当前状态
    string nowcout="0";
    //输入串的游标
    int com = 0;
    int num = 1;
    
    int t=0;
    //输入串
    string input = "";
    
    stack <char> symbols;//创建一个符号栈
    
    stack <int> status;//创建一个状态栈
    
    void show(string statuA,int statuG);
    void init()
    {
        cout<<"输入的文法"<<endl;
        for (int j = 0; j < 6; j++)
        {
            cout << wf[j] << endl;
        }
        cout << "VT:";
        for (int i = 0; i < 6; i++)
        {
            cout << vt[i] << "	";
        }
        cout << endl<< "VN:";
        for (int i = 0; i <3; i++)
        {
            cout << vn[i] << "	";
        }
        cout << endl;
        symbols.push('#');
        status.push(0);
    
    }
    //获取非终结符所在下标
    int getVtNowIndex(char now)
    {
        for(int i=0;i<6;i++)
        {
            if(now==vt[i])
            {
                return i;
            }
        }
        return -1;
    }
    //获取终结符所在下标
    int getVnNowIndex(char now)
    {
        for(int i=0;i<3;i++)
        {
            if(now==vn[i])
            {
                return i;
            }
        }
        return -1;
    }
    
    //输出栈中元素但是不破坏栈的结构
    int showStack(stack<int >&s){
        stack <int> temp;
        int num=s.size();
        for(int i=0;i<num;i++)
        {
            temp.push(s.top());
            s.pop();
        }
        for(int i=0;i<num;i++)
        {
            cout<<temp.top();
            s.push(temp.top());
            temp.pop();
        }
    }
    
    //输出栈中元素但是不破坏栈的结构
    char showStack(stack<char >&s){
        stack <char> temp;
        int num=s.size();
        for(int i=0;i<num;i++)
        {
            temp.push(s.top());
            s.pop();
        }
        for(int i=0;i<num;i++)
        {
            cout<<temp.top();
            s.push(temp.top());
            temp.pop();
        }
    }
    //格式化输出
    void show(string statuA,int statuG)
    {
        showStack(status);
        cout<<"	";
        showStack(symbols);
        cout<<"	";
        cout<<input.substr(com);
        cout<<"		"<<nowcout<<"	"<<statuG<<endl;
    
    
    }
    //移进
    void yj(int statu,char symbol)
    {
    
        symbols.push(symbol);
        status.push(statu);
        string statuA = "s"+statu;
        show(statuA,0);
        com++;
    }
    //规约
    void gy(int index)
    {
    
        int n = wf[index].length()-3;
        for(int i=0;i<n;i++)
        {
            symbols.pop();
            status.pop();
        }
        symbols.push(wf[index][0]);
        int indexj = getVnNowIndex(wf[index][0]);
        int indexi = status.top();
        status.push(goto_[indexi][indexj]);
        string statuA = "r"+index;
        show(statuA,goto_[indexi][indexj]);
    }
    //分析
    void analysis(string s)
    {
        while(com<input.size())
        {
            int i = status.top();
            char ch = s[com];
            t=getVtNowIndex(ch);
            nowcout=action[i][t];
            if (action[i][t][0] == 's')
            {
                int t1 = action[i][t][1]-'0';
                yj(t1, ch);
            }
            else if (action[i][t][0] == 'r')
            {
                gy(action[i][t][1]-'0');
            }
            else if (action[i][t] == "^")
            {
                cout << "	Error" << endl;
                break;
            }
            else if (action[i][t] == "acc")
            {
                show("",0);
                //cout << "acc" << "	 分析成功" << endl;
                break;
            }
        }
    }
    
    int main()
    {
        init();
        cout<<"输入的文法:"<<endl;
        cin>>input;
        cout<<"状态栈	符号栈	输入串		ACTION	GOTO
    ";
        show("0",0);
        analysis(input);
        return 0;
    }
    View Code

    四、运行结果

  • 相关阅读:
    题解:luoguP1070 道路游戏(DP)
    题解:luoguP2577【ZJOI2005】午餐(DP)
    题解:bzoj1801: [Ahoi2009]chess 中国象棋
    题解:bzoj1878: [SDOI2009]HH的项链
    SpringBoot静态资源文件 lion
    简要的Log4Net 应用配置
    Web Service 初级教程
    log4Net 动态改变写入文件
    Ornament 类型资源权限
    JQuery 引发两次$(document).ready事件
  • 原文地址:https://www.cnblogs.com/20183544-wangzhengshuai/p/13983228.html
Copyright © 2020-2023  润新知