编译原理基础: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 集合和怎么用这些工具做预测分析,加油哦!

相关推荐
Asthenia04129 分钟前
面试官问我:你写代码会复用公共SQL么?
后端
Asthenia041221 分钟前
为什么把私钥写在代码里是一个致命错误
后端
程序员一诺27 分钟前
【Flask开发】嘿马文学web完整flask项目第2篇:2.用户认证,Json Web Token(JWT)【附代码文档】
后端·python·flask·框架
Asthenia041231 分钟前
如何在 Java 中正确判空 BigDecimal 等数据类型
后端
冷琅辞44 分钟前
Swift语言的跨平台开发
开发语言·后端·golang
Asthenia04121 小时前
Pandas期末备考:常见问题解析
后端
今夜有雨.1 小时前
使用C++实现HTTP服务
开发语言·网络·c++·后端·网络协议·tcp/ip·http
东方苾梦1 小时前
Lua语言的安全开发
开发语言·后端·golang
Asthenia04121 小时前
Spring Boot @Conditional 注解分析与实际业务场景应用
后端
慕离桑1 小时前
HTML语言的数据可视化
开发语言·后端·golang