python 算符优先分析法的设计实现 编译原理

news2024/10/7 4:32:45

本文内容:

1、给出文法如下:
G[E]

E->T|E+T;

T->F|T*F;

F->i|(E);
可以构造算符优先表如下:

+*()i
+><<><
*>><><
(<<<=<
)>>>
i>>>


2、计算机中表示上述优先关系,优先关系的机内存放方式有两种1)直接存放,2)为优先关系建立优先函数,这里由学生自己选择一种方式;
3、给出算符优先分析算法如下:

k:=1;S[k]:='#';
REPEAT
        把下一个输入符号读进a中;
        IF S[k]属于Vt THEN j:=k ELSE j:=k-1;

        WHILE S[j]>a DO
        BEGIN
                REPEAT

                        Q:=S[j];
                        IF S[j-1]属于Vt THEN j:=j-1 ELSE j:=j-2

                UNTIL s[j]<Q
                把S[j+1]...S[k]归约为某个N;

                k:=j+1;
                S[k]:=N;
        END OF WHILE;
        IF S[j]<a OR S[j]=a THEN

        BEGIN
                k:=k+1;

                S[k]:=a

        END
        ELSE ERROR

UNTIL a=‘#'

样例:

 代码如下:

# 输出结果
def output(str, a, b, type):
    global program
    program.append([type, str[a:b + 1]])


# 判断字符串一部分是否属于关键字
# 是返回1不是返回2
def iskeywords(str, a, b):
    # 关键字
    keywords = {"if", "int", "for", "while", "do", "return", "break", "continue"}
    s = str[a:a + b + 1]  # 拷贝字符
    if s in keywords:  # 判断是否存在,存在返回1,否则返回2
        return 1
    else:
        return 2


# 判断字符是否属于运算符或分隔符的一部分。
# 不是返回0,是返回1,是且后面能跟=号返回2
def belong_to(str, type):
    if type == 4:  # 选择运算符
        library = "+-*/=><!"  # 运算符
    else:  # 选择分隔符
        library = ",;{}()"  # 分隔符
    if str in library:  # 存在
        # 是可能后面跟=号的几个符号
        if type == 4 and library.index(str) >= 4:
            return 2
        else:
            return 1
    return 0


# 递归的词法分析函数,读入一行str字符串,初始位置 n = 0
# 分离+判断,打印输出类型
# 由之前的c语言版本改写而成
def scan(str, n):
    # 7 种类型(最后输出1 - 5)
    # -1
    # 0: 初始
    # 1: 关键字, 在keywords中
    # 2: 标识符
    # 3: 常数(无符号整型)
    # 4: 运算符和界符:+ - * / = > < >= <= !=
    # 5: 分隔符:, ; {}()
    i = n
    type = 0
    while i < len(str):
        if type == 0:  # 初始态
            if str[i] == ' ':  # 空格跳过
                n += 1
                i += 1
                continue
            elif str[i] == '\0' or str[i] == '\n':  # 是结束
                return
            elif ('a' <= str[i] <= 'z') or ('A' <= str[i] <= 'Z'):
                type = 1  # 是字母,
            elif '0' <= str[i] <= '9':
                type = 3  # 是数字,常数
            else:
                type = belong_to(str[i], 4)
                if type > 0:  # 是运算符
                    # 是能跟=号的运算符,后面是=号
                    if type == 2 and str[i + 1] == '=':
                        i = i + 1  # 结束位置后移
                    output(str, n, i, 4)  # 输出 + 递归 + 结束
                    scan(str, i + 1)
                    return
                elif belong_to(str[i], 5):  # 是分隔符
                    output(str, n, i, 5)  # 输出 + 递归 + 结束
                    scan(str, i + 1)
                    return
                else:
                    print("失败:", str[i])
                    return
        elif type == 1:  # 关键字或标识符
            if not (('a' <= str[i] <= 'z') or ('A' <= str[i] <= 'Z')):  # 不是字母了
                if '0' <= str[i] <= '9':  # 是数字,只能是标识符
                    type = 2
                else:  # 非字母数字
                    type = iskeywords(str, n, i - 1)
                    output(str, n, i - 1, type)  # 输出 + 递归 + 结束
                    scan(str, i)
                    return
        elif type == 2:  # 标识符
            if not (('a' <= str[i] <= 'z') or ('A' <= str[i] <= 'Z')):
                # 不是字母了
                if not ('0' <= str[i] <= '9'):
                    # 不是数字
                    output(str, n, i - 1, type)  # 输出 + 递归 + 结束
                    scan(str, i)
                    return
        elif type == 3:
            if not ('0' <= str[i] <= '9'):
                # 不是数字
                output(str, n, i - 1, type)  # 输出 + 递归 + 结束
                scan(str, i)
                return
        else:
            print("%d失败" % type)
        i += 1


