编译原理实验一:源程序的预处理及词法分析程序的设计与实现(python)

news2024/11/30 10:40:23

实验目的

设计并实现一个包含预处理功能的词法分析程序,加深对编译中词法分析过程的理解。

实验要求

1、实现预处理功能

源程序中可能包含有对程序执行无意义的符号,要求将其剔除。
首先编制一个源程序的输入过程,从键盘、文件或文本框输入若干行语句,依次存入输入缓冲区(字符型数据);然后编制一个预处理子程序,去掉输入串中的回车符、换行符和跳格符等编辑性文字;把多个空白符合并为一个;去掉注释。

2、实现词法分析功能

输入:所给文法的源程序字符串。
输出:二元组(syn,token或sum)构成的序列。其中,
syn为单词种别码。
Token为存放的单词自身字符串。
Sum为整型常量。
具体实现时,可以将单词的二元组用结构进行处理。

3、待分析的C语言子集的词法(可以自行扩充,也可以按照C语言的词法定义)

1)关键字
main if then while do static int double struct break else long switch case typedef char return const float short continue for void default sizeof do
所有的关键字都是小写。
2)运算符和界符
+ - * / : := < <> <= > >= = ; ( ) #
3)其他标记ID和NUM
通过以下正规式定义其他标记:
ID→letter(letter|digit)*
NUM→digit digit*
letter→a|…|z|A|…|Z
digit→0|…|9…
4)空格由空白、制表符和换行符组成
空格一般用来分隔ID、NUM、专用符号和关键字,词法分析阶段通常被忽略。

4、各种单词符号对应的种别码

题目提供的种别码有部分错误,实际要求是可自行定义,这里提供一份参考:

keyword = {'main':1,'if':2,'then':3,'while':4,'do':5,
           'static':6,'int':7,'double':8,'struct':9,
           'break':10,'else':11,'long':12,'switch':13,
           'case':14,'typedef':15,'char':16,'return':17,
           'const':18,'float':19,'short':20,'continue':21,
           'for':22,'void':23,'ID':25,'NUM':26,'default':39,
           'sizeof':24,'stdio.h':40,'include':44,'scanf':48,'printf':49}
operator = {'+':27,'-':28,'*':29,'/':30,':':31,':=':32, '<':33,
            '<>':34,'<=':35,'>':36,'>=':37,'=':38,';':41,'(':42,
            ')':43,'#':0,'{':46,'}':47}

5、 词法分析程序的主要算法思想

算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到的单词符号的第一个字符的种类,拼出相应的单词符号。

代码:

import re
def pre(file):
    data = file.read()
    out =[]
    data = re.sub(re.compile('/\*{1,2}[\s\S]*?\*/'),"",data)
    data = re.sub(re.compile('//[\s\S]*?\n'), "", data)
    data = data.split("\n")
    for i in data:
        i = i.strip(' ').replace('\t', '')
        i = ' '.join(str(i).split())
        if(i!=''):
            out.append(i)
    return out
keyword = {'main':1,'if':2,'then':3,'while':4,'do':5,
           'static':6,'int':7,'double':8,'struct':9,
           'break':10,'else':11,'long':12,'switch':13,
           'case':14,'typedef':15,'char':16,'return':17,
           'const':18,'float':19,'short':20,'continue':21,
           'for':22,'void':23,'ID':25,'NUM':26,'default':39,
           'sizeof':24,'stdio.h':40,'include':44,'scanf':48,'printf':49}
operator = {'+':27,'-':28,'*':29,'/':30,':':31,':=':32, '<':33,
            '<>':34,'<=':35,'>':36,'>=':37,'=':38,';':41,'(':42,
            ')':43,'#':0,'{':46,'}':47}
with open('test.txt', 'r') as file:
    data = pre(file)
    #print(data)
    for i in range(len(data)):
        pattern1 = re.compile('[a-zA-Z.0-9]+')
        line = re.findall(pattern1,data[i])
        for j in line:
            if j in keyword:
                print(j+' -> '+str(keyword[j]))
            elif str(j).isdigit():
                print("'"+str(j)+"' -> 26")
            else:
                j = str(j).strip('.')
                print("'"+j+"' -> 25")
        line2 = re.sub(pattern1," ",data[i])
        line2=line2.split(" ")
        for j in line2:
            if j in operator:
                print(j+' -> '+str(operator[j]))

测试文本:

#include<stdio.h>
struct student
{
    int id;
    long int counts;
    /*

asfagsaf

    */
    /* data */
};
student stu[2000000];
int main(){
    for(long int i=0;i<2000000;i++){
        stu[i].id=i;
        stu[i].counts=0;
    }
    long int n,m;
    int a;
    scanf("%d",&n);
    for(long int i=0;i<n;i++){
        scanf("%ld",&a);
        stu[a].counts++;
    }
    scanf("%ld",&m);
    for(long int i=0;i<m;i++){
        scanf("%d",&a);
        if(stu[a].counts==0){
            printf("NO\n");
        }
        else{
            printf("YES\n");
        }
    }
    return 0;
}

输出:

