Context-Free Grammar(CFG,上下文无关文法)

<aside> 💡

**奇怪的类比:**假设 G 是 “人类” 这一物种的设计图。


**本质上:**CFG 的目的就是 把任意一句语法结构,展开成一个语法树(句 → 树)。具体做法是,从 $S$ 开始,对于每块代码 找到其对应的规则 $P_i$ ,然后识别出该规则中的 $T$ 和 $N$:

$$ G = (N, T, S, P) $$

  1. $G$ 具体是什么?
  2. $N$(Non-Terminal Symbol)是什么?
    1. $N$ 是语法中更抽象 high-level 的概念,可以继续被递归拆分,进一步解析
    2. 比如 <Statment> (语句),<Expression>(表达式),<Function>(函数)
  3. $T$(Terminal Symbol)是什么?
  4. $S$(Start Symbol)是什么?
  5. $P$(Productions)是什么?

CleanShot 2025-12-08 at 13.15.19@2x.png

CleanShot 2025-12-08 at 12.15.01@2x.png

<aside> ❓

为啥不用 Regular Expression → NFA → DFA 的解析思路?

因为 Regex 是一种有限状态自动机(只知道当前状态 没有存储),像马尔可夫链一样。这导致无法处理需要 计数、嵌套 的语法结构(比如括号需要左右匹配)。

而 CFG 对应的机器叫 PDA (Pushdown Automaton,下推自动机)。相比于 DFA,PDA 多了,从而解决了记忆的问题

</aside>

Regular 转 CFG

例子:

CleanShot 2025-12-08 at 12.26.12@2x.png

规则如下:

  1. 对每个状态 $i$,创建一个 nonterminal 状态 $A_i$
  2. 对状态转移 $i \xrightarrow{a} j$,创建对应的 $A_i \rightarrow a A_j$
  3. 对状态转移 $i \xrightarrow \epsilon j$ ,创建对应的 $A_i \rightarrow A_j$
  4. 假如状态 $i$ 有多条状态转移,则用|拼接
    1. 例如 $i\rightarrow j, i\xrightarrow ak$,创建 $A_i \rightarrow A_j|a A_k$