parser combinator vs 递归下降:同一个文法,两种写法
combinator(组合子)= 一个「吃 parser、吐 parser」的高阶函数,自己不含解析逻辑,只负责把小 parser 拼成大 parser
(seq 顺序、alt 选择、many 重复…)。文法用「拼数据」声明出来。
递归下降 (recursive descent) 则相反:每条文法规则手写成一个函数,控制流(while/if/递归)自己写。
两条路殊途同归——产出同一棵 AST。下面这两个 toy 解析器都真在跑,改 pattern 看两边树是否一字不差。
. · | · 量词 * + ?(含惰性 *?)·
分组 ( ) / 非捕获 (?:)。没有字符类 / 锚点 / 转义 / 反向引用——那些本仓库的生产解析器(走的正是右边这种递归下降)都有,见 「解析引擎」那页。
parser combinator声明式 · 拼出来
递归下降命令式 · 手写控制流
AST 节点形状两边完全一致:Char / AnyChar / Concat / Alt /
Repeat{quant,greedy} / Group{capturing,#index}。捕获组编号 #1 #2… 由两边共用的一个
left-to-right 后处理 pass 按左括号顺序填(对齐 JS)。绿条 = 逐字段 deep-equal 通过。
两边的解析器长什么样
注意区别只在「怎么描述文法」:左边把 seq/alt/many 拼成数据,右边把同样的结构写成 while/if 与函数递归。
parser combinator (单子式 · 节选,完整版即本页脚本)声明式
递归下降 (节选,完整版即本页脚本)命令式
@vega/parsing/regex 的生产解析器选了右边的递归下降
(优先级分层、\1 反向引用的前向回填、精确错误位置都更顺手);而 combinator 这种写法,仓库里 action-grammar 已经有完整示范。