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

news2025/5/21 3:40:30

一、程序功能描述

本程序由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

#include<iostream>
#include<cstring>
#include<string>
#include<vector>
#include<map>
using namespace std;
const int N=1024;
string testFileName = "test4.txt";
string info[3] = {"---------------------------", "SLR(1)分析", "---------------------------"};
map<char, int> deCode =
{
    {'i', 0},
    {'=', 1},
    {'+', 2},
    {'-', 3},
    {'*', 4},
    {'/', 5},
    {'(', 6},
    {')', 7},
    {'#', 8},
    {'S', 9},
    {'E', 10},
    {'T', 11},
    {'F', 12},
    {'V', 13},
};
vector<vector<int>>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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1434480.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

进程和线程的区别详解

&#x1f3a5; 个人主页&#xff1a;Dikz12&#x1f4d5;格言&#xff1a;那些在暗处执拗生长的花&#xff0c;终有一日会馥郁传香欢迎大家&#x1f44d;点赞✍评论⭐收藏 目录 进程 进程在系统中是如何管理的 进一步认识PCB 线程 能否一直增加线程数目来提高效率 进程和线程…

【240126】上海大学—调剂信息

上海大学 学校层级&#xff1a;211 调剂专业&#xff1a;081000 信息与通信工程 发布时间&#xff1a;2024.1.26 发布来源&#xff1a;网络发布 调剂要求&#xff1a;要求考数一英一且初试成绩在320分以上 来源说明 1、官方发布&#xff1a;学校官网、研招网 2、网络发布…

EOF和0区别

题目描述 KiKi学习了循环&#xff0c;BoBo老师给他出了一系列打印图案的练习&#xff0c;该任务是打印用“*”组成的X形图案。 输入描述&#xff1a; 多组输入&#xff0c;一个整数&#xff08;2~20&#xff09;&#xff0c;表示输出的行数&#xff0c;也表示组成“X”的反斜…

Architecture Lab:Part C【流水线通用原理/Y86-64的流水线实现/实现IIADDQ指令】

目录 任务描述 知识回顾 流水线通用原理 Y86-64流水线实现&#xff08;PIPE-与PIPE&#xff09; 开始实验 IIADDQ指令的添加 优化 ncopy.ys 仅用第四章知识&#xff0c;CEP11.55 8x1展开&#xff0c;CPE9.35 8x1展开2x1展开消除气泡&#xff0c;CPE8.10 流水线化通过…

在VM虚拟机上搭建MariaDB数据库服务器

例题&#xff1a;搭建MariaDB数据库服务器&#xff0c;并实现主主复制。 1.在二台服务器中分别MariaDB安装。 2.在二台服务器中分别配置my.cnf文件&#xff0c;开启log_bin。 3.在二台服务器中分别创建专用于数据库同步的用户replication_user&#xff0c;并授权SLAVE。&#x…

【DDD】学习笔记-数据分析模型

在 Eric Evans 提出领域驱动设计之前&#xff0c;对企业系统的分析设计多数采用数据模型驱动设计。如前所述&#xff0c;这种数据模型驱动设计就是站在数据的建模视角&#xff0c;逐步开展分析、设计与实现的建模过程。通过对数据的正确建模&#xff0c;设计人员就可以根据模型…

【INTEL(ALTERA)】为什么在编译 HDMI 英特尔® FPGA IP设计示例 VHDL 变体时看到错误 (13879)?

说明 由于英特尔 Quartus Prime Pro Edition 软件版本 23.2 存在一个问题&#xff0c;您在编译 HDMI 英特尔 FPGA IP设计示例的 VHDL 变体时可能会看到以下错误&#xff1a; 错误 &#xff08;13879&#xff09;&#xff1a; VHDL 绑定指示 hdmi_rx_ram_1port_intel_mce_2010…

Java设计模式大全:23种常见的设计模式详解(一)

本系列文章简介&#xff1a; 设计模式是在软件开发过程中&#xff0c;经过实践和总结得到的一套解决特定问题的可复用的模板。它是一种在特定情境中经过验证的经验和技巧的集合&#xff0c;可以帮助开发人员设计出高效、可维护、可扩展和可复用的软件系统。设计模式提供了一种在…

缩略图保持加密(TPE)论文

