构造LR(1)分析程序,利用它进行语法分析,判断给出的符号串是否为该文法识别的句子,代码

时间: 2024-03-25 22:40:51 浏览: 17
构造LR(1)分析程序的步骤如下: 1. 构造文法的所有LR(1)项集 2. 构造LR(1)分析表,包括ACTION和GOTO两个部分 3. 利用构造的分析表对输入的符号串进行分析 下面是一个示例代码,假设我们要判断如下文法是否可以识别给出的符号串: ``` S -> E E -> E + T | T T -> T * F | F F -> ( E ) | id ``` 符号串为:`( id + id ) * id` LR(1)分析程序代码如下: ```python # 定义文法的所有产生式 productions = [ ('S', 'E'), ('E', 'E', '+', 'T'), ('E', 'T'), ('T', 'T', '*', 'F'), ('T', 'F'), ('F', '(', 'E', ')'), ('F', 'id') ] # 定义终结符和非终结符 terminals = ['+', '*', '(', ')', 'id', '$'] non_terminals = ['S', 'E', 'T', 'F'] # 定义LR(1)项 class LR1Item: def __init__(self, production, dot_index, lookahead): self.production = production self.dot_index = dot_index self.lookahead = lookahead def __eq__(self, other): return self.production == other.production and self.dot_index == other.dot_index and self.lookahead == other.lookahead def __hash__(self): return hash((self.production, self.dot_index, self.lookahead)) def __str__(self): prod_str = ' '.join(self.production) prod_str = prod_str[:self.dot_index] + '.' + prod_str[self.dot_index:] return f"[{prod_str}, {self.lookahead}]" # 构造LR(1)项集 def closure_lr1(items): closure = set(items) while True: new_items = set() for item in closure: if item.dot_index < len(item.production) and item.production[item.dot_index] in non_terminals: for prod in productions: if prod[0] == item.production[item.dot_index]: lookahead = item.lookahead if item.dot_index + 1 < len(item.production): lookahead = first(item.production[item.dot_index + 1:], item.lookahead) new_item = LR1Item(prod, 0, lookahead) if new_item not in closure: new_items.add(new_item) if not new_items: break closure |= new_items return closure # 计算一个符号串的FIRST集 def first(symbols, lookahead): first_set = set() if not symbols: first_set.add(lookahead) elif symbols[0] in terminals: first_set.add(symbols[0]) elif symbols[0] in non_terminals: first_set |= first_table[symbols[0]] if 'eps' in first_set: first_set.remove('eps') first_set |= first(symbols[1:], lookahead) return first_set # 计算一个LR(1)项集的GOTO集 def goto_lr1(items, symbol): new_items = set() for item in items: if item.dot_index < len(item.production) and item.production[item.dot_index] == symbol: new_items.add(LR1Item(item.production, item.dot_index + 1, item.lookahead)) return closure_lr1(new_items) # 构造文法的FIRST集 first_table = {} for terminal in terminals: first_table[terminal] = set([terminal]) for non_terminal in non_terminals: first_table[non_terminal] = set() while True: updated = False for production in productions: non_terminal = production[0] symbols = production[1:] old_first_set = set(first_table[non_terminal]) first_set = first(symbols, 'eps') first_table[non_terminal] |= first_set if old_first_set != first_table[non_terminal]: updated = True if not updated: break # 构造LR(1)项集族 start_item = LR1Item(productions[0], 0, '$') start_set = closure_lr1(set([start_item])) item_sets = [start_set] while True: new_sets = [] for item_set in item_sets: for symbol in terminals + non_terminals: goto_set = goto_lr1(item_set, symbol) if goto_set and goto_set not in item_sets + new_sets: new_sets.append(goto_set) if not new_sets: break item_sets += new_sets # 构造LR(1)分析表 action_table = {} goto_table = {} for i, item_set in enumerate(item_sets): for item in item_set: if item.dot_index == len(item.production): if item.production[0] == 'S': action_table[(i, '$')] = 'accept' else: for j, production in enumerate(productions): if item.production == production and item.lookahead in follow_table[production[0]]: action_table[(i, item.lookahead)] = ('reduce', j) elif item.production[item.dot_index] in terminals: goto_set = goto_lr1(item_set, item.production[item.dot_index]) if goto_set in item_sets: action_table[(i, item.production[item.dot_index])] = ('shift', item_sets.index(goto_set)) elif item.production[item.dot_index] in non_terminals: goto_set = goto_lr1(item_set, item.production[item.dot_index]) if goto_set in item_sets: goto_table[(i, item.production[item.dot_index])] = item_sets.index(goto_set) # 构造文法的FOLLOW集 follow_table = {} for non_terminal in non_terminals: follow_table[non_terminal] = set() follow_table[productions[0][0]] = set(['$']) while True: updated = False for production in productions: for i in range(len(production) - 1): if production[i] in non_terminals: old_follow_set = set(follow_table[production[i]]) if production[i + 1] in terminals: follow_table[production[i]] |= set([production[i + 1]]) elif production[i + 1] in non_terminals: follow_table[production[i]] |= first_table[production[i + 1]] if 'eps' in follow_table[production[i]]: follow_table[production[i]].remove('eps') follow_table[production[i]] |= follow_table[production[0]] if old_follow_set != follow_table[production[i]]: updated = True if production[-1] in non_terminals: old_follow_set = set(follow_table[production[-1]]) follow_table[production[-1]] |= follow_table[production[0]] if old_follow_set != follow_table[production[-1]]: updated = True if not updated: break # 对输入符号串进行分析 stack = [0] input_str = "( id + id ) * id $" input_index = 0 while True: state = stack[-1] lookahead = input_str[input_index] if (state, lookahead) in action_table: action = action_table[(state, lookahead)] if action == 'accept': print("该符号串是该文法可以识别的句子!") break elif action[0] == 'shift': stack.append(lookahead) stack.append(action[1]) input_index += 1 elif action[0] == 'reduce': production_index = action[1] production = productions[production_index] for i in range(2 * len(production)): stack.pop() new_state = stack[-1] stack.append(production[0]) stack.append(goto_table[(new_state, production[0])]) else: raise Exception("ERROR") else: raise Exception("ERROR") ``` 上述代码中,我们首先构造了LR(1)项集族,然后利用它构造了LR(1)分析表,最后利用LR(1)分析表对输入的符号串进行了分析。在分析过程中,我们使用了一个栈来模拟LR分析器的行为,不断地从栈中弹出符号并将新的符号压入栈中,直到遇到接受状态或者出现语法错误。

