编译原理本科课程 专题5 基于 SLR(1)分析的语义分析及中间代码生成程序设计

一、程序功能描述

本程序由C/C++编写,实现了赋值语句语法制导生成四元式,并完成了语法分析和语义分析过程。

以专题 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

二、主要数据结构描述

        关于本程序的数据结构,首先用map存储了非终结符及终结符的编码映射,而后用string存储文件读入和写入的信息等,最重要的是利用vector二维数组实现了SLR分析表,用于存储分析动作;此外定义了四元组和栈的相应结构体。由于本人习惯,字符串处理总体上采用了C风格和C++方式并存的写法。

、程序结构描述

        除main函数外,本程序共定义了4个函数:

        getIndex用于返回输入字符在deCode 映射中的对应索引,若非法字符则返回-1。

dispQuad用于显示解析过程中生成的四元组,并展示输入表达式的中间代码表示;SLR_display则显示分析栈的当前状态、剩余的输入字符串以及解析过程中的当前动作。这两个函数都用于实现编译前端的可视化。

        在SLR_analysis真正实现了SLR(1)文法的分析过程,使用栈 (anstk) 跟踪解析过程中的状态、符号和输入字符串位置,并根据 SLR 解析表执行移入、规约和接受等动作,最后在解析过程中生成四元组,表示中间代码。

四、程序测试

        测试案例展示如下:

        测试用例1:a=((b)+c*d)/f+e*g

编译原理本科课程 专题5 基于 SLR(1)分析的语义分析及中间代码生成程序设计_第1张图片

编译原理本科课程 专题5 基于 SLR(1)分析的语义分析及中间代码生成程序设计_第2张图片