# 添加S->;E;,形成句子括号
# S->;E;        ;       ;
# E->T|E+T      +,*,i,( +,*,i,)
# T->F|T*F      *,i,(   *,i,)
# F->i|(E)      i,(     i,)
#   A-> ···aB···    b∈FIRSTVT(B)    a<b
#   A-> ···Bb···    a∈LASTVT(B)     a>b

#       +   *   (   )   i   ;
#   +   >   <   <   >   <   >
#   *   >   >   <   >   <   >
#   (   <   <   <   =   <
#   )   >   >       >       >
#   i   >   >       >       >
#   ;   <   <   <       <   =

# 算符分析函数
def Operator_Analysis():
    priority_relationship = {  # 优先关系
        '+': {'+': '>', '*': '<', '(': '<', ')': '>', 'i': '<', ';': '>'},
        '*': {'+': '>', '*': '>', '(': '<', ')': '>', 'i': '<', ';': '>'},
        '(': {'+': '<', '*': '<', '(': '<', ')': '=', 'i': '<', ';': None},
        ')': {'+': '>', '*': '>', '(': None, ')': '>', 'i': None, ';': '>'},
        'i': {'+': '>', '*': '>', '(': None, ')': '>', 'i': None, ';': '>'},
        ';': {'+': '<', '*': '<', '(': '<', ')': None, 'i': '<', ';': '='}}
    p = program.copy()  # 剩余输入串
    s = [';']  # 栈
    a = None  # 当前符号
    k = 0
    j = 0
    while 1:
        # 读入下一个符号
        a = p.pop(0)
        if a[0] == 2 or a[0] == 3:
            a = 'i'
        else:
            a = a[1]
        if not s[k] == 'F':  # 找找终结符
            j = k
        else:
            j = k - 1
        while priority_relationship[s[j]][a] == '>':  # 规约
            while 1:
                Q = s[j]
                if not s[j - 1] == 'F':
                    j = j - 1
                else:
                    j = j - 2
                if priority_relationship[s[j]][Q] == '<':  # 找到左括号结束
                    break
            if len(s[j + 1:k + 1]) % 2 == 0:    # 如果不是奇数就不是 a op b,a,(a),这几种形式,
                print("错误")
                return -1

            s = s[0:j + 1]
            s.append('F')
            k = j + 1
        if priority_relationship[s[j]][a] == '<' or priority_relationship[s[j]][a] == '=':
            s.append(a)  # 入栈
            k = k + 1
        else:
            print("错误")
            return -1
        if a == ';':
            break
    print("正确")
    return 1


file = "program.txt"
file = open(file)  # 读取文件
while i := file.readline():
    program = []  # 记录读到的句子
    scan(i, 0)
    print(i, end='')
    Operator_Analysis()
file.close()

结果:

10;
正确
1+2;
正确
(1+2)*3+(5+6*7);
正确
((1+2)*3+4;
错误
1+2+3+(*4+5);
错误
(a+b)*(c+d);
正确
((ab3+de4)**5)+1;错误

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

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

相关文章

飞桨花滑骨骼点动作识别比赛——从 baseline 调优讲解

赛题介绍背景数据集 思路讲解backbone 模型文件结构 -- PaddleVideo 框架configs 文件夹paddlevideo 文件夹 模型介绍1. ST-GCN -- Baseline 模型整体结构GCN部分TCN部分 2. 2s-AGCN自适应图卷积双流网络 3. CTR-GCNCTR-GC 赛题介绍 背景 2021 CCF BDCI 基于飞桨实现花样滑冰…

初识JavaScript---(1)

初识JavaScript———&#xff08;1&#xff09;&#xff01;&#xff01;&#xff01; 一、初识JavaScript 1.什么是JavaScript&#xff1f; JavaScript是运行在浏览器上的脚本语言&#xff0c;简称JS。JavaScript程序不需要我们程序员手动编译&#xff0c;编写完源代码之后…

shell编程-02-变量作用域

作用域 局部变量&#xff1a;变量只能在函数内部使用 全局变量&#xff1a;变量可以在当前 Shell 进程中使用 环境变量&#xff1a;变量还可以在子进程中使用 局部变量 函数中定义的变量默认是全局变量&#xff0c;在定义时加上local命令&#xff0c;此时该变量就成了局部变…

Spring系列-10 事务机制

背景&#xff1a; 在 事务-1 事务隔离级别和Spring事务传播机制 中对事务的特性、隔离级别、Spring事务的传播机制结合案例进行了分析&#xff1b;在 事务-2 Spring与Mybatis事务实现原理 中对JDBC、Mybatis、Spring整合Mybatis实现事务的原理结合框架源码进行了介绍&#xff…

如何免费使用GPT-4模型

一、引言 OpenAI 最近发布了ChatGPT最新的 GPT-4 模型&#xff0c;这是 OpenAI 迄今为止发布的最强大的语言模型系统。它不仅有视觉能力&#xff0c;而且是多模态的&#xff0c;可以解释文本和生成图像。此外&#xff0c;它在推理测试中表现良好&#xff0c;可以支持大约26种不…

Redis的ZipList和QuickList和SkipList和RedisObject

ZipList:压缩列表&#xff0c;为了节省内存而设计的一种数据结构 ZipList是一种特殊的双端链表&#xff0c;是由一系列的特殊编码的连续内存块组成&#xff0c;不需要通过指针来进行寻址来找到各个节点&#xff0c;可以在任意一端进行压入或者是弹出操作&#xff0c;并且该操作…

RocketMQ的学习历程(5)----broker内部设计

文章目录 概要整体架构流程技术名词解释CommitLog和ConsumeQueue页缓存和内存映射刷盘机制 小结 概要 在首个学习历程中&#xff0c;我们已经了解了&#xff0c;RokctMQ简单的工作流程。 如果想要更深的理解RokcetMQ消息处理的流程&#xff0c;broker内部流程的理解是必要的&…

【挑战全站最全】Linux系统的安装与配置教程——以CentOS为例

&#x1f680;作者&#xff1a;那个叫马尔的大夫&#x1f680; ⭐专栏&#xff1a;操作系统⭐ &#x1f33c;内容&#xff1a;主要分享一些关于Linux操作系统的知识 &#x1f967;不忘初心&#xff0c;砥砺前行~ 目录 一、用到的软件环境——虚拟机软件&#xff08;必需&#…

调用函数不仅仅只是传递正确的参数类型

这里有一个新手犯下的一个典型错误。 假设&#xff0c;我们想调用这个函数&#xff0c;GetBinaryType。 void sample() { if (GetBinaryType(TEXT(“explorer.exe”), ????)) { … } } 请问&#xff0c;这里的问号处应该传递什么类型的参数&#xff1f;你可能会说&#x…

python、pyqt5实现人脸检测、性别和年龄预测

摘要&#xff1a;这篇博文介绍基于opencv&#xff1a;DNN模块自带的残差网络的人脸、性别、年龄识别系统&#xff0c;系统程序由OpenCv, PyQt5的库实现。如图系统可通过摄像头获取实时画面并识别其中的人脸表情&#xff0c;也可以通过读取图片识别&#xff0c;本文提供完整的程…

设计模式入门:策略模式

现有一套模拟鸭子游戏&#xff0c;可以一边游泳&#xff0c;一边呱呱叫。 每种鸭子都会呱呱叫和游泳&#xff0c;只是外观不同。因此&#xff0c;quack和swim放在父类中&#xff0c;display放在子类中实现。 增加新的功能&#xff1a;鸭子飞翔。 1 我们可能想到直接在父类中增…

LeetCode——最小化字符串长度

目录 一、题目 二、题目解读 三、代码 1、set去重 2、用一个二进制数记录每个字母是否出现过 一、题目 6462. 最小化字符串长度 - 力扣&#xff08;Leetcode&#xff09; 给你一个下标从 0 开始的字符串 s &#xff0c;重复执行下述操作 任意 次&#xff1a; 在字符串…

聊一聊数据库事务的那些事(隔离级别,传播行为)

我们平时使用事务的时候&#xff0c;可能脑子里面想到和事务有关的知识点无非就是&#xff0c;ACID&#xff0c;事务隔离级别那一套&#xff0c;使用的事务也就是是通过注解的形式&#xff0c;或者手动开启事务。更细致一点的问题或许没有深究下去&#xff0c;比如事务的传播行…

STM32F407的PWM

文章目录 32的PWM资源PWM输出原理捕获/比较模式寄存器&#xff08;TIMx_CCMR1/2&#xff09;捕获/比较使能寄存器&#xff08;TIMx_CCER&#xff09;捕获/比较寄存器&#xff08;TIMx_CCR1~4&#xff09; 库函数版本的PWM波输出开启 TIM3 时钟以及复用功能时钟置 &#xff0c;配…

对CT数据进行最小最大值归一化(Min-Max Normalization)和消除过暗过亮值处理

文章目录 PIL库的图像失真问题使用最小最大值归一化&#xff08;Min-Max Normalization&#xff09;预处理消除过暗过亮值pytorch中对tensor使用最小最大值归一化处理&#xff08;torchvision.transforms&#xff09; 我们在处理CT图像时&#xff08;以dcm格式为例&#xff09;…

全栈小程序开发路线

目录 个人心得&#xff1a; 我的学习路线 个人心得&#xff1a; 我擅长的是小程序开发和技术变现&#xff0c;从2021年至今开发上线20于个小程序&#xff0c;矩阵用户超过10万&#xff0c;变现10万左右。 以下是部分小程序截图&#xff0c;追风口做的小程序&#xff0c;基本…

「Win」Windows注册表介绍与操作

✨博客主页&#xff1a;何曾参静谧的博客 &#x1f4cc;文章专栏&#xff1a;「Win」Windows程序设计 相关术语 Windows的注册表&#xff1a;是一个重要的系统组件&#xff0c;用于存储操作系统和应用程序的配置信息。它类似于一个数据库&#xff0c;包含了各种键值对、参数、设…

Vue报错:Error: error:0308010C:digital envelope routines::unsupported解决

问题 node 环境 Node.js v18.14.2 使用npm start.出现以下报错 Error: error:0308010C:digital envelope routines::unsupported at new Hash (node:internal/crypto/hash:71:19) at Object.createHash (node:crypto:133:10) at module.exports (F:\RuoYi-Cloud\CourseSched…

SWAT模型系统学习(建模方法、实例应用、高级进阶)

目前&#xff0c;水环境问题逐渐成为制约社会经济和环境可持续发展的重要因素。根据国内外研究表明&#xff0c;受全球环境变化和经济快速发展的影响&#xff0c;面源污染已逐渐成为水环境污染的第一因素。但面源污染由于具有排放分散、隐蔽&#xff0c;排污随机、不确定、不易…

搜索算法(三) 回溯法

1.回溯法 回溯法可以理解成一种特殊的深度优先算法&#xff0c;比起普通的DFS&#xff0c;多了还原当前节点的一步。 修改当前节点、递归子节点、还原当前节点。 本质是一种试错的思想。 维基百科&#xff1a; 2.例题 1&#xff09; 力扣https://leetcode.cn/problems/pe…