include -> 44
stdio.h -> 40
# -> 0
< -> 33
> -> 36
struct -> 9
'student' -> 25
{ -> 46
int -> 7
'id' -> 25
; -> 41
long -> 12
int -> 7
'counts' -> 25
; -> 41
'student' -> 25
'stu' -> 25
'2000000' -> 26
int -> 7
main -> 1
for -> 22
long -> 12
int -> 7
'i' -> 25
'0' -> 26
'i' -> 25
'2000000' -> 26
'i' -> 25
( -> 42
= -> 38
; -> 41
< -> 33
; -> 41
'stu' -> 25
'i' -> 25
'id' -> 25
'i' -> 25
= -> 38
; -> 41
'stu' -> 25
'i' -> 25
'counts' -> 25
'0' -> 26
= -> 38
; -> 41
} -> 47
long -> 12
int -> 7
'n' -> 25
'm' -> 25
; -> 41
int -> 7
'a' -> 25
; -> 41
scanf -> 48
'd' -> 25
'n' -> 25
for -> 22
long -> 12
int -> 7
'i' -> 25
'0' -> 26
'i' -> 25
'n' -> 25
'i' -> 25
( -> 42
= -> 38
; -> 41
< -> 33
; -> 41
scanf -> 48
'ld' -> 25
'a' -> 25
'stu' -> 25
'a' -> 25
'counts' -> 25
} -> 47
scanf -> 48
'ld' -> 25
'm' -> 25
for -> 22
long -> 12
int -> 7
'i' -> 25
'0' -> 26
'i' -> 25
'm' -> 25
'i' -> 25
( -> 42
= -> 38
; -> 41
< -> 33
; -> 41
scanf -> 48
'd' -> 25
'a' -> 25
if -> 2
'stu' -> 25
'a' -> 25
'counts' -> 25
'0' -> 26
( -> 42
printf -> 49
'NO' -> 25
'n' -> 25
} -> 47
else -> 11
{ -> 46
printf -> 49
'YES' -> 25
'n' -> 25
} -> 47
} -> 47
return -> 17
'0' -> 26
; -> 41
} -> 47

在这里插入图片描述

注意要点:

  1. 预处理文件后,从数据中提取单词和符号的过程使用了正则表达式,为[a-zA-Z.0-9]+,这里会出现一个小bug,算是逻辑漏洞,就是面向比如stu[i].counts=0;这样的语句,并没有根据.把语句前后分开,而是把.合并到了.counts里。解决方法是在输出的时候把.去掉。
  2. 预处理文件用到的正则表达式:/\*{1,2}[\s\S]*?\*/,目的是去除多行注释,//[\s\S]*?\n目的是去除单行注释。

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

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

相关文章

[附源码]java毕业设计校园拓展活动管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

论文阅读之Dynamic Routing Between Capsules(2017)

文章目录前言capsule network参考前言 capsule network 可以简单理解为将神经网络的标量计算&#xff0c;赋予了方向&#xff0c;变换成了向量进行计算。 标量只有大小之分。 向量不仅有大小&#xff0c;还有方向之分。 应该可以略微感受到这种思路的魔力了。 capsule 主要是…

IB历史备考,如何拿高分?

邻近期末考&#xff0c;大伙儿是不是十分焦虑不安呢&#xff1f;大家的老师经常发觉学生们本来知识要点都把握得挺不错的&#xff0c;但每到考試便是拿不上满意的考试成绩&#xff0c;让人十分郁闷&#xff01;因此应对那样的难点&#xff0c;大家的IB历史时间评委为大伙儿筹备…

行业分析| 智慧消防对讲

消防工程关系国计民生&#xff0c;关系到每个公民的人身和财产安全&#xff0c;在每个场所的建设中&#xff0c;消防工程建设是必不可少的一个板块&#xff0c;包括消防应急通道建设和应急设备建设两个方面。其中消防系统设备建设主要分为九大系统的建设&#xff1a;消防水系统…

VectorCAST测试工具环境搭建

**目的&#xff1a;**本文提供VectorCAST使用的实际操作方法&#xff0c;以便项目可以很好的使用VectorCAST工具。 适用范围&#xff1a;VectorCAST是一个专门针对嵌入式软件的C/C代码进行单元测试的工具&#xff0c;它可以自动生成测试用例、评估测试结果并生成测试报告。 **工…

十年来高薪专业变成了它——信息安全

“什么专业好就业&#xff1f;” “什么专业以后赚的钱多&#xff1f;” 确实&#xff0c;专业对应的行业薪资各有不同&#xff0c;选对了专业赢在起跑线也不是没有可能&#xff01; 麦可思机构分析了近十年大学生就业数据情况&#xff0c;发现从2011年到2020年的大学毕业生高…

Windows简单安装redis

1.去git下载 或者去搜点资源&#xff0c;windows下载是压缩包&#xff0c;找个目录解压进去。 Github下载地址&#xff1a;https://github.com/MicrosoftArchive/redis/releases 2.打开cmd 尝试启动 比如我放在d盘soft下面&#xff0c;windows你直接打开cmd&#xff0c;输入d…

Baklib知识分享|文档生命周期:确保您的文档产出效率

