用python编写LR(0)分析表的构造 含界面设计的完整代码注解

时间: 2024-05-14 18:12:39 浏览: 32
由于LR(0)分析表的构造过程比较复杂,因此我们需要将其分解为多个步骤来实现。以下是用python编写LR(0)分析表的完整代码注解: ```python from collections import defaultdict # 定义文法 grammar = { 'S': ['E'], # 文法规则1 'E': ['E+T', 'T'], # 文法规则2 'T': ['T*F', 'F'], # 文法规则3 'F': ['(E)', 'id'] # 文法规则4 } # 定义终结符号和非终结符号 terminals = {'+', '*', '(', ')', 'id'} non_terminals = {'S', 'E', 'T', 'F'} # 定义LR(0)自动机 action = defaultdict(dict) # 动作表 goto = defaultdict(dict) # 转移表 # 计算FIRST集和FOLLOW集 first = defaultdict(set) follow = defaultdict(set) # 计算FIRST集 def compute_first(symbol): if symbol in terminals: first[symbol].add(symbol) else: for rule in grammar[symbol]: if rule[0] in terminals: first[symbol].add(rule[0]) else: compute_first(rule[0]) first[symbol].update(first[rule[0]]) # 计算FOLLOW集 def compute_follow(): follow['S'].add('$') # 将$添加到S的FOLLOW集中 for symbol in non_terminals: for rule in grammar[symbol]: for i in range(len(rule)): if rule[i] in non_terminals: if i == len(rule) - 1: # 如果该符号是产生式的最后一个符号 follow[rule[i]].update(follow[symbol]) # 将FOLLOW(S)加入FOLLOW(A)中 else: if rule[i+1] in terminals: # 如果下一个符号是终结符 follow[rule[i]].add(rule[i+1]) # 将该终结符加入FOLLOW(A)中 else: follow[rule[i]].update(first[rule[i+1]]) # 将FIRST(β)中的所有符号加入FOLLOW(A)中 # 构造LR(0)自动机 def construct_LR0_machine(): items = {} # 项目集 C = [] # 项目集规范族 start_item = ('S\'', ['S']) # 初始项目 items[start_item] = 0 # 将初始项目加入项目集中,并将其编号为0 C.append(set([start_item])) # 将初始项目集加入项目集规范族中 i = 0 # 项目集编号 while i < len(C): item_set = C[i] # 取出一个项目集 i += 1 for symbol in terminals.union(non_terminals): # 对于文法中的每个符号 G = set() # G表示通过该符号能够到达的项目集 for item in item_set: # 对于项目集中的每个项目 if item[1] != [] and item[1][0] == symbol: # 如果该项目的下一个符号是当前符号 G.add((item[0], item[1][1:])) # 将该项目的点向后移动一位,并加入G中 if G != set(): # 如果G不为空 if G not in C: # 如果G不在项目集规范族中 items.update({item: len(items) for item in G}) # 将G中的所有项目加入项目集中,并分配编号 C.append(G) # 将G加入项目集规范族中 action[item_set][symbol] = ('S', items[G]) # 将action表中对应的项设为'State' else: for item in item_set: # 对于项目集中的每个项目 if item[1] != [] and item[1][0] in non_terminals: # 如果该项目的下一个符号是非终结符 G = set() # G表示通过该非终结符能够到达的项目集 for rule in grammar[item[1][0]]: # 对于该非终结符的每个产生式 G.add((item[1][0], list(rule))) # 将该产生式加入G中 if G not in C: # 如果G不在项目集规范族中 items.update({item: len(items) for item in G}) # 将G中的所有项目加入项目集中,并分配编号 C.append(G) # 将G加入项目集规范族中 goto[item_set][item[1][0]] = items[G] # 将goto表中对应的项设为'State' for item in item_set: # 对于项目集中的每个项目 if item[1] == []: # 如果该项目的点已经到达了产生式的末尾 if item[0] == 'S\'': # 如果该项目是初始项目 action[item_set]['$'] = ('Accept', None) # 将action表中对应的项设为'Accept' else: for a in follow[item[0]]: # 对于该项目的非终结符的每个FOLLOW符号 action[item_set][a] = ('Reduce', item[0] + '->' + ''.join(item[1])) # 将action表中对应的项设为'Reduce' # 输出LR(0)自动机 def output_LR0_machine(): print('Action Table:') print('{:20s}'.format('State'), end='') for a in terminals.union({'$'}): print('{:10s}'.format(str(a)), end='') print() for i in range(len(C)): print('{:20s}'.format(str(i)), end='') for a in terminals.union({'$'}): if a in action[C[i]]: print('{:10s}'.format(str(action[C[i]][a][0]) + ' ' + str(action[C[i]][a][1])), end='') else: print('{:10s}'.format(''), end='') print() print('\nGoto Table:') print('{:20s}'.format('State'), end='') for a in non_terminals: print('{:10s}'.format(str(a)), end='') print() for i in range(len(C)): print('{:20s}'.format(str(i)), end='') for a in non_terminals: if a in goto[C[i]]: print('{:10s}'.format(str(goto[C[i]][a])), end='') else: print('{:10s}'.format(''), end='') print() # 主函数 if __name__ == '__main__': # 计算FIRST集和FOLLOW集 for symbol in terminals.union(non_terminals): compute_first(symbol) compute_follow() # 构造LR(0)自动机 construct_LR0_machine() # 输出LR(0)自动机 output_LR0_machine() ``` 上述代码中,我们首先定义了文法的规则、终结符号和非终结符号,并使用`defaultdict`定义了动作表`action`和转移表`goto`。接着,我们定义了计算FIRST集和FOLLOW集的函数`compute_first`和`compute_follow`。 在构造LR(0)自动机时,我们使用了项目集法,并定义了如下函数: - `construct_LR0_machine`: 构造LR(0)自动机的函数。 - `items`: 用于存储项目集中的所有项目,并为每个项目分配一个编号。 - `C`: 用于存储所有项目集。 - `start_item`: 初始项目。 - `item_set`: 当前处理的项目集。 - `symbol`: 当前处理的符号。 - `G`: 通过当前符号能够到达的项目集。 - `rule`: 产生式。 - `output_LR0_machine`: 用于输出LR(0)自动机的函数。 最后,我们在主函数中调用`compute_first`、`compute_follow`和`construct_LR0_machine`函数,然后输出LR(0)自动机。

