编译原理基础: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 管后续。试着自己写个小文法,建个分析表跑跑看,动手玩玩就更明白了!加油哦!

相关推荐
码兄科技21 小时前
实战:基于Spring Boot + UniApp的地理信息小程序开发
spring boot·后端·uni-app
腾讯云云开发1 天前
腾讯云 CloudBase 登上 WAIC:我们为 Agent 重新设计了云的生产线
后端
星栈1 天前
从装一堆工具到看懂 Node 工程化思维:我的项目复盘记录
后端·node.js
65岁退休Coder1 天前
LangChain v1.3.4 笔记 - 05 Agent 上下文记忆
后端
颜酱1 天前
04 | 召回前置准备:搭好召回所需的四个数据库
前端·人工智能·后端
JaneConan1 天前
鸿蒙 韶非 UI 系列:能力调用 startAbilityForResult,跳能力拿回参,鸿蒙能力路由入门
后端·harmonyos
晴空了无痕1 天前
从 Go 基础到 K8s:一条可落地的 Go 服务端成长路线
开发语言·后端·golang·kubernetes
用户8356290780511 天前
如何使用 Python 在 Excel 中添加、编辑和删除超链接
后端·python
花椒技术1 天前
原本要 2 天的服务端冒烟前置审查,为什么 3 分半就能出报告?|QA 质量交付实践(三)
后端·ai编程·测试
达达尼昂1 天前
AI 编程的工程化实践:Flutter AI Harness 的设计与落地
人工智能·后端·全栈