编译原理实验三:算符优先分析算法的设计与实现(python)

news2024/11/25 16:57:09

实验目的

根据算符优先分析法,对表达式进行语法分析,使其能够判断一个表达式是否正确。通过算符优先分析方法的实现,加深对自下而上语法分析方法的理解。

实验内容

1、输入文法。可以是如下算术表达式的文法(你可以根据需要适当改变):
E→E+T|E-T|T
T→T*F|T/F|F
F→(E)|i
2、对给定表达式进行分析,输出表达式正确与否的判断。
程序输入/输出示例:
输入:1+2;
输出:正确
输入:(1+2)/3+4-(5+6/7);
输出:正确
输入:((1-2)/3+4
输出:错误
输入:1+2-3+(*4/5)
输出:错误

实验过程

(1)读取文法,数据预处理
从文件中读取文法、终结符和非终结符。本部分处理与实验二中读取文法的方法一致。

def data_input():  # 读取文法
    with open("input2.txt", 'r+', encoding="utf-8") as f:
        temp = f.readlines()
    for i in temp:
        line = str(i.strip("\n"))
        formules.append(line)
        if line[0] not in non_ter:
            non_ter.append(line[0])
            grammarElement.setdefault(line[0], line[5:])
        else:
            grammarElement[line[0]] += "|" + line[5:]
    for i in temp:
        line = str(i.strip("\n")).replace(" -> ", "")
        for j in line:
            if j not in non_ter and j not in terSymblo:
                terSymblo.append(j)
    if 'ε' in terSymblo: terSymblo.remove('ε')

(2)求firstVT集:

def get_fistVT(formule):
    x = formule[0]
    ind = non_ter.index(x)
    index = []
    i = 5
    if formule[i] in terSymblo and formule[i] not in firstVT[x]:  # 首位为终结符 P->a...
        firstVT[x] += formule[i]
    elif formule[i] in non_ter:  # 首位为非终结符
        for f in firstVT[formule[i]]:
            if f not in firstVT[x]:
                firstVT[x] += f
        if i + 1 < len(formule):
            if formule[i + 1] in terSymblo and formule[i + 1] not in firstVT[x]:  # P->Q..
                firstVT[x] += formule[i + 1]

(3)求lastVT集

def get_lastVT(formule):
    x = formule[0]
    i = len(formule) - 1
    if formule[i] in terSymblo and formule[i] not in lastVT[x]:
        lastVT[x] += formule[i]
    elif formule[i] in non_ter:
        for f in lastVT[formule[i]]:
            if f not in lastVT[x]:
                lastVT[x] += f
        if formule[i - 1] in terSymblo and formule[i - 1] not in lastVT[x]:
            lastVT[x] += formule[i - 1]

(4)算符优先分析表
同样使用二维字典进行存储,先编写二维字典的更新函数

def addtodict2(thedict, key_a, key_b, val):  # 设置二维字典的函数
    if key_a in thedict.keys():
        thedict[key_a].update({key_b: val})
    else:
        thedict.update({key_a: {key_b: val}})

之后求算符优先分析表

def analy(formule): #算符优先分析表
    start = 5
    end = len(formule) - 2
    if start == end: return
    for i in range(start, end):
        if formule[i] in terSymblo and formule[i + 1] in terSymblo:
            addtodict2(data, formule[i], formule[i + 1], "=")
        if formule[i] in terSymblo and formule[i + 1] in non_ter and formule[i + 2] in terSymblo:
            addtodict2(data, formule[i], formule[i + 2], "=")
        if formule[i] in terSymblo and formule[i + 1] in non_ter:
            for j in firstVT[formule[i + 1]]:
                addtodict2(data, formule[i], j, "<")
        if formule[i] in non_ter and formule[i + 1] in terSymblo:
            for j in lastVT[formule[i]]:
                addtodict2(data, j, formule[i + 1], ">")
        if formule[i + 1] in terSymblo and formule[i + 2] in non_ter:
            for j in firstVT[formule[i + 2]]:
                addtodict2(data, formule[i + 1], j, "<")
        if formule[i + 1] in non_ter and formule[i + 2] in terSymblo:
            for j in lastVT[formule[i + 1]]:
                addtodict2(data, j, formule[i + 2], ">")
                ```
(5)算符优先算法分析过程
首先是过程中要用到的过程函数 
```python
def reverseString(string):
    return string[::-1]

初始化两个栈

def initStack(string):
   # 分析栈,入栈#
   analysisStack = "#"
   # 当前输入串入栈,即string逆序入栈
   currentStack = reverseString(string)
   # 调用分析函数
   toAnalyze(analysisStack, currentStack)

寻找分析栈最顶终结符元素,返回该元素及其下标

def findVTele(string):
    ele = '\0'
    ele_index = 0
    for i in range(len(string)):
        if (string[i] in terSymblo):
            ele = string[i]
            ele_index = i
    return ele, ele_index
    ```
然后才是具体分析过程
根据栈中内容进行分析
```python
def toAnalyze(analysisStack, currentStack):
    global analyzeResult
    global analyzeStep
    analyzeStep += 1
    analysisStack_top, analysisStack_index = findVTele(analysisStack)  # 分析栈最顶终结符元素及下标
    currentStack_top = currentStack[-1]  # 当前输入串栈顶
    relation = data[analysisStack_top][currentStack_top]
    if relation == '<':
        print(" {:^5} {:^15} {:^9} {:^15} {:^12} ".format(analyzeStep, analysisStack, relation,
                                                          reverseString(currentStack), '移进'))
        analysisStack += currentStack_top
        currentStack = currentStack[:-1]
        toAnalyze(analysisStack, currentStack)
    elif relation == '>':
        print(" {:^5} {:^15} {:^9} {:^15} {:^12} ".format(analyzeStep, analysisStack, relation,
                                                          reverseString(currentStack), '归约'))
        currenChar = analysisStack_top
        temp_string = ""
        for i in range(len(analysisStack) - 1, -1, -1):
            if (analysisStack[i] >= 'A' and analysisStack[i] <= 'Z'):
                temp_string = analysisStack[i] + temp_string
                continue
            elif (data[analysisStack[i]][currenChar] == '<'):
                break;
            temp_string = analysisStack[i] + temp_string
            currenChar = analysisStack[i]
        if (temp_string in sentencePattern):
            analysisStack = analysisStack[0:i + 1]
            analysisStack += 'N'
            toAnalyze(analysisStack, currentStack)
        else:
            print("归约出错!待归约串为:", temp_string, "--->产生式右部无此句型!")
            analyzeResult = False
            return
    elif (relation == '='):
        if (analysisStack_top == '#' and currentStack_top == '#'):
            print(" {:^5} {:^15} {:^9} {:^15} {:^12} ".format(analyzeStep, analysisStack, relation,
                                                              reverseString(currentStack), '完成'))
            analyzeResult = True
            return
        else:
            print(" {:^5} {:^15} {:^9} {:^15} {:^12} ".format(analyzeStep, analysisStack, relation,
                                                              reverseString(currentStack), '移进'))
            analysisStack += currentStack_top
            currentStack = currentStack[:-1]
            toAnalyze(analysisStack, currentStack)
    elif (relation == None):
        print(" {:^5} {:^15} {:^9} {:^15} {:^12} ".format(analyzeStep, analysisStack, 'None',
                                                          reverseString(currentStack), '报错'))
        analyzeResult = False
        return

(6)之后是主程序,控制个程序的运行,以及分析过程的输出

data_input()
data = dict()
for i in non_ter:
    firstVT.setdefault(i, "")
    lastVT.setdefault(i, "")
for i in terSymblo:
    for j in terSymblo:
        addtodict2(data, i, j, '')
#print(data)
sym = non_ter + terSymblo

for n in range(10):
    for i in formules:
        get_fistVT(i)
        get_lastVT(i)
print("firstVT集合:")
for i in non_ter:
    print(i+" : "+firstVT[i])
print("lastVT集合:")
for i in non_ter:
    print(i+" : "+lastVT[i])

temp2 = Start +" -> #" +Start+"#"
formules.append(temp2)
for i in formules:
    analy(i)
print("算符优先分析表")
for i in terSymblo:
    print("\t" + i.ljust(4), end="")
print()
for i in terSymblo:
    print(i.ljust(4), end="")
    for j in terSymblo:
        if j in data[i]:
            print(data[i][j].ljust(8), end="")
        else:
            print("\t\t", end="")
    print()

sentencePattern = ["N+N", "N*N", "N/N", "(N)", "i","N^N","N,N","a"]
analyzeResult = False
analyzeStep = 0
print("请输入待分析的字符串:")
string = input()
string = string.replace(" ", "")
string+="#"
print(" {:^4} {:^13} {:^6} {:^12} {:^10} ".format('步骤', '分析栈', '优先关系', '当前输入串', '移进或归约'))
initStack(string)
if (analyzeResult):
    print("该字符串是文法的合法句子。\n")
else:
    print("该字符串不是文法的合法句子。\n")

总程序

import re

grammarElement = {}
terSymblo = ['#']
non_ter = []
Start = 'S'
allSymbol = []  # 所有符号
firstVT = {}  # FIRSTVT集
lastVT = {}  # lastVT集
formules = []

def data_input():  # 读取文法
    with open("input2.txt", 'r+', encoding="utf-8") as f:
        temp = f.readlines()
    for i in temp:
        line = str(i.strip("\n"))
        formules.append(line)
        if line[0] not in non_ter:
            non_ter.append(line[0])
            grammarElement.setdefault(line[0], line[5:])
        else:
            grammarElement[line[0]] += "|" + line[5:]
    for i in temp:
        line = str(i.strip("\n")).replace(" -> ", "")
        for j in line:
            if j not in non_ter and j not in terSymblo:
                terSymblo.append(j)
    if 'ε' in terSymblo: terSymblo.remove('ε')


def get_fistVT(formule):
    x = formule[0]
    ind = non_ter.index(x)
    index = []
    i = 5
    if formule[i] in terSymblo and formule[i] not in firstVT[x]:  # 首位为终结符 P->a...
        firstVT[x] += formule[i]
    elif formule[i] in non_ter:  # 首位为非终结符
        for f in firstVT[formule[i]]:
            if f not in firstVT[x]:
                firstVT[x] += f
        if i + 1 < len(formule):
            if formule[i + 1] in terSymblo and formule[i + 1] not in firstVT[x]:  # P->Q..
                firstVT[x] += formule[i + 1]

def get_lastVT(formule):
    x = formule[0]
    i = len(formule) - 1
    if formule[i] in terSymblo and formule[i] not in lastVT[x]:
        lastVT[x] += formule[i]
    elif formule[i] in non_ter:
        for f in lastVT[formule[i]]:
            if f not in lastVT[x]:
                lastVT[x] += f
        if formule[i - 1] in terSymblo and formule[i - 1] not in lastVT[x]:
            lastVT[x] += formule[i - 1]

def addtodict2(thedict, key_a, key_b, val):  # 设置二维字典的函数
    if key_a in thedict.keys():
        thedict[key_a].update({key_b: val})
    else:
        thedict.update({key_a: {key_b: val}})

def analy(formule): #算符优先分析表
    start = 5
    end = len(formule) - 2
    if start == end: return
    for i in range(start, end):
        if formule[i] in terSymblo and formule[i + 1] in terSymblo:
            addtodict2(data, formule[i], formule[i + 1], "=")
        if formule[i] in terSymblo and formule[i + 1] in non_ter and formule[i + 2] in terSymblo:
            addtodict2(data, formule[i], formule[i + 2], "=")
        if formule[i] in terSymblo and formule[i + 1] in non_ter:
            for j in firstVT[formule[i + 1]]:
                addtodict2(data, formule[i], j, "<")
        if formule[i] in non_ter and formule[i + 1] in terSymblo:
            for j in lastVT[formule[i]]:
                addtodict2(data, j, formule[i + 1], ">")
        if formule[i + 1] in terSymblo and formule[i + 2] in non_ter:
            for j in firstVT[formule[i + 2]]:
                addtodict2(data, formule[i + 1], j, "<")
        if formule[i + 1] in non_ter and formule[i + 2] in terSymblo:
            for j in lastVT[formule[i + 1]]:
                addtodict2(data, j, formule[i + 2], ">")

def reverseString(string):
    return string[::-1]

# 初始化两个栈
def initStack(string):
    # 分析栈,入栈#
    analysisStack = "#"
    # 当前输入串入栈,即string逆序入栈
    currentStack = reverseString(string)
    # 调用分析函数
    toAnalyze(analysisStack, currentStack)

# 寻找分析栈最顶终结符元素,返回该元素及其下标
def findVTele(string):
    ele = '\0'
    ele_index = 0
    for i in range(len(string)):
        if (string[i] in terSymblo):
            ele = string[i]
            ele_index = i
    return ele, ele_index

# 根据栈中内容进行分析
def toAnalyze(analysisStack, currentStack):
    global analyzeResult
    global analyzeStep
    analyzeStep += 1
    analysisStack_top, analysisStack_index = findVTele(analysisStack)  # 分析栈最顶终结符元素及下标
    currentStack_top = currentStack[-1]  # 当前输入串栈顶
    relation = data[analysisStack_top][currentStack_top]
    if relation == '<':
        print(" {:^5} {:^15} {:^9} {:^15} {:^12} ".format(analyzeStep, analysisStack, relation,
                                                          reverseString(currentStack), '移进'))
        analysisStack += currentStack_top
        currentStack = currentStack[:-1]
        toAnalyze(analysisStack, currentStack)
    elif relation == '>':
        print(" {:^5} {:^15} {:^9} {:^15} {:^12} ".format(analyzeStep, analysisStack, relation,
                                                          reverseString(currentStack), '归约'))
        currenChar = analysisStack_top
        temp_string = ""
        for i in range(len(analysisStack) - 1, -1, -1):
            if (analysisStack[i] >= 'A' and analysisStack[i] <= 'Z'):
                temp_string = analysisStack[i] + temp_string
                continue
            elif (data[analysisStack[i]][currenChar] == '<'):
                break;
            temp_string = analysisStack[i] + temp_string
            currenChar = analysisStack[i]
        if (temp_string in sentencePattern):
            analysisStack = analysisStack[0:i + 1]
            analysisStack += 'N'
            toAnalyze(analysisStack, currentStack)
        else:
            print("归约出错!待归约串为:", temp_string, "--->产生式右部无此句型!")
            analyzeResult = False
            return
    elif (relation == '='):
        if (analysisStack_top == '#' and currentStack_top == '#'):
            print(" {:^5} {:^15} {:^9} {:^15} {:^12} ".format(analyzeStep, analysisStack, relation,
                                                              reverseString(currentStack), '完成'))
            analyzeResult = True
            return
        else:
            print(" {:^5} {:^15} {:^9} {:^15} {:^12} ".format(analyzeStep, analysisStack, relation,
                                                              reverseString(currentStack), '移进'))
            analysisStack += currentStack_top
            currentStack = currentStack[:-1]
            toAnalyze(analysisStack, currentStack)
    elif (relation == None):
        print(" {:^5} {:^15} {:^9} {:^15} {:^12} ".format(analyzeStep, analysisStack, 'None',
                                                          reverseString(currentStack), '报错'))
        analyzeResult = False
        return

data_input()
data = dict()
for i in non_ter:
    firstVT.setdefault(i, "")
    lastVT.setdefault(i, "")
for i in terSymblo:
    for j in terSymblo:
        addtodict2(data, i, j, '')
#print(data)
sym = non_ter + terSymblo

for n in range(10):
    for i in formules:
        get_fistVT(i)
        get_lastVT(i)
print("firstVT集合:")
for i in non_ter:
    print(i+" : "+firstVT[i])
print("lastVT集合:")
for i in non_ter:
    print(i+" : "+lastVT[i])

temp2 = Start +" -> #" +Start+"#"
formules.append(temp2)
for i in formules:
    analy(i)
print("算符优先分析表")
for i in terSymblo:
    print("\t" + i.ljust(4), end="")
print()
for i in terSymblo:
    print(i.ljust(4), end="")
    for j in terSymblo:
        if j in data[i]:
            print(data[i][j].ljust(8), end="")
        else:
            print("\t\t", end="")
    print()

sentencePattern = ["N+N", "N*N", "N/N", "(N)", "i","N^N","N,N","a"]
analyzeResult = False
analyzeStep = 0
print("请输入待分析的字符串:")
string = input()
string = string.replace(" ", "")
string+="#"
print(" {:^4} {:^13} {:^6} {:^12} {:^10} ".format('步骤', '分析栈', '优先关系', '当前输入串', '移进或归约'))
initStack(string)
if (analyzeResult):
    print("该字符串是文法的合法句子。\n")
else:
    print("该字符串不是文法的合法句子。\n")

测试

测试文法

S -> a
S -> ^
S -> (T)
T -> T,S
T -> S

在这里插入图片描述
在这里插入图片描述
完成

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

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

相关文章

赋能组织执行力学习-R4管理-结果体系、责任体系、检查与改进体系、及时激励体系

本文向大家介绍R4管理&#xff0c;是由结果体系&#xff08;Result&#xff09;、责任体系&#xff08;Responsibility&#xff09;、检查与改进体系&#xff08;Review&#xff09;、及时激励体系&#xff08;Reward&#xff09;组成&#xff0c;帮助我们如何更好的运用。 马云…

TikTok选品技巧 | 爆品一般是怎么选出来的,快看这些技巧

TikTok电商商家看过来&#xff01;随着短视频时代的兴起与发展&#xff0c;TikTok在全球受到越来越多的用户所追捧。同时&#xff0c;吸引了更多TikTok商家前来发展电商。但是&#xff0c;想要在这里快速实现TikTok变现目标&#xff0c;并非容易。TikTok选品和TikTok营销是最不…

数据库原理及MySQL应用 | 多表查询

在实际应用中&#xff0c;多表查询应用相对较多&#xff0c;根据多表之间的相关列&#xff0c;可以从多个表中检索出所需数据。 在实际应用中&#xff0c;单表查询应用范围相对较少&#xff0c;因为用户需要的数据往往存储在多个不同的表中&#xff0c;这时需要进行多表查询。…

oracle的pkg改为hivesql

1. oracle的() 改为hive左右连接 oracle ()学习_cclovezbf的博客-CSDN博客最近工作需要将oracle的存储过程转化为hive的sql脚本。遇到很多不一样的地方&#xff0c;例如oracle连接中有()号的用法。借鉴这篇文章&#xff0c;但是这个排版比较烂。。。先建表和插入数据首先说明…

笔试强训(四十六)

目录一、选择题二、编程题2.1 简单错误记录2.1.1 题目2.1.2 题解一、选择题 &#xff08;1&#xff09;一台刚接入互联网的WEB服务器第一次被访问到时&#xff0c;不同协议的发生顺序是下面中的&#xff08;A&#xff09; A.ARP->DNS->HTTP B.ARP->HTTP->DNS C.DN…

怎么提取伴奏?有什么实用的提取软件?

由于我喜欢唱歌&#xff0c;所以在读书时期偶尔会参加学校的一些歌唱比赛或是文艺汇演。而一开始的我没什么经验&#xff0c;练习时都是放着原声带跟唱&#xff0c;但是到了舞台上发现只有伴奏&#xff0c;一时间卡不到开唱的点&#xff0c;甚是尴尬。所以后来我吸取了教训&…

蓝桥杯嵌入式 cubeMX生成代码解读

文章目录前言一、代码风格二、为什么要这些注释&#xff1f;三、生成的独立模块的代码总结前言 本篇文章讲介绍一下cubeMX生成代码的风格。 一、代码风格 在main.c中可以看到非常多的注释代码&#xff0c;很多人都不知道这些是用来干嘛的&#xff0c;现在就给大家介绍一下这…

你了解Java中的ForkJoin吗?

什么是ForkJoin? ForkJoin 从字面上看Fork是分岔的意思&#xff0c;Join是结合的意思&#xff0c;我们可以理解为将大任务拆分成小任务进行计算求解&#xff0c;最后将小任务的结果进行结合求出大任务的解&#xff0c;这些裂变出来的小任务&#xff0c;我们就可以交给不同的线…

新智慧杂志新智慧杂志社新智慧编辑部2022年第30期目录

杏坛潮_热点关注 特色劳动教育模式探究——基于“劳动周”项目的设计与实践 王胜; 1-3《新智慧》投稿&#xff1a;cn7kantougao163.com “双减”背景下小学数学大单元深度学习的实践与探索——以小学高年级为例 王晓雪; 4-6 杏坛潮_创新教育 问题教学法在高中物理教…

20221215英语学习

今日新词&#xff1a; rich adj.富有的, 富裕的, 油腻的 luck n.运气, 幸运, 好运, 侥幸 live adj.活的, 现场直播的, 实况转播的, 现场演出的 tutor n.家庭教师&#xff1b;私人教师&#xff1b;导师&#xff1b;助教 swipe v.挥拳打, 扬起巴掌打, 挥起&#xff08;物体&…

刷屏的AI 绘画,你成功驯服了吗?其背后的AIGC模型你可能还不知道

文章目录前言基于 CLIP Latents 的条件文本图像生成BLIPHugging Face奇点智源中文-CLIP百度昆仑万维之AI绘画前言 随着人工智能技术的发展与完善&#xff0c;AIGC&#xff08;AI generated content&#xff09;在内容的创作上为人们的工作和生活带来前所未有的帮助&#xff0c…

SpringCloud(7)— ElasticSearch基础

SpringCloud&#xff08;7&#xff09;— Elasticsearch基础 一 初识Elasticsearch elasticserach是一个强大的开源搜索引擎&#xff0c;可以从海量数据中迅速找到想要的内容。 elasticsearch结合了 Kibana, Logstach, Beats,也就是 elastic stack。主要应用于日志数据分析&…

【信管4.1】范围与需求

范围与需求范围其实说白了就是我们要做的东西都包括哪些内容&#xff0c;这些内容的边界在哪里&#xff0c;范围其实从另一个角度来说的话&#xff0c;也可以看成是一个产品的约束。为什么要有一个约束呢&#xff1f;你见过一个即是电商&#xff0c;又是社交&#xff0c;还能兼…

Python还好就业吗?30多岁转行晚吗?

最近不少人在微信问我现在Python还好就业不好就业&#xff1f;发展前景怎么样&#xff1f;我30多岁了&#xff0c;还能不能转行编程&#xff1f;Python该怎么学&#xff1f;如果做Python到底该做爬虫还是数据分析还是web&#xff1f;…等等这样的问题&#xff0c;现在逐一谈下我…

将市场部与整个组织联系起来,协调每个人的利益,来达成业务目标

让我们来谈谈业务目标&#xff0c;以及这些目标如何将营销部门与整个组织联系起来&#xff0c;并帮助协调每个人的利益。什么是有效的目标&#xff0c;什么是无效的目标?举一两个例子就好了。 当然。我们目前在高管层看到的情况是——甚至在新冠疫情之前我们就已经看到了——首…

【软件测试】你遇到的随机的bug?出现的原因......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 随机性bug? 为什么…

学习过程中遇到的问题总结(持续更新~~~)

问题总结问题1&#xff1a;Access denied for user 1234localhost (using password: YES)问题2&#xff1a;启动tomcat问题&#xff0c;报错Failed to execute goal org.apache.tomcat.maven:tomcat7-maven-plugin:2.2:run (default-cli) on project springMvc_03_request_mapp…

Linux 6.2:华为代码加速核心功能 715 倍!

整理 | 王启隆出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;作为送给全球开发者的圣诞礼物&#xff0c;Linux 在前日发布了 Linux 6.1 内核的稳定版&#xff0c;并开启了 Linux 6.2 的合并窗口。这次更新不仅为广大用户带来了不少新功能与改进&#xff0c;还让许…

竣达技术 | 智能机房动力环境监控主机、多功能监控服务器

专为现代各类计算机及网络通信机房、通信行业基站而设计的远程多功能监控服务器&#xff0c;系统具备3个RS485通讯接口可监控机房环境温湿度、门禁、烟雾、漏水、市电断电等各类传感器检测对应的告警状态&#xff0c;同时支持15个开关量检测。6路继电器输出控制&#xff0c;支持…

MySQL——表数据删了一半了,表文件大小还是不变

本篇文章针对 InnoDB 引擎展开讨论。一个 InnoDB 表包含两部分&#xff0c;即&#xff1a;表结构定义和数据。在 MySQL 8.0 版本以前&#xff0c;表结构是存在以.frm 为后缀的文件里。而 MySQL 8.0 版本&#xff0c;则已经允许把表结构定义放在系统数据表中了。因为表结构定义占…