一个多世纪以来&#xff0c;文档一直是任何产品或服务的支柱。它是用户在使用您的产品、应用程序、网站或其他软件服务时所引用的内容。但在现代&#xff0c;随着大多数帮助或支持文档从传统形式转移到数字形式&#xff0c;对效率的需求比以往任何时候都更加明显。此外&#xf…

[附源码]SSM计算机毕业设计基于javaweb电影购票系统JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【Shell 脚本速成】01、编程语言与 Shell 脚本介绍

目录 一、编程语言介绍 二、shell介绍 1、shell介绍 2、bash shell基本特性 2.1 命令和文件自动补全 2.2 常见的快捷键 3、shell脚本介绍 准确来说&#xff1a; 3.1 案例演示 3.2 什么时候用到脚本&#xff1f; 4、shell脚本语法 4.1 shell脚本组成 4.2 脚本文件命…

Spring事务配置(案例:转账业务追加日志,事务传播行为)

目录 Spring事务配置 案例 事务传播行为 代码实现&#xff1a; 1.文件大致格式&#xff1a; 2.ServiceAdvise&#xff08;AOP功能包&#xff09; 3.JdbcConfig&#xff08;jdbc配置文件&#xff0c;包含了事务管理器&#xff09; 4.MybatisConfig&#xff08;mybatis配置…

Unity技术手册-UGUI零基础详细教程-ScrollBar和ScrollView

往期文章分享点击跳转>《导航贴》- Unity手册&#xff0c;系统实战学习点击跳转>《导航贴》- Android手册&#xff0c;重温移动开发 本文约8千字&#xff0c;新手阅读需要20分钟&#xff0c;复习需要12分钟 【收藏随时查阅不再迷路】 &#x1f449;关于作者 众所周知&…

2022/11/22 [easyx]关于字符和一些背景

#include<stdio.h> #include<graphics.h> //包含图形库头文件 int main() {//创建一个窗口//(show console 显示控制台)&#xff0c;640&#xff0c;480为窗口大小*initgraph(640,480,SHOWCONSOLE);//showconsole可以换成NOCLOSE:程序不能关闭// NOMINIMIZE不能最小…

洛谷 T292115 [传智杯 #5 练习赛] 树的变迁#并查集+逆向思维

一道质量挺高的题&#xff08;个人感觉&#xff09;&#xff0c;题目说了每次要删除一条边&#xff0c;分成两棵树&#xff0c;那么很容易想到用并查集去维护。但是问题在于如果要将原来那棵树分成新的两个树必然不能使用路径压缩&#xff0c;如图所示 如果使用了路径压缩那就…

数据安全法vs国家标准,40+标准助力数据安全保驾护航~(附整理文档及pdf下载)

2021年9月1日&#xff0c;《中华人民共和国数据安全法》生效施行&#xff0c;如何助力数据安全法的贯彻落实&#xff0c;做到数据合法合规的使用需要建设一系列的数据安全标准体系。也就是说&#xff0c;有了数据安全相关标准&#xff0c;就是有了如何践行数据安全法落地实施的…

Oracle LiveLabs实验:Manage and Monitor Autonomous Database

概述 本研讨会中的实验将引导您完成开始使用 Oracle 自治数据库的所有步骤。 首先&#xff0c;您将创建一个 Oracle 自治数据库实例。 然后&#xff0c;您将练习使用自治数据库工具和 API 从不同位置以不同格式加载数据的几种方法。 您将使用 SQL 分析数据并使用 Oracle Analy…

JavaScript构造函数和原型:继承

ES6之前并没有给我们提供 extends 继承。我们可以通过构造函数原型对象模拟实现继承&#xff0c;被称为组合继承。 call() 调用这个函数, 并且修改函数运行时的 this 指向 fun.call(thisArg, arg1, arg2, ...) thisArg &#xff1a;当前调用函数 this 的指向对象 arg1&am…

weapp源码反编译步骤

一、下载解密工具 解密工具下载&#xff1a;地址 二、在微信电脑版&#xff0c;打开目标小程序,在如下的目录中可以找到小程序的目录 这是我自自定义的缓存目录&#xff0c;找不到自己缓存目录在哪儿的&#xff0c;手机给自己的文件助手发个文档&#xff0c;打开所在目录&…

高标准企业级安全性,华为云会议为线上沟通保驾护航

如今&#xff0c;全球企业正在以办公室为主的工作环境向混合型工作环境转变&#xff0c;线上会议逐渐成为企业的刚需。事实上通过云会议的形式进行的远程沟通协作&#xff0c;如线上招聘、培训、课堂等也已非常普及&#xff0c;不过随之而来的网络安全风险也愈发引起各界关注。…

Linux有多重要?冲30万年薪Linux学习入门指南

与 Windows 相比&#xff0c;Linux 相对来说更加安全稳定&#xff0c;而且Linux可以定制化或者选择不同的发行版&#xff0c;下面借鉴网上的一张图片展示下 Linux 与 Windows 的区别。 ​ ​简单说就是linux 性能更好&#xff0c;直接通过命令行底层运行 1.廉价&#xff08;免费…