python语法分析器(parser)源码阅读(一)

从官方网站上下载了python3.7.9的源代码,准备这几天看一下python的语法分析器。

本来我以为会有很多东西,没想到打开了parser这个文件夹之后,发现才有14个文件(c语言的文件),其中有2个头文件,12个源文件。

注:阅读这一部分的源码,搭配《编译原理》更佳。

我准备从自顶向下的顺序进行分析:

文件包含关系

1.头文件

  • parser.h                定义了几个语法分析器有关的数据结构,以栈的形式存储语法分析器
  • tokenizer.h           里面主要写了一个结构体tok_state ,记录着源代码(你写的python代码)的很多东西

2.源文件

  • acceler.c               语法分析器加速模块
  • bitset.c                  被解析器使用的bitset原语
  • firstsets.c              FIRST集的代码实现(详见《编译原理》4.4.2)   
  • grammar.c            语法实现
  • grammar1.c          被parser所需要的语法子程序
  • listnode.c              在文件(stdout,即输出)中列举一些节点
  • metagrammar.c    定义了一堆变量,暂没看懂啥意思。
  • myreadline.c        获取输入的地方,调用的ReadConsoleW这个API来获取输入
  • node.c                 语法分析树节点实现
  • parser.c               语法分析器实现
  • parsetok.c           语法分析与词法分析的沟通桥梁
  • tokenizer.c           词法分析器

有些文件解释的不是很理想,但是并无伤大雅,接下来我会更深入的分析里面的函数与数据结构。

接下来供上结构图,仅包含parser中的文件。

 

 

LR语法分析器种自底向上的解析方法,广泛应用于编译器设计中。以下是关于LR语法分析器实现的些详细说明: ### LR Parser 的基本原理 LR 解析器的核心在于通过状态转换图来识别输入字符串是否符合给定的上下文无关文法。它主要依赖于项目集族(Item Set Family)、动作表(Action Table)以及跳转表(Goto Table)。这些表格可以通过SLR(1),LR(0),LR(1) 或者 LALR(1) 方法构建[^5]。 #### 动作表和跳转表的作用 - **动作表**:定义了解析过程中遇到不同符号时应该采取的动作,可能的操作包括移入(shift)、规约(reduce)、接受(accept)或者报错(error)。 - **跳转表**:用于指导当读取到非终结符时如何切换当前的状态。 ### 实现示例 下面是个简单的 Python 版本的 SLR(1) 解析器框架,展示了如何基于预计算好的 Action 和 Goto 表格执行解析过程: ```python class LRParser: def __init__(self, action_table, goto_table, grammar_rules): self.action_table = action_table self.goto_table = goto_table self.grammar_rules = grammar_rules def parse(self, input_tokens): stack = [0] symbols = ['S'] # Start symbol index = 0 while True: state = stack[-1] token = input_tokens[index] if index < len(input_tokens) else '$' action = self.action_table.get((state, token), None) if not action: raise Exception(f"Parsing error at {token}") act_type, value = action if act_type == 's': # Shift operation stack.append(value) symbols.append(token) index += 1 elif act_type == 'r': # Reduce operation lhs, rhs = self.grammar_rules[value] for _ in range(len(rhs)): stack.pop() symbols.pop() new_state = stack[-1] next_state = self.goto_table[(new_state, lhs)] stack.append(next_state) symbols.append(lhs) elif act_type == 'acc': print("Parsing successful!") break return "Success" # Example usage with predefined tables and rules. action_table_example = { (0,'id'): ('s',2), (0,'$'): ('acc',None), (1,'+'): ('s',3), (1,'$'): ('r',( 'E',['T','+','E'] )), ... } goto_table_example = { (0,'E'): 1, (0,'T'): 4, ... } rules_example = [ ('E', ['T']), ('E', ['T', '+', 'E']), ('T', ['F']), ('T', ['F', '*', 'T']), ('F', ['(', 'E', ')']), ('F', ['id']) ] parser = LRParser(action_table=action_table_example, goto_table=goto_table_example, grammar_rules=rules_example) input_string = ["id", "+", "id", "$"] result = parser.parse(input_string) print(result) ``` 此代码片段仅作为概念验证,并未包含完整的 Action/Goto 表格填充逻辑。实际应用需根据具体文法规则生成相应表格[^6]。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值