文献: R.Zhao,Y.Zhang,Y.Nan,W.Wen,X.Chai,andR. Lan, “Primitively visually meaningful image encryption: A new paradigm,” Inf. Sci. (Ny), Vol. 613, pp. 628–48, 2022. DOI: 10.1016/j.ins.2022.08.027. (1) 第1行:原始图像 第2行:加密图像 加密的目标: 原始…

synchronized内部工作原理

作者简介&#xff1a; zoro-1&#xff0c;目前大二&#xff0c;正在学习Java&#xff0c;数据结构&#xff0c;javaee等 作者主页&#xff1a; zoro-1的主页 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01;&#x1f496;&#x1f496; synchronized内部工作原理 syn…

运维监控之MySQL死锁查询及监控

死锁是指两个或两个以上的事务在执行过程中&#xff0c;因争夺资源而造成的一种相互等待的现象&#xff0c;若无外力作用&#xff0c;它们都将无法推进下去&#xff0c;此时称系统处于死锁状态或系统产生了死锁。 为了监控MySQL的死锁情况&#xff0c;可以使用以下方法&#xf…

【论文解读】Point Transformer

Point Tranformer 摘要引言方法实验结论 摘要 自注意网络已经彻底改变了自然语言处理&#xff0c;并在图像分析任务&#xff08;如图像分类和对象检测&#xff09;方面取得了令人印象深刻的进展。受这一成功的启发&#xff0c;我们研究了自注意网络在三维点云处理中的应用。我…

流浪动物救助|基于Springboot的流浪动物救助平台设计与实现(源码+数据库+文档)

流浪动物救助平台目录 目录 基于Springboot的流浪动物救助平台设计与实现 一、前言 二、系统功能设计 三、系统实现 1、用户信息管理 2、动物信息管理 3、商品评论管理 4、公告信息管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设…

常用Hallmark及KEGG、GO基因查询

文献&#xff1a;The Molecular Signatures Database (MSigDB) hallmark gene set collection - PMC (nih.gov) GSEA | MSigDB | Browse Human Gene Sets (gsea-msigdb.org)通过msigdb数据库可以查看各个Hallmark、KEGG、GO具体包含的基因细节。 Hallmark nameProcess categor…

python中的三种程序控制结构-顺序结构、分支结构、循环结构

程序控制结构 一、顺序结构二、分支结构三、循环结构条件循环-while遍历循环-for循环控制-break、continue 一、顺序结构 顺序结构是指程序在执行时按照代码的顺序逐一执行&#xff0c;每一行代码只执行一次&#xff0c;然后依次执行下一行代码。顺序结构是程序最基本的执行方式…

springboot果蔬配送商城

技术架构&#xff1a; java mysql bootstrap jquery mybatis springboot 有需要该项目的小伙伴可以私信我你的Q。 功能介绍&#xff1a; 系统基于Java技术进行开发&#xff0c;后台数据库使用MySQL&#xff0c;在Windows环境下使用idea开发工具进行开发&#xff0c;主…

异地办公必不可缺的远程控制软件,原理到底是什么?

目录 引言远程桌面连接软件的作用与重要性 基本概念与架构客户端-服务器模型网络通信协议 核心技术组件图形界面捕获与传输输入转发会话管理 性能优化策略带宽优化延迟优化 引言 远程桌面连接软件的作用与重要性 在当今这个高度数字化和网络化的时代&#xff0c;远程桌面连接软…

基于springboot智慧养老平台源码和论文

首先,论文一开始便是清楚的论述了系统的研究内容。其次,剖析系统需求分析,弄明白“做什么”,分析包括业务分析和业务流程的分析以及用例分析,更进一步明确系统的需求。然后在明白了系统的需求基础上需要进一步地设计系统,主要包罗软件架构模式、整体功能模块、数据库设计。本项…

Yarn常见问题处理

任务出现container OOM异常导致作业失败 原因 Container内存不足或者作业数据倾斜 解决方案 检查Container相关参数,判断是否设置过小(低于4GB)。如果Container小于4GB,优先考虑调大当前作业container大小,如果是Tez任务,还需要同步调整以下参数 # tez container size…

教你一招如何半小时把C语言的 scanf printf sscanf sprintf fscanf fprintf wscanf wprintf 玩出花来

本篇会加入个人的所谓‘鱼式疯言’ ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 我会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人能…