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] << "\t";
    }
    cout << endl<< "VN:";
    for (int i = 0; i <3; i++)
    {
        cout << vn[i] << "\t";
    }
    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<<"\t";
    showStack(symbols);
    cout<<"\t";
    cout<<input.substr(com);
    cout<<"\t\t"<<nowcout<<"\t"<<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 << "\tError" << endl;
            break;
        }
        else if (action[i][t] == "acc")
        {
            show("",0);
            //cout << "acc" << "\t 分析成功" << endl;
            break;
        }
    }
}

int main()
{
    init();
    cout<<"輸入的文法:"<<endl;
    cin>>input;
    cout<<"狀態棧\t符號棧\t輸入串\t\tACTION\tGOTO\n";
    show("0",0);
    analysis(input);
    return 0;
}
View Code

四、運行結果

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM