《编译原理》:基于SLR(1)的语义分析

实验目的与内容

实验目的

  1. 实现SLR(1)分析的语义分析与中间代码生成程序设计原理:
  • 深入了解SLR(1)分析方法,以实现对源代码的语义分析。
  • 设计和实现编译器前端,包括语法分析和中间代码生成阶段。
  1. 掌握语法制导的基本概念:
  • 理解语法制导翻译的基本理念和原则。
  • 利用语法规则引导语义分析,确保编译器能够准确地理解源代码结构。
  1. 研究目标代码结构分析的基本方法:
  • 学习目标代码的结构分析技术,以确保生成的中间代码在后续阶段能够被正确翻译为目标代码。
  • 掌握如何优化目标代码结构,以提高最终程序的执行效率。
  1. 实现赋值语句语法制导生成四元式的基本原理和方法:
  • 理解赋值语句的语法结构,并通过语法制导方法生成对应的四元式。
  • 考虑语义信息,确保生成的中间代码能够准确地反映源代码的语义。
  1. 完善语法分析和语义分析过程:
  • 设计和实现强大的语法分析器,确保对源代码进行准确的结构分析。
  • 在语义分析阶段,处理语法制导的翻译,生成相应的中间代码。

实验内容

        以专题1词法分析程序的输出为语法分析的输入,完成以下描述赋值语句SLR(1)文法的语义分析及中间代码四元式的过程,实现编译器前端。

G[S]: S→V=E

E→E+T∣E-T∣T    

       T→T*F∣T/F∣F

       F→(E)∣i

       V→i


实验要求

 设计说明

        终结符号i为用户定义的简单变量,即标识符的定义。重点解决SLR(1)分析表构造,赋值语句文法的改写和语义动作的添加。解决编译程序总体结构理解问题,理解语法制导翻译过程的基本概念和实现方法,理解编译器前端的组成。

设计要求

  1. 构造文法的SLR(1)分析表,设计语法制导翻译过程,给出每一产生式对应的语义动作;
  2. 设计中间代码四元式的结构;
  3. 输入串应是词法分析的输出二元式序列,即某赋值语句“专题1”的输     出结果,输出为赋值语句的四元式序列中间文件;
  4. 以交互界面的形式给出SLR(1)分析过程,要求包括符号栈、状态栈、输入串等的变化情况以及当前完成的动作。
  5. 设计两个测试用例(尽可能完备),并给出程序执行结果四元式序列。
  6. 选做:考虑根据文法自动构造SLR(1)分析表,并添加到你的程序中。

实验过程

完整代码

#define _CRT_SECURE_NO_WARNINGS  1
#include <string>
#include <list>
#include <stack>
#include <iostream>
#include <algorithm>
#include<cstring>

using namespace std;

typedef struct s
{
    int finish = 0;  // Whether finished
    int tag = 3;     // Current position of the dot
    string str;
} sentence;

typedef struct
{
    int I;        // Current state
    char Vt;      // Terminal symbol
    char tag;     // r or s
    int action;   // Action
} act;

typedef struct
{
    int I;        // Current state
    char Vn;      // Non-terminal symbol
    int next_I;   // Transition state
} go;

typedef struct
{
    int number;   // Number
    list<sentence> l;
} I;  // State

typedef struct
{
    char op;
    char arg1;
    char arg2;
    char result;
} siyuanshi;

typedef struct
{
    char name;
    string value;  // Place
} var;  // Variable

list<I> DFA;        // State set
list<char>* First;  // FIRST set
list<char>* Follow; // FOLLOW set
list<act> ACTION;   // ACTION[i][j]
list<go> GOTO;      // GO[i][j]
list<char> Vt;      // Terminal symbols set
list<char> Vn;      // Non-terminal symbols set

char input[100];    // Read input from lexical analysis

void readfile()
{
    cout << "-------------------------------------------------------" << endl;
    cout << "Read file to get input statements:" << endl;
    FILE* fp;
    char buf[1000];
    if ((fp = fopen("./test2.txt", "r")) != NULL) {
        while (fgets(buf, 1000, fp) != NULL)
        {
            int len = strlen(buf);
            printf("%s", buf);
            int flag = 0;

            for (int i = 0; i < len; i++) {
                if (buf[i] == '(' && flag == 0) {
                    flag = 1; // Recognize symbol
                    for (int j = i + 1; j < len; j++) {
                        if (buf[j] == ',') {
                            input[strlen(input)] = buf[j + 1];
                            i = j + 1;
                            break;
                        }
                    }
                }
                else if (flag == 1 && buf[i] == ')') {
                    flag = 0;
                }
            }
        }
    }
    input[strlen(input)] = '#';
    fclose(fp);
    cout << endl;
    cout << endl << "Input string: " << input << endl << endl;
}

int S[100];         // Analysis stack
int S_top = 0;      // Analysis stack top
char T[100];         // Symbol stack, top is the same as the analysis stack
string value[100];   // Store symbol attributes
list<siyuanshi> L_sys;  // Quadruple
list<int> sys;          // States set that generate quadruples
list<var> V;            // Variable table

int result_count = 0;
string G[11] = { "S->A", "A->V=E", "E->E+T", "E->E-T", "E->T", "T->T*F", "T->T/F", "T->F", "F->(E)", "F->i", "V->i" };

act getACTION(int i, char b)
{
    char c = b;
    if (b >= 'a' && b <= 'z')
        b = 'i';
    list<act>::iterator it;
    for (it = ACTION.begin(); it != ACTION.end(); it++)
    {
        if (it->I == i && it->Vt == b)
        {
            return *it;
        }
    }
    return { 0,0,0,0 };  // ERROR
}

int getGOTO(int i, char b)
{
    list<go>::iterator it;
    for (it = GOTO.begin(); it != GOTO.end(); it++)
    {
        if (it->I == i && it->Vn == b)
            return  it->next_I;
    }
    return -1;  // ERROR
}

char newTemp()
{
    char c = 'A';
    result_count++;
    return c + result_count - 1;
}

void SLR()
{
    int V_num = 0;  // Symbol table
    int index = 0;
    S[0] = 0;  // Initialize
    cout << "Analysis stack: (| | contains attributes of non-terminal symbols)" << endl;
    while (getACTION(S[S_top], input[index]).tag != 'r' || getACTION(S[S_top], input[index]).action != 0)  // acc
    {
        if (getACTION(S[S_top], input[index]).tag == 0)  // ERROR
        {
            cout << "Error!" << endl;  // Error handling
            return;
        }
        else if (getACTION(S[S_top], input[index]).tag == 's')
        {   // push
            S[S_top + 1] = getACTION(S[S_top], input[index]).action;  // Push operation
            T[S_top + 1] = input[index];
            value[S_top + 1] = input[index];
            S_top++;
            index++;  // Advance(); read the next symbol
        }
        else if (getACTION(S[S_top], input[index]).tag == 'r')
        {
            char arg1, arg2, result;  // Quadruple
            int i = getACTION(S[S_top], input[index]).action;  // Production to be reduced
            string str = "";
            for (int j = 0; j < G[i].length() - 3; j++)
            {
                // pop operation
                if (value[S_top] != "(" && value[S_top] != ")")
                {
                    string ss = "";
                    ss += value[S_top];
                    ss += str;
                    str = string(ss);
                }
                if (j == 0)
                    if (value[S_top].length() == 1)  // Single symbol
                        arg1 = value[S_top][0];
                    else  // Look up the table, find the symbol
                    {
                        for (list<var>::iterator v = V.begin(); v != V.end(); v++)
                        {
                            if (v->value == value[S_top])
                            {
                                arg1 = v->name;
                                break;
                            }
                        }
                    }
                if (j == 2)
                    if (value[S_top].length() == 1)
                        arg2 = value[S_top][0];
                    else
                        for (list<var>::iterator v = V.begin(); v != V.end(); v++)
                        {
                            if (v->value == value[S_top])
                            {
                                arg2 = v->name;
                                break;
                            }
                        }
                S[S_top] = -1;
                T[S_top] = 0;
                value[S_top] = "";
                S_top--;
            }
            for (list<int>::iterator ii = sys.begin(); ii != sys.end(); ii++)  // Generate quadruple
                if (i == *ii)
                {
                    result = newTemp();
                    V.push_back({ result, str });
                    L_sys.push_back({ G[i][4], arg1, arg2, result });
                    break;
                }
            // push
            S[S_top + 1] = getGOTO(S[S_top], G[i][0]);
            T[S_top + 1] = G[i][0];
            value[S_top + 1] = str;  // Attribute transfer
            S_top++;
        }
        for (int tt = 0; tt <= 15; tt++)
        {
            if (tt <= S_top)
                if (S[tt] >= 10)
                    cout << S[tt] << " ";
                else
                    cout << S[tt] << "  ";
            else
                cout << "   ";
        }
        for (int tt = 0; tt <= S_top; tt++)
        {
            if (tt <= S_top)
            {
                cout << T[tt] << " ";
                if (isupper(T[tt]))
                    cout << "|" << value[tt] << "| ";
            }
            else
                cout << "  ";
        }
        cout << endl;
    }
    cout << endl << "Match successful!" << endl;
    cout << endl << "Quadruples:" << endl;
    for (list<siyuanshi>::iterator s = L_sys.begin(); s != L_sys.end(); s++)
    {
        cout << '(' << s->op << "," << s->arg1 << "," << s->arg2 << ',' << s->result << ')' << endl;
    }
}
void print(sentence s)
{
    int r;
    cout << "  ";
    for (r = 0; r < s.str.length(); r++)
        if (r == s.tag)
            cout << "·" << s.str[r];
        else
            cout << s.str[r];
    if (r == s.tag)
        cout << "·";
    cout << endl;
}