相关推荐

最新推荐

recommend-type

编译原理课程设计-LR(1)语法分析模拟构造器的设计

语法分析的主要任务是接收词法分析程序识别出来的单词符由某种号串,判断它们是否语言的文法产生,即判断被识别的符号串是否为某语法部分。 LR(k)分析法是给出一种能根据当前分析栈中的符号串,“k”是指为了作出...
recommend-type

华为OD机试D卷 - 用连续自然数之和来表达整数 - 免费看解析和代码.html

私信博主免费获取真题解析以及代码
recommend-type

Screenshot_2024-05-10-20-21-01-857_com.chaoxing.mobile.jpg

Screenshot_2024-05-10-20-21-01-857_com.chaoxing.mobile.jpg
recommend-type

数字图像处理|Matlab-频域增强实验-彩色图像的频域滤波.zip

数字图像处理|Matlab-频域增强实验-彩色图像的频域滤波.zip
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

实现实时数据湖架构:Kafka与Hive集成

![实现实时数据湖架构:Kafka与Hive集成](https://img-blog.csdnimg.cn/img_convert/10eb2e6972b3b6086286fc64c0b3ee41.jpeg) # 1. 实时数据湖架构概述** 实时数据湖是一种现代数据管理架构,它允许企业以低延迟的方式收集、存储和处理大量数据。与传统数据仓库不同,实时数据湖不依赖于预先定义的模式,而是采用灵活的架构,可以处理各种数据类型和格式。这种架构为企业提供了以下优势: - **实时洞察:**实时数据湖允许企业访问最新的数据,从而做出更明智的决策。 - **数据民主化:**实时数据湖使各种利益相关者都可
recommend-type

spring添加xml配置文件

1. 创建一个新的Spring配置文件,例如"applicationContext.xml"。 2. 在文件头部添加XML命名空间和schema定义,如下所示: ``` <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans
recommend-type

JSBSim Reference Manual

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

"互动学习:行动中的多样性与论文攻读经历"

多样性她- 事实上SCI NCES你的时间表ECOLEDO C Tora SC和NCESPOUR l’Ingén学习互动,互动学习以行动为中心的强化学习学会互动,互动学习,以行动为中心的强化学习计算机科学博士论文于2021年9月28日在Villeneuve d'Asq公开支持马修·瑟林评审团主席法布里斯·勒菲弗尔阿维尼翁大学教授论文指导奥利维尔·皮耶昆谷歌研究教授:智囊团论文联合主任菲利普·普雷教授,大学。里尔/CRISTAL/因里亚报告员奥利维耶·西格德索邦大学报告员卢多维奇·德诺耶教授,Facebook /索邦大学审查员越南圣迈IMT Atlantic高级讲师邀请弗洛里安·斯特鲁布博士,Deepmind对于那些及时看到自己错误的人...3谢谢你首先,我要感谢我的两位博士生导师Olivier和Philippe。奥利维尔,"站在巨人的肩膀上"这句话对你来说完全有意义了。从科学上讲,你知道在这篇论文的(许多)错误中,你是我可以依