news 2026/7/13 6:09:04

上下文无关文法 (CFG) 实战:3步构建无二义性四则运算语法树

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
上下文无关文法 (CFG) 实战:3步构建无二义性四则运算语法树

上下文无关文法实战:三步构建无二义性四则运算语法树

在编程语言和数学表达式处理中,上下文无关文法(CFG)扮演着至关重要的角色。它不仅是编译原理的理论基础,更是解决实际语法解析问题的利器。本文将以四则运算表达式为例,展示如何设计无二义性的CFG,并通过Python代码实现语法树的构建。

1. 理解上下文无关文法基础

上下文无关文法由四个部分组成:

  • 终结符(Terminals):构成语言基本元素的符号,如数字、运算符
  • 非终结符(Non-terminals):表示语法结构的变量
  • 产生式规则(Productions):定义非终结符如何展开
  • 开始符号(Start symbol):语法分析的起点

四则运算的简单文法可能如下:

Expr → Expr + Term | Expr - Term | Term Term → Term * Factor | Term / Factor | Factor Factor → ( Expr ) | number

这种分层结构有效解决了运算符优先级问题:

  • Factor处理括号和基本单元
  • Term处理乘除运算
  • Expr处理加减运算

2. 消除二义性的关键技巧

原始文法E → E + E | E * E | (E) | number存在二义性,无法确定运算顺序。通过引入层级结构消除二义性:

# 优先级从低到高分层 grammar = { 'Expr': [['Expr', '+', 'Term'], ['Expr', '-', 'Term'], ['Term']], 'Term': [['Term', '*', 'Factor'], ['Term', '/', 'Factor'], ['Factor']], 'Factor': [['(', 'Expr', ')'], ['number']] }

结合性处理方案

  • 左递归实现左结合(如Expr → Expr + Term
  • 右递归实现右结合(如Expr → Term + Expr

3. Python实现语法树构建

以下是完整的语法解析器实现:

import re class TreeNode: def __init__(self, value): self.value = value self.children = [] def add_child(self, node): self.children.append(node) def __str__(self, level=0): ret = " " * level + repr(self.value) + "\n" for child in self.children: ret += child.__str__(level+1) return ret class Parser: def __init__(self, expression): self.tokens = re.findall(r'\d+|[()+*/-]', expression) self.current_token = None self.next_token() def next_token(self): if self.tokens: self.current_token = self.tokens.pop(0) else: self.current_token = None return self.current_token def parse(self): tree = self.parse_expr() if self.current_token is not None: raise SyntaxError("Unexpected token") return tree def parse_expr(self): node = self.parse_term() while self.current_token in ('+', '-'): op = self.current_token self.next_token() right = self.parse_term() new_node = TreeNode(op) new_node.add_child(node) new_node.add_child(right) node = new_node return node def parse_term(self): node = self.parse_factor() while self.current_token in ('*', '/'): op = self.current_token self.next_token() right = self.parse_factor() new_node = TreeNode(op) new_node.add_child(node) new_node.add_child(right) node = new_node return node def parse_factor(self): if self.current_token == '(': self.next_token() node = self.parse_expr() if self.current_token != ')': raise SyntaxError("Expected ')'") self.next_token() return node elif self.current_token.isdigit(): node = TreeNode(self.current_token) self.next_token() return node else: raise SyntaxError("Unexpected token") # 示例使用 expression = "(1+2)*3" parser = Parser(expression) syntax_tree = parser.parse() print(syntax_tree)

输出结果示例

'*' '+' '1' '2' '3'

4. 文法设计与调试技巧

常见问题排查表

问题现象可能原因解决方案
无法识别括号表达式Factor规则未正确定义检查Factor → ( Expr )规则
运算符优先级错误层级结构不正确确保乘除在加减上层
右结合变成左结合递归方向错误将左递归改为右递归

扩展支持更多运算符

# 添加指数运算(右结合) grammar['Term'].append(['Factor', '^', 'Term'])

通过这种结构化方法,我们可以逐步构建复杂的语法解析器,同时保持代码的可维护性和扩展性。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/13 6:05:58

UE5蓝图性能优化实战:事件委托与对象池消除卡顿

1. 项目概述:为什么蓝图优化是UE5项目的必修课 在虚幻引擎5(UE5)项目中,蓝图视觉化脚本以其直观、高效的特点,成为了快速原型开发和中小型项目的主力。然而,随着项目规模的扩大和逻辑复杂度的提升&#xff…

作者头像 李华
网站建设 2026/7/13 6:03:41

OWASP ZAP 2.15.0 API 自动化测试:Python 脚本集成 CI/CD 实现 5 分钟扫描

OWASP ZAP 2.15.0 API 自动化测试:Python 脚本集成 CI/CD 实现 5 分钟扫描在当今快速迭代的软件开发环境中,安全测试往往成为流程中的瓶颈。传统手动渗透测试需要数小时甚至数天,而自动化安全扫描工具 OWASP ZAP 的 API 功能配合 Python 脚本…

作者头像 李华
网站建设 2026/7/13 6:02:01

MBR vs GPT分区表对比:2TB容量限制与4KiB对齐的5个核心差异点

MBR与GPT分区表深度对比:从2TB限制到4K对齐的五大技术分野当一块全新的硬盘首次接入计算机时,操作系统看到的是一片未经划分的存储空间。分区表就像这块"白纸"上的网格线,决定了数据如何被有序组织。在当前的存储技术中&#xff0c…

作者头像 李华
网站建设 2026/7/13 5:58:58

FTP 21端口渗透工具对比:Hydra vs Medusa vs Metasploit 3种爆破效率实测

FTP 21端口安全测试工具深度评测:Hydra、Medusa与Metasploit实战对比当我们需要评估FTP服务器的安全性时,密码爆破测试是不可或缺的一环。作为渗透测试人员,选择合适的工具往往能事半功倍。本文将基于实际测试环境,对三款主流FTP爆…

作者头像 李华
网站建设 2026/7/13 5:56:40

现代C++性能优化实战:从基础技巧到高级内存与并发优化

1. 项目概述:为什么现代C性能优化是门必修课?干了这么多年C,从嵌入式设备到大型服务器,我最大的感触是:性能优化不是锦上添花,而是基本功。尤其是在C17标准普及的今天,编译器、标准库和语言特性…

作者头像 李华
网站建设 2026/7/13 5:56:17

多维聚合中的数据操作:从维度对齐到稀疏填充的五步实战

1. 项目概述:为什么多维聚合中的数据操作不是“加个GROUP BY”就能搞定的“Part 20: Data Manipulation in Multi-Dimensional Aggregation”——这个标题乍看像教科书里一个平平无奇的章节编号,但我在银行风控建模组带新人时,常拿它当“压力…

作者头像 李华