void find(char ch, int tag_Vn)
{
    for (int qq = 0; qq < 11; qq++)
    {
        if (ch == G[qq][0])
        {
            if (G[qq][3] >= 'A' && G[qq][3] <= 'Z')
                if (G[qq][3] == ch)  // Avoiding infinite loop and repeated searches
                    ;
                else
                    find(G[qq][3], tag_Vn);
            else
            {
                int tag = 0;
                for (list<char>::iterator i = First[tag_Vn].begin(); i != First[tag_Vn].end(); i++)
                {
                    if (*i == G[qq][3])
                    {
                        tag = 1;
                        break;
                    }
                }
                if (tag == 0)
                    First[tag_Vn].push_back(G[qq][3]);
            }
        }
    }
}

int findVn(char c)
{
    int tag = -1;
    for (list<char>::iterator i = Vn.begin(); i != Vn.end(); i++)
    {
        tag++;
        if (c == *i)
            return tag;
    }
    return -1;
}

void scan()  // Construct symbol sets
{
    for (int i = 0; i < 11; i++)// Grammar length
    {
        for (int j = 0; j < G[i].length(); j++)
        {
            if (j == 1 || j == 2)
                continue;
            if (isupper(G[i][j]))
            {
                if (find(Vn.begin(), Vn.end(), G[i][j]) == Vn.end())
                    Vn.push_back(G[i][j]);
            }
            else
            {
                if (find(Vt.begin(), Vt.end(), G[i][j]) == Vt.end())
                    Vt.push_back(G[i][j]);
            }
        }
    }
    Vt.push_back('#');
    First = new list<char>[Vn.size()];
    int tag_Vn = -1;
    for (list<char>::iterator ch = Vn.begin(); ch != Vn.end(); ch++)
    {
        tag_Vn++;
        for (int qq = 0; qq < 11; qq++)
        {
            if (*ch == G[qq][0])
            {
                if (G[qq][3] >= 'A' && G[qq][3] <= 'Z')
                {
                    find(G[qq][3], tag_Vn);
                }
                else
                {
                    First[tag_Vn].push_back(G[qq][3]);
                }
            }
        }
    }
    Follow = new list<char>[Vn.size()];
    Follow[0].push_back('#');
    int follow_sum = 0;  // Follow set total quantity
    int previous_sum = -1;  // Previous total
    while (follow_sum != previous_sum)
    {
        for (int i = 0; i < 11; i++)
        {
            for (int j = 3; j < G[i].length() - 1; j++)
            {
                if (isupper(G[i][j]))
                    if (!isupper(G[i][j + 1]))  // Terminal symbol
                    {
                        int tag = 0;
                        for (list<char>::iterator ii = Follow[findVn(G[i][j])].begin(); ii != Follow[findVn(G[i][j])].end(); ii++)
                        {
                            if (*ii == G[i][j + 1])
                            {
                                tag = 1;
                                break;
                            }
                        }
                        if (tag == 0)
                            Follow[findVn(G[i][j])].push_back(G[i][j + 1]);
                    }
                    else  // Non-terminal symbol
                    {
                        for (list<char>::iterator ii = Follow[findVn(G[i][j + 1])].begin(); ii != Follow[findVn(G[i][j + 1])].end(); ii++)
                        {
                            if (find(Follow[findVn(G[i][j + 1])].begin(), Follow[findVn(G[i][j + 1])].end(), *ii) == Follow[findVn(G[i][j + 1])].end())  // Not repeated
                                Follow[findVn(G[i][j])].push_back(*ii);
                        }
                    }
            }
            if (isupper(G[i][G[i].length() - 1]))
                for (list<char>::iterator ii = Follow[findVn(G[i][0])].begin(); ii != Follow[findVn(G[i][0])].end(); ii++)
                {
                    if (find(Follow[findVn(G[i][G[i].length() - 1])].begin(), Follow[findVn(G[i][G[i].length() - 1])].end(), *ii) == Follow[findVn(G[i][G[i].length() - 1])].end())  // Not repeated
                        Follow[findVn(G[i][G[i].length() - 1])].push_back(*ii);
                }
        }
        previous_sum = follow_sum;
        follow_sum = 0;
        for (int ii = 0; ii < Vn.size(); ii++)
        {
            follow_sum += Follow[ii].size();
        }
    }
    list<char>::iterator iter;
    cout << "Terminal symbols set: ";
    for (iter = Vt.begin(); iter != Vt.end(); iter++)
    {
        cout << *iter;
    }
    cout << endl;
    cout << "Non-terminal symbols set: ";
    for (iter = Vn.begin(); iter != Vn.end(); iter++)
    {
        cout << *iter;
    }
    cout << endl;
    int pp;
    cout << "FIRST" << endl;
    for (pp = 0, iter = Vn.begin(); pp < Vn.size(); pp++, iter++)
    {
        cout << *iter << "     ";
        for (list<char>::iterator ch = First[pp].begin(); ch != First[pp].end(); ch++)
        {
            cout << *ch << " ";
        }
        cout << endl;
    }
    cout << "FOLLOW" << endl;
    for (pp = 0, iter = Vn.begin(); pp < Vn.size(); pp++, iter++)
    {
        cout << *iter << "     ";
        for (list<char>::iterator ch = Follow[pp].begin(); ch != Follow[pp].end(); ch++)
        {
            cout << *ch << " ";
        }
        cout << endl;
    }
}

