【编译原理】基于LR分析表编写语法分析器

问题

【问题描述】已知文法G[E]:

E → E + T | T

T → (E) | id | id[E]

设计LR分析表,并用c++语言编写语法分析器。

【输入形式】一个句子
【输出形式】句子语法结构正确,输出“Syntax analysis is right”反之输出“Error on syntax analysis”

【样例输入】a1+a2
【样例输出】Syntax analysis is right

【样例说明】
【评分标准】根据通过的测试数据个数评分

思路

0x01 画出LR(0)项目集规范族

其中

I1,I4存在移入规约冲突

对于I1:

{+} ∩ FOLLOW(S) = { + } ∩ {#} = $ \emptyset $

对于I4:

{ [ } ∩ FOLLOW(T) = {[} ∩ FOLLOW(E) ={ [ } ∩ { +,),],# } = $ \emptyset $

所以,适用SLR(1)文法

0x02 做出SLR分析表

ACTION GOTO
+ ( ) [ ] id # E T
0 s3 s4 1 2
1 s5 acc
2 r2 r2 r2 r2
3 s3 s4 6 2
4 r4 r4 s7 r4 r4
5 s3 s4 8
6 s5 s9
7 s3 s4 10 2
8 r1 r1 r1 r1
9 r3 r3 r3 r3
10 s5 s11
11 r5 r5 r5 r5

对于产生式:

0、S -> E

1、E -> E+T

2、E ->T

3、T ->(E)

4、T ->id

5、T ->id[E]
进行代码编写模拟分析过程:

代码:

#include <iostream>
#include <stack>
#include <vector>
#include <queue>
#include <string>
#include <map>
using namespace std;

//action 表
vector<string> action[12];
void initial_action_table()
{
    
    
    
    for (int i = 0;i < 12;i++)
    {
    
    
        for (int j = 0;j < 7;j++)
        {
    
    
            action[i].push_back("NULL");
        }
    }

    action[0][1] = "s3";action[0][5] = "s4";
    action[1][0] = "s5";action[1][6] = "acc";
    action[2][0] = "r2";action[2][2] = "r2";action[2][4] = "r2";action[2][6] = "r2";
    action[3][1] = "s3";action[3][5] = "s4";
    action[4][0] = "r4";action[4][2] = "r4";action[4][3] = "s7";action[4][4] = "s7";action[4][4] =  "r4";action[4][6] =  "r4";
    action[5][1] = "s3";action[5][5] = "s4";
    action[6][0] = "s5";action[6][2] = "s9";
    action[7][1] = "s3";action[7][5] = "s4";
    action[8][0] = "r1";action[8][2] = "r1";action[8][4] = "r1";action[8][6] = "r1";
    action[9][0] = "r3";action[9][2] = "r3";action[9][4] = "r3";action[9][6] = "r3";
    action[10][0] = "s5";action[10][4] = "s11";
    action[11][0] = "r5";action[11][2] = "r5";action[11][4] = "r5";action[11][6] = "r5";
} 

//goto表
int goTo[12][2] = {
    
    
    1, 2,
    0, 0, 
    0, 0,
    6, 2,
    0, 0,
    0, 8,
    0, 0,
    10, 2,
    0, 0,
    0, 0,
    0, 0,
    0, 0
};

//Vt、Vn
vector<char> Vn = {
    
    '+', '(', ')', '[', ']', 'a', '#'};
vector<char> Vt = {
    
    'S', 'E', 'T'};

/*
我们需要表达用 
1、表达式左部 进行归约
2、表达式右部的长度用于出栈
对产生式进行编号:
0、S -> E
1、E -> E+T
2、E ->T
3、T ->(E)
4、T ->id
5、T ->id[E]
*/
struct Production{
    
    
    char Vt;
    int length; 
};

Production pro[6] = {
    
     {
    
    'S',1}, {
    
    'E',3}, {
    
    'E',1}, {
    
    'T',3}, {
    
    'T',1}, {
    
    'T',4}};

//状态栈
stack<int> state;
//符号栈
queue<char> symbol;

void initial_queue()
{
    
    
//输入:
    char ch;
    // {'+', '(', ')', '[', ']', 'i', '#'};
    while((ch = getchar()) != EOF)
    {
    
    
        switch(ch)
        {
    
    
            case '+': symbol.push('+');break;
            case '(': symbol.push('(');break;
            case ')': symbol.push(')');break;
            case '[': symbol.push('[');break;
            case ']': symbol.push(']');break;
            case 'a': 
               if (isdigit(getchar())) 
                    symbol.push('a');
                    break;
            default:
                break;
        }
    }

    symbol.push('#');
}
int main()
{
    
    
    initial_action_table();
    initial_queue();
    state.push(0);

    map<char, int> Vn2num;
    int k = 0; 
    for (vector<char>::iterator it = Vn.begin();it != Vn.end(); it++)
    {
    
    
        Vn2num.insert(pair<char,int>(*it, k));
        k++;
    }

    while(1)
    {
    
    
        char ch = symbol.front();
        int top = state.top();
        int index = Vn2num[ch];
        string str = action[top][index];
        if(str[0] == 's')
        {
    
    
            int nextstate = 0;
            for(int i = 1; str[i] ; i++)
            {
    
    
                nextstate = nextstate*10 + (str[i] - '0');
            }

            state.push(nextstate);
            symbol.pop();
        }

        if(str[0] == 'r')
        {
    
    
            int pro_index = 0; //产生式标号
            for(int i = 1; str[i] ; i++)
            {
    
    
                pro_index = pro_index*10 + (str[i] - '0');
            }
            int popnum = pro[pro_index].length;
            char Vt = pro[pro_index].Vt;
            //出栈
            for(int i = 0;i < popnum;i ++)
            {
    
    
               state.pop();
            }
            //GOTO 查出栈后的状态的GOTO表
            if(Vt == 'E')
            {
    
    
                state.push(goTo[state.top()][0]);
            }
            else
            {
    
    
                state.push(goTo[state.top()][1]);
            }   
        }

        if(str[0] == 'a')
        {
    
    
            cout << "Syntax analysis is right"; break;
        }
        if(str[0] == 'N')
        {
    
    
            cout << "Error on syntax analysis"; break;
        } 
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_44795952/article/details/112406861
今日推荐