编译原理基础:FIRST 集合与提取公共左因子

编译原理基础:FIRST 集合与提取公共左因子

嗨!如果你正在学编译原理,可能会觉得有些概念听起来很高大上,比如 FIRST 集合和提取公共左因子。别担心,今天我们就来聊聊这两个东西,用简单的话讲明白它们是什么,以及为什么它们在编译器设计里很重要。

FIRST 集合:从哪开始?

感性理解

想象你在写一个程序,编译器得搞清楚你的代码从哪里开始解析。比如你写了个表达式,编译器得知道第一个符号可能是啥------是数字?变量?还是括号?这个"第一个可能出现的符号"的集合,就是 FIRST 集合。简单来说,它就像是编译器的小抄,告诉它:"嘿,这串代码开头可能是这些东西哦!"

形式化表达

在文法里(比如上下文无关文法),FIRST 集合是针对某个非终结符(non-terminal)或产生式,计算出它能推导出的字符串的第一个终结符(terminal)的集合。

定义一下:

  • 对于文法中的非终结符 A,FIRST(A) 就是所有从 A 推导出的字符串的第一个终结符的集合。
  • 如果 A 能推导出空串 ε,那么 ε 也算在 FIRST(A) 里。

举个例子:

假设有文法:

r 复制代码
E → T + E | T  
T → id | ( E )  
  • FIRST(T) 是啥?T 可以推导出 "id" 或 "( E )",所以 FIRST(T) = { id, ( }。
  • FIRST(E) 呢?E 可以推导出 T 开头的东西,所以 FIRST(E) = FIRST(T) = { id, ( }。

这个集合的作用是啥?它帮编译器在预测式分析(比如 LL(1) 文法)里快速判断下一步该走哪条路。

提取公共左因子:让文法更"干净"

感性理解

假设你在写代码,编译器看到你写的语句开头老是重复,比如"if (条件) ..." 和 "if (条件) ...",它会觉得有点晕:这两条路开头一样,咋分啊?提取公共左因子就像是把这些重复的开头抽出来,整理一下,让编译器更容易看懂你的文法。

形式化表达

在文法里,如果一个非终结符的多个产生式有相同的开头(公共左因子),就会导致解析时出现二义性。提取公共左因子的方法是把这些公共部分抽出来,变成一个新的产生式,剩下的部分单独处理。

比如:

css 复制代码
A → α β1 | α β2  

这里 α 是公共左因子,可以改成:

css 复制代码
A → α A'  
A' → β1 | β2  

举个例子:

假设有文法:

bash 复制代码
S → id = E | id + T  

两个产生式都以 "id" 开头,提取公共左因子后变成:

bash 复制代码
S → id S'  
S' → = E | + T  

这样,编译器看到 "id" 就知道先走 S,然后再看后面是 "=" 还是 "+",一步步解析就清晰多了。

为什么这两个东西重要?

  • FIRST 集合:它是预测式语法分析的核心工具,帮助编译器快速决定从哪个产生式开始推导,避免瞎猜。
  • 提取公共左因子:它能消除文法中的二义性,让编译器解析时不"撞车",特别在 LL(1) 文法里很关键。

小结

FIRST 集合像是文法的"导航仪",告诉编译器每一步可能的方向;提取公共左因子像是"整理大师",把乱糟糟的文法收拾得井井有条。学编译原理的时候,这俩是基础中的基础,理解了它们,你就离写一个自己的编译器更近一步啦!下次我们再聊聊 FOLLOW 集合和怎么用这些工具做预测分析,加油哦!

相关推荐
Pr Young13 分钟前
go build命令
后端·golang
数据知道15 分钟前
Go语言:Go 语言中的命令行参数操作详解
开发语言·后端·golang·go语言
代码匠心22 分钟前
从零开始学Flink:实时流处理实战
java·大数据·后端·flink
hui函数43 分钟前
Python全栈(基础篇)——Day05:后端内容(dict与set+while循环+for循环+实战演示+每日一题)
开发语言·后端·python
Apifox.1 小时前
Apifox 9 月更新| AI 生成接口测试用例、在线文档调试能力全面升级、内置更多 HTTP 状态码、支持将目录转换为模块
前端·人工智能·后端·http·ai·测试用例·postman
绝无仅有2 小时前
消息队列mq面试经典问题与解答总结
后端·面试·github
绝无仅有2 小时前
数据库mysql报错追踪与解决总结
后端·面试·github
Codelinghu2 小时前
快速入门SpringAI-SpringAI Alibaba实战
后端
ZhengEnCi2 小时前
@Component 注解完全指南-从入门到精通的 Spring 核心组件管理
spring boot·后端
Penge6663 小时前
MySQL-隐式类型转换的 “隐形陷阱”
后端·mysql