I closure(I& dfa)
{
    list<sentence>::iterator iter;
    for (iter = dfa.l.begin(); iter != dfa.l.end(); iter++)
    {
        if ((iter->tag <= iter->str.length()))
            if ((iter->str[iter->tag] >= 'A' && iter->str[iter->tag] <= 'Z'))
            {
                for (int tt = 0; tt < 11; tt++)  // Find the corresponding production
                {
                    if (iter->str[iter->tag] == G[tt][0])
                    {
                        int q = 0;
                        list<sentence>::iterator it;
                        sentence x;
                        x.str = G[tt];
                        for (it = dfa.l.begin(); it != dfa.l.end(); it++)
                        {
                            if ((it->str == x.str) && (it->tag == x.tag))
                            {
                                q = 1;
                                break;
                            }
                        }
                        if (q == 0)
                        {
                            dfa.l.push_back(x);
                        }
                    }
                }
            }
    }
    return dfa;
}

int compare(I a, I b) // Whether equal
{
    if (a.l.size() != b.l.size())
        return 1;
    else
    {
        for (list<sentence>::iterator iii = a.l.begin(), jjj = b.l.begin(); iii != a.l.end() || jjj != b.l.end(); iii++, jjj++)
            if (iii->str != jjj->str || iii->tag != jjj->tag)  // Check if equal
            {
                return 1;
            }
    }
    return 0;
}