#include
#include
#include
#include
#include
using namespace std;
const int N=1024;
string testFileName = "test4.txt";
string info[3] = {"---------------------------", "SLR(1)分析", "---------------------------"};
map deCode =
{
    {'i', 0},
    {'=', 1},
    {'+', 2},
    {'-', 3},
    {'*', 4},
    {'/', 5},
    {'(', 6},
    {')', 7},
    {'#', 8},
    {'S', 9},
    {'E', 10},
    {'T', 11},
    {'F', 12},
    {'V', 13},
};
vector>table = 
                    {{ 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2},
                    { 0, 0, 0, 0, 0, 0, 0, 0,-11,0,0, 0, 0, 0},
                    { 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                    {-10,-10,-10,-10,-10,-10,-10,-10,-10, 0, 0, 0, 0, 0},
                    { 9, 0, 0, 0, 0, 0, 8, 0, 0, 0, 5, 6, 7, 0},
                    {-1,-1,10,11,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0},
                    {-4,-4,-4,-4,12,13,-4,-4,-4, 0, 0, 0, 0, 0},
                    {-7,-7,-7,-7,-7,-7,-7,-7,-7, 0, 0, 0, 0, 0},
                    { 9, 0, 0, 0, 0, 0, 8, 0, 0, 0,14, 6, 7, 0},
                    {-9,-9,-9,-9,-9,-9,-9,-9,-9, 0, 0, 0, 0, 0},
                    { 9, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0,15, 7, 0},
                    { 9, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0,16, 7, 0},
                    { 9, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0,17, 0},
                    { 9, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0,18, 0},
                    { 0, 0,10,11, 0, 0, 0,19, 0, 0, 0, 0, 0, 0},
                    {-2,-2,-2,-2,12,13,-2,-2,-2, 0, 0, 0, 0, 0},
                    {-3,-3,-3,-3,12,13,-3,-3,-3, 0, 0, 0, 0, 0},
                    {-5,-5,-5,-5,-5,-5,-5,-5,-5, 0, 0, 0, 0, 0},
                    {-6,-6,-6,-6,-6,-6,-6,-6,-6, 0, 0, 0, 0, 0},
                    {-8,-8,-8,-8,-8,-8,-8,-8,-8, 0, 0, 0, 0, 0}};

struct quadruple {
    char op[N];
    char arg1[N];
    char arg2[N];
    char res[N];
};
struct quadruple quad[N];   
int topOfQuad = 0;          

struct Stack {
    char s[N];
    int i[N];
    int space[N];
    int top;
}; 
 

int getIndex(char ch);
int SLR_analysis(char *str, struct Stack *anstk);
void SLR_display(char *str, struct Stack *anstk, int cur);
void dispQuad();

int main() {
    for (int i = 0; i < 3; i++)
        cout << info[i] << endl;


    FILE *fp = fopen(testFileName.c_str(), "r");
    char buf[N] = "";
    char input[N] = "";
    fgets(buf, N, fp);
    int j = 0;
    for(int k = 0; k < strlen(buf); k++) { 
        if(buf[k] == '1' && buf[k+1] == ',') {
            k += 3;
            while(1) {
                if(buf[k] == ')' && buf[k+1] == ' ')
                    break;
                input[j++] = buf[k++];
            }
            continue;
        }
        if(buf[k] == ',' && buf[k+1] == ' ') {
            k += 2;
            while(1) {
                if(buf[k] == ')' && buf[k+1] == ' ')
                    break;
                input[j++] = buf[k++];
            }
        }
    }
    printf("输入表达式为: %s\n", input); 
    input[j] = '#'; 
    fclose(fp);
    struct Stack *anstk;
    anstk = (struct Stack *)malloc(sizeof(struct Stack));
    anstk->s[0] = '#';
    anstk->i[0] = 0;
    anstk->space[0] = -1;
    anstk->top = 0; 
    if(!SLR_analysis(input, anstk)) {
        cout << "语法错误!" << endl;
    }
    else {
        cout << "分析成功!" << endl;
        dispQuad(); 
    }
    return 0;
}

int getIndex(char ch) {
    if (deCode.find(ch) != deCode.end())
        return deCode[ch];
    else
        return -1;
}
 
void SLR_display(char *str, struct Stack *anstk, int cur) { 
    for(int i = 0; i <= anstk->top; i++) {
        cout << anstk->s[i];
        
    }

    for(int i = 0; i < 3-(anstk->top+1)/8; i++) {
        cout<< "\t";
    }
    for(int i = cur; i < strlen(str); i++) {
        cout << str[i];
    }
    printf("\n");
}
 
void dispQuad() { 
    printf("四元式:\n");
    for(int i = 1; i <= topOfQuad; i++) {
        printf("(%s, %s, %s, %s)\n", quad[i].op, quad[i].arg1, quad[i].arg2, quad[i].res);
    }
}

int SLR_analysis(char *str, struct Stack *anstk) { 
    topOfQuad = 0;
    int i = 0;
    int next;
    printf("分析栈:\t\t\t字符串:\t\t\t动作:\n");
    while(i < strlen(str)) {
        if(anstk->top < 0) return 0; 
        int y; 
        if (str[i] >= 'a' && str[i] <= 'z') y = getIndex('i'); 
        else y = getIndex(str[i]);
        if(y == -1 || table[anstk->i[anstk->top]][y] == 0) { 
            return 0;
        }
        if(table[anstk->i[anstk->top]][y] > 0) { 
            next = table[anstk->i[anstk->top]][y];
            anstk->top++;
            anstk->s[anstk->top] = str[i];
            anstk->i[anstk->top] = next;
            anstk->space[anstk->top] = i;
            i++;
            SLR_display(str, anstk, i);
        }
        else if(table[anstk->i[anstk->top]][y] < 0) { 
            int tmp = -table[anstk->i[anstk->top]][y]; 
            if(tmp == 4 || tmp == 7 || tmp == 9 || tmp == 10) {
                anstk->top--; 
            }
            else if(tmp == 2 || tmp == 3 || tmp == 5 || tmp == 6){
                
                topOfQuad++;
                if(tmp == 2) strcpy(quad[topOfQuad].op, "+");
                else if(tmp == 3) strcpy(quad[topOfQuad].op, "-");
                else if(tmp == 5) strcpy(quad[topOfQuad].op, "*");
                else strcpy(quad[topOfQuad].op, "/");
                if(anstk->space[anstk->top - 2] < 0) sprintf(quad[topOfQuad].arg1, "t%d", -anstk->space[anstk->top - 2]);
                else {
                    char arg1[2] = {str[anstk->space[anstk->top - 2]], '\0'};
                    strcpy(quad[topOfQuad].arg1, arg1);
                }
                if(anstk->space[anstk->top] < 0) sprintf(quad[topOfQuad].arg2, "t%d", -anstk->space[anstk->top]);
                else {
                    char arg2[2] = {str[anstk->space[anstk->top]], '\0'};
                    strcpy(quad[topOfQuad].arg2, arg2);
                }
                cout << "\t\t\t\t\t\t";
                printf("t%d = %s %s %s\n", topOfQuad, quad[topOfQuad].arg1, quad[topOfQuad].op, quad[topOfQuad].arg2); 
                sprintf(quad[topOfQuad].res, "t%d", topOfQuad);
                anstk->top -= 3; 
                anstk->space[anstk->top + 1] = -topOfQuad; 
            }
            else if(tmp == 8) {
                anstk->top -= 3; 
                anstk->space[anstk->top + 1] = anstk->space[anstk->top + 2]; 
            }
            else if(tmp == 1){
                topOfQuad++;
                strcpy(quad[topOfQuad].op, "=");
                if(anstk->space[anstk->top] < 0) sprintf(quad[topOfQuad].arg1, "t%d", abs(anstk->space[anstk->top]));
                else {
                    char arg1[2] = {str[anstk->space[anstk->top]], '\0'};
                    strcpy(quad[topOfQuad].arg1, arg1);
                }
                sprintf(quad[topOfQuad].arg2, " ");
                char res[2] = {str[anstk->space[anstk->top - 2]], '\0'};
                strcpy(quad[topOfQuad].res, res);
                cout << "\t\t\t\t\t\t";
                printf("%s = %s\n", quad[topOfQuad].res, quad[topOfQuad].arg1);
                anstk->top -= 3; 
            }
            else anstk->top -= 3;
            if(tmp == 1) { 
                y = getIndex('S');
                next = table[anstk->i[anstk->top]][y]; 
                anstk->top++;
                anstk->s[anstk->top] = 'S';
                anstk->i[anstk->top] = next; 
            }
            else if(tmp == 2 || tmp ==3 || tmp == 4) {
                y = getIndex('E');
                next = table[anstk->i[anstk->top]][y]; 
                anstk->top++;
                anstk->s[anstk->top] = 'E';
                anstk->i[anstk->top] = next;
            }
            else if(tmp == 5 || tmp == 6 || tmp == 7) {
                y = getIndex('T');
                next = table[anstk->i[anstk->top]][y];
                anstk->top++;
                anstk->s[anstk->top] = 'T';
                anstk->i[anstk->top] = next;
            }
            else if(tmp == 8 || tmp == 9) {
                y = getIndex('F');
                next = table[anstk->i[anstk->top]][y];
                anstk->top++;
                anstk->s[anstk->top] = 'F';
                anstk->i[anstk->top] = next;
            }
            else if(tmp == 10) {
                y = getIndex('V');
                next = table[anstk->i[anstk->top]][y];
                anstk->top++;
                anstk->s[anstk->top] = 'V';
                anstk->i[anstk->top] = next;
            }
            else if(tmp == 11) {
                return 1; 
            }
            SLR_display(str, anstk, i);
        }
    }
    return 0;
}

你可能感兴趣的:(编译原理,c++)