相关推荐

最新推荐

recommend-type

用python+pyqt5手工编写一个含交互界面的简易的词法分析器

python+pyqt5手工编写一个含交互界面的简易词法分析器 @author:x1nge. 编译原理基础实验 基础 在之前的一篇博文中我记录了一个不含交互界面的简易词法分析器程序编写内容 点击此处查看 在本文我将用pyqt5写一个...
recommend-type

使用 prometheus python 库编写自定义指标的方法(完整代码)

主要介绍了使用 prometheus python 库编写自定义指标的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
recommend-type

基于python的Tkinter编写登陆注册界面

主要为大家详细介绍了基于python的Tkinter编写登陆注册界面,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
recommend-type

Python+Qt5+Pycharm 界面设计.docx

最近小白需要做一个计算器,但是计算机编程能力几乎没有,所以各种查阅资料,最终确认使用Python+Qt5+Pycharm做一个界面。但是过程中遇到太多的坑,所以想把过程和方法记录下来,供大家参考。
recommend-type

python GUI库图形界面开发之PyQt5简单绘图板实例与代码分析

主要介绍了python GUI库图形界面开发之PyQt5简单绘图板实例与代码分析,需要的朋友可以参考下
recommend-type

zigbee-cluster-library-specification

最新的zigbee-cluster-library-specification说明文档。
recommend-type

管理建模和仿真的文件

管理Boualem Benatallah引用此版本:布阿利姆·贝纳塔拉。管理建模和仿真。约瑟夫-傅立叶大学-格勒诺布尔第一大学,1996年。法语。NNT:电话:00345357HAL ID:电话:00345357https://theses.hal.science/tel-003453572008年12月9日提交HAL是一个多学科的开放存取档案馆,用于存放和传播科学研究论文,无论它们是否被公开。论文可以来自法国或国外的教学和研究机构,也可以来自公共或私人研究中心。L’archive ouverte pluridisciplinaire
recommend-type

MATLAB正态分布协方差分析:揭示正态分布变量之间的协方差

![MATLAB正态分布协方差分析:揭示正态分布变量之间的协方差](https://site.cdn.mengte.online/official/2021/11/20211128213137293.png) # 1. 正态分布概述 正态分布,又称高斯分布,是统计学中最重要的连续概率分布之一。它广泛应用于自然科学、社会科学和工程领域。 正态分布的概率密度函数为: ``` f(x) = (1 / (σ√(2π))) * exp(-(x - μ)² / (2σ²)) ``` 其中: - μ:正态分布的均值 - σ:正态分布的标准差 - π:圆周率 正态分布具有以下特性: - 对称性:
recommend-type

我正在开发一款个人碳足迹计算app,如何撰写其需求分析文档,请给我一个范例

为了更全面、清晰地定义个人碳足迹计算app的需求,需求分析文档应该包含以下内容: 1.项目简介:对该app项目的概述及目标进行说明。 2.用户分析:包括目标用户群、用户需求、行为等。 3.功能需求:对app的基本功能进行定义,如用户登录、数据录入、数据统计等。 4.非功能需求:对使用app的性能和质量等进行定义,如界面设计、数据安全、可扩展性等。 5.运行环境:包括app的开发环境和使用环境。 下面是一个范例: 需求分析文档 1. 项目简介 该app项目旨在为用户提供一款方便、易用、可定制的个人碳足迹计算平台,以促进环保和可持续性发展。 2. 用户分析 目标用户群:全球关
recommend-type

JSBSim Reference Manual

JSBSim参考手册,其中包含JSBSim简介,JSBSim配置文件xml的编写语法,编程手册以及一些应用实例等。其中有部分内容还没有写完,估计有生之年很难看到完整版了,但是内容还是很有参考价值的。