编译原理基础:LL(1) 文法与 LL(1) 分析法

编译原理基础:LL(1) 文法与 LL(1) 分析法

嗨!学编译原理是不是觉得有点像解谜游戏?今天我们要聊聊 LL(1) 文法和 LL(1) 分析法,这俩是编译器设计里的"预测大师",能让解析代码变得简单又高效。别怕,我会用大白话讲明白它们是啥,还会带点形式化的定义,帮你一步步搞懂!

LL(1) 文法:不纠结的文法

感性理解

想象你在做选择题,每个题目的开头都长得不一样,你一看就能知道选哪个答案,完全不用犹豫。LL(1) 文法就像这样的"完美选择题":编译器读到代码的某个符号,只看一眼(一个 token),就能立刻决定走哪条路解析,不用猜来猜去。简单说,它是让编译器"果断"的文法。

形式化表达

LL(1) 是一种上下文无关文法(CFG),名字里的意思是:

  • 第一个 L:从左到右扫描输入。
  • 第二个 L:用最左推导(leftmost derivation)。
  • 1:只看一个符号(lookahead 一个 token)就能决定用哪个产生式。

一个文法是 LL(1) 的,必须满足:

  1. 对于非终结符 A 的每个产生式 A → α | β,FIRST(α) 和 FIRST(β) 没有交集(开头不能撞车)。
  2. 如果 α 或 β 能推 ε(空串),则 FIRST(β) 或 FIRST(α) 不能和 FOLLOW(A) 有交集(空串时后续也不能冲突)。

例子:

css 复制代码
S → a S | b
  • FIRST(a S) = { a },FIRST(b) = { b },没交集,是 LL(1)。 但如果改成:
css 复制代码
S → a S | a T
  • FIRST(a S) = { a },FIRST(a T) = { a },有交集,就不是 LL(1)。

LL(1) 分析法:一步到位的解析

感性理解

LL(1) 分析法就像是拿着一个"导航表"开车。编译器一边读代码,一边查表,看到当前符号和栈顶的非终结符,就能立刻知道下一步是推导啥,还是跳过啥。整个过程干净利落,像玩拼图一样,步步到位,最后拼出整个程序。

形式化表达

LL(1) 分析法是一种自顶向下的预测分析法,用一个预测分析表(parsing table)和栈来解析输入。核心步骤:

  1. 构建预测分析表 :
    • 行是文法的非终结符,列是终结符(包括 $)。
    • 根据 FIRST 和 FOLLOW 集合填表:
      • 对于 A → α,若 t ∈ FIRST(α),表A, t = A → α。
      • 若 α 能推 ε,则对 t ∈ FOLLOW(A),表A, t = A → α。
  2. 解析过程 :
    • 用栈保存推导状态,从开始符号 S 入栈。
    • 读输入符号,栈顶如果是:
      • 终结符:匹配就弹出,继续读。
      • 非终结符:查表,替换成对应产生式。
    • 栈空且输入读完,解析成功。

例子: 文法:

css 复制代码
S → a S | b
  • FIRST(S → a S) = { a },FIRST(S → b) = { b }。

  • FOLLOW(S) = { $ }(假设 S 是开始符号)。

  • 预测分析表:

    a b $
    S S→aS S→b
  • 输入 "aab":

    • 栈:S,输入:aab$
    • 查表 S,a → S→aS,栈:a S,匹配 a,栈:S
    • 查表 S,a → S→aS,栈:a S,匹配 a,栈:S
    • 查表 S,b → S→b,栈:b,匹配 b,栈:\[\]
    • 输入读完,栈空,成功!

为啥 LL(1) 这么重要?

  • 简单高效:只看一个符号就能决定下一步,解析速度快。
  • 好实现:预测分析表直接告诉编译器怎么走,不用回溯。
  • 有限制但实用:虽然不是所有文法都是 LL(1),但通过提取公共左因子、消除左递归,可以改成 LL(1)。

小结

LL(1) 文法是"果断"的文法,保证编译器不纠结;LL(1) 分析法是"导航"的方法,让解析一步到位。它们靠 FIRST 和 FOLLOW 集合合作,FIRST 管开头,FOLLOW 管后续。试着自己写个小文法,建个分析表跑跑看,动手玩玩就更明白了!加油哦!

相关推荐
深蓝AI4 小时前
Python 3.13 的 Queue.shutdown:异步消费者终于能正常收工了
后端
武子康4 小时前
MultiNet6 空闲崩溃:`EXCVADDR=0x8` 后又出现 `CORRUPT HEAP`
人工智能·后端·agent
武子康5 小时前
MultiNet7 每轮都 clean,ESP32-P4 内存为什么还在掉?
人工智能·后端·agent
超级架构师6 小时前
PRAXO-CORE 2.5.0:用 conformance 和显式边界构建 Go Agent 框架
开发语言·人工智能·后端·golang·ai编程·智能体框架·praxo-core
陈随易6 小时前
AI 运维服务器,安全又可靠的方法
前端·后端·程序员
IT_陈寒8 小时前
JavaScript的this坑人实录,这次我真的记下来了
前端·人工智能·后端
starzy19909 小时前
Scala类和对象:从构造器到样例类的完整指南
开发语言·后端·scala
梦影_9 小时前
MySQL进阶教程(五)—— SQL调优(下)
android·大数据·数据库·后端·sql·mysql·database
考虑考虑9 小时前
mariadb数据库
数据库·后端·mariadb
明月_清风9 小时前
用自然语言操控真机:Google Artemis 移动端 AI Agent 上手与实践
人工智能·后端