void table()
{
    int num = 0;
    sentence first;  // Starting symbol
    first.str = G[0];
    I L;
    L.number = 0;
    L.l.push_back(first);
    DFA.push_back(L);
    list<I>::iterator dfa;
    for (dfa = DFA.begin(); dfa != DFA.end(); dfa++)
    {
        list<sentence>::iterator iter;
        closure(*dfa);
        for (iter = dfa->l.begin(); iter != dfa->l.end(); iter++)  // Process each right part of the production in the state
            if (iter->finish == 0)
            {
                I C;  // New state
                C.number = DFA.size();
                if (iter->tag < iter->str.length())  // Not completed yet
                {
                    sentence s;
                    s.str = iter->str;
                    if (iter->str[iter->tag] >= 'A' && iter->str[iter->tag] <= 'Z')
                    {
                        GOTO.push_back({ dfa->number,iter->str[iter->tag],C.number });
                    }
                    else
                    {
                        ACTION.push_back({ dfa->number,iter->str[iter->tag],'s',C.number });
                    }
                    s.tag = iter->tag + 1;
                    iter->finish = 1;
                    C.l.push_back(s);
                    list<sentence>::iterator i;
                    for (i = iter, i++; i != dfa->l.end(); i++)
                        if (i->str[i->tag] == iter->str[iter->tag])
                        {
                            s.str = i->str;
                            s.tag = i->tag + 1;
                            i->finish = 1;
                            C.l.push_back(s);
                        }
                    int judge = 0, count = 0;
                    for (list<I>::iterator ii = DFA.begin(); ii != DFA.end(); ii++, count++)  // Check for duplicates
                    {
                        judge = compare(*ii, closure(C));  // Modify C
                        if (judge == 0)
                            break;
                    }
                    if (judge == 0)
                    {
                        if (iter->str[iter->tag] >= 'A' && iter->str[iter->tag] <= 'Z')
                        {
                            GOTO.pop_back();
                            GOTO.push_back({ dfa->number,iter->str[iter->tag], count });
                        }
                        else
                        {
                            ACTION.pop_back();
                            ACTION.push_back({ dfa->number,iter->str[iter->tag],'s',count });
                        }
                    }
                    else
                        DFA.push_back(C);
                }
                else  // Already completed
                {
                    int cc = 0, tt;
                    for (tt = 0; tt < 11; tt++)
                    {
                        if (iter->str == G[tt])
                            break;
                    }
                    for (list<char>::iterator c = Vn.begin(); c != Vn.end(); c++, cc++)
                        if (*c == iter->str[0])
                            break;
                    for (list<char>::iterator c = Follow[cc].begin(); c != Follow[cc].end(); c++)
                    {
                        ACTION.push_back({ dfa->number,*c,'r',tt });  // Corresponding to the jth production
                        for (int ss = 3; ss < G[tt].length(); ss++)  // Find the production corresponding to the four-element
                            if (G[tt][ss] == '+' || G[tt][ss] == '-' || G[tt][ss] == '*' || G[tt][ss] == '/')
                            {
                                sys.push_back(tt);
                            }
                    }
                }
            }
    }
    num = 0;
    for (dfa = DFA.begin(); dfa != DFA.end(); dfa++)
    {
        cout << "State " << num++ << ":" << endl;
        for (list<sentence>::iterator iii = dfa->l.begin(); iii != dfa->l.end(); iii++)
        {
            cout << "    ";
            print(*iii);
        }
    }
    cout << endl;
    int kkk = 0;
    for (list<go>::iterator g = GOTO.begin(); g != GOTO.end(); g++)
    {
        cout << "GOTO(" << g->I << ", " << g->Vn << ") = " << g->next_I<<"       ";
        kkk++;
        if (kkk % 4 == 0) {
            cout << endl;
        }
    }
    cout << endl << endl;
    kkk = 0;
    for (list<act>::iterator a = ACTION.begin(); a != ACTION.end(); a++)
    {
        cout << "ACTION(" << a->I << ", " << a->Vt << ") = " << a->tag << a->action << "       ";
        kkk++;
        if (kkk % 4 == 0) {
            cout << endl;
        }
    }
    cout << endl;
}

int main()
{
    readfile();
    scan();
    table();
    SLR();
    cout << "---------------------21281157 hxd------------------------" << endl;
    return 0;
}

测试 

Test1

示例如下:

DFA状态集:

SLR分析表:

SLR文法分析和四元式构造过程:

  • 12
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天之交子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值