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[iX]=j表示,規定當棧頂狀態為i,遇到當前文法符號為X時應轉向狀態jX為終結符或非終結符。
  • ACTION[ia]規定了棧頂狀態為i時遇到輸入符號a應執行。動作有四種可能:

(1)移進:

action[ia]= Sj:狀態j移入到狀態棧,把a移入到文法符號棧,其中i,j表示狀態號。

(2)歸約:

action[ia]=rk:當在棧頂形成句柄時,則歸約為相應的非終結符A,即文法中有A- B的產生式,若B的長度為R(|B|=R),則從狀態棧和文法符號棧中自頂向下去掉R個符號,即棧指針SP減去R,並把A移入文法符號棧內,j=GOTO[i,A]移進狀態棧,其中i為修改指針后的棧頂狀態。

(3)接受acc:

當歸約到文法符號棧中只剩文法的開始符號S時,並且輸入符號串已結束即當前輸入符是'#',則為分析成功。

(4)報錯:

當遇到狀態棧頂為某一狀態下出現不該遇到的文法符號時,則報錯,說明輸入端不是該文法能接受的符號串。

源程序

#include <iostream>

#include <iomanip>

#include <cstdlib>

#include <vector>

#include <string>

#include <utility>

using namespace std;

 

#define numStates 6

#define numInputs 3

 

int t(char);

int go(char);

 

 

char terminals[numInputs] = { '(', ')', '$' };

string table[numStates][numInputs] =

{ // ( ) $

    { "s:2", "r:S~!", "r:S~!" },

    { "", "", "a:" },

    { "s:2", "r:S~!", "r:S~!" },

    { "", "s:4", "" },

    { "s:2", "r:S~!", "r:S~!" },

    { "", "r:S~(S)S", "r:S~(S)S" }

};

 

char nonterminals[1] = { 'S' };

int gotos[numStates][1] =

{

    { 1 },

    { -1 },

    { 3 },

    { -1 },

    { 5 },

    { -1 }

};

 

 

int main()

{

    char k;

    const int spacing = 10;

    int state;

    char in;

    string action;

 

    vector < pair < char, int > > stack;

    stack.push_back(make_pair('$', 0));

    cout << "hello, Press Return to step through parse" << endl << endl;

 

    string input = "()()$";

 

    cout << "Enter your input string to recognize: ";

    getline(cin, input);

    input += '$';

 

 

    cout << setfill('=') << left << setw(2 * spacing) << "Stack"

        << setw(2 * spacing) << "Input"

        << setw(2 * spacing) << "Action" << endl << setfill(' ');

 

    while (1)

    {

 

        // Display stack

        cout << endl;

        int u = 0;

        for (u = 0; u<stack.size(); u++)

            cout << stack[u].first << " " << stack[u].second << " ";

        for (; u<7; u++)

            cout << " ";

        for (int u = input.size(); u<spacing; u++)

            cout << " ";

 

        // Display input

        cout << setw(spacing) << input;

 

        // Display the action code to take

        cout << setw(spacing) << left << action;

 

        state = stack.back().second;

 

        in = input[0];

 

        

        action = table[state][t(in)];

 

        // Stepping pause

        cin.get();

 

        cout << "=> ";

 

        // blank/error cell

        if (action == "")

        {

            cout << "ERROR input not accepted" << endl;

            return 0;

        }

 

        // Accepted cell

        else if (action[0] == 'a')

        {

            cout << "INPUT STRING ACCEPTED" << endl;

            return 0;

        }

 

        // Reduction

        else if (action[0] == 'r')

        {

            cout << "Reducing '" << action.substr(4, action.length() - 1)

                << "' on the stack to " << action[2];

 

 

            

            for (int i = action.length() - 1; i>3; i--)

            {

 

                if (stack.back().first == action[i])

                    stack.pop_back();

 

 

                // Epsilons do not consume anything

                else if (action[i] == '!')

                    continue;

 

 

                else

                {

                    cout << "Error in reduce, expected "

                        << stack.back().first << endl;

                    return 0;

                }

            }

 

            cout << " Then goto state " << gotos[stack.back().second][go(action[2])] << endl;

 

 

            stack.push_back(

                make_pair(

                action[2],

                gotos[stack.back().second][go(action[2])]));

        }

 

 

 

        // Shift

        else if (action[0] == 's')

        {

            cout << "Shifting top of input to stack and moving to state " << action[2] << endl;

 

            stack.push_back(

                make_pair(

                input[0],

                action[2] - 48));

 

            input.erase(0, 1);

        }

    }

 

    return 0;

}

 

 

int t(char terminal)

{ // Linear search bad

    for (int i = 0; i<numInputs; i++)

    if (terminals[i] == terminal)

        return i;

    cout << "t(): There was an error in look finding '" << terminal << "' in the table." << endl;

    return -1;

}

 

int go(char nterminal)

{ // Linear search bad

    for (int i = 0; i<numInputs; i++)

    if (nonterminals[i] == nterminal)

        return i;

    cout << "go(): There was an error in look finding '" << nterminal << "' in the table." << endl;

    return -1;

}

結果

 


免責聲明!

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



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