Rust in Everything
基于 pulldown-cmark 0.13.5

行内解析

第一遍结束时,每个段落、标题、表格单元格里是一串节点:大部分是指向原文的 Text,夹着第一遍认不准的 Maybe* 占位。这一部分讲第二遍,也就是行内主线:Parser::next 走到占位时调 handle_inline,用两趟把这串节点就地改写成强调、链接、代码段,再交给 item_to_event 变成事件。例子文档里调了 6 次(一份文档)。

代码几乎都在 parse.rs(3044 行):两趟的主体 handle_inline_pass1 和 handle_emphasis_and_hard_break,以及它们用到的 InlineStack、LinkStack、CodeDelims、MathDelims;标签扫描在 linklabel.rs(173 行),实体和标点是生成的两张表 entities.rs、puncttable.rs。规则对照 CommonMark 0.31.2 规范的「Inlines」一章和附录里的参考算法,扩展对照 specs/ 下各自的文件。

  1. 按需解析:8 种占位从哪来、谁来解决;next 遇到占位才调 handle_inline,一次改写一条兄弟链,链接里的子链要再调一次;本站语料上第二遍每个节点只被看一两次。
  2. 强调与分隔符栈:左右侧在第一遍算好,InlineStack 从栈顶往下找、3 的倍数规则;9 个下界就是规范的 openers_bottom,关掉后病态输入变平方;#1155 补上的那个桶,中文标点紧贴 ** 的坑。
  3. 链接与图片:LinkStack 与「链接里不能有链接」,内联、完整、折叠、快捷四种写法,BrokenLinkCallback;括号层数、标签长度、展开预算三个上限的实测;脚注引用和 wikilink。
  4. 代码段、HTML、实体:CodeDelims 按长度记位置、HtmlScanGuard 记住失败的扫描;自动链接;实体在 2125 项的有序表上二分;反斜杠转义在第一遍就切开文本。
  5. 数学与智能标点:$ 的开闭规则和货币写法,花括号上下文与 25 层上限;连字符、省略号、引号在两遍里怎么分工。
flowchart TB
  nx["Parser next"] --> hi["handle_inline"]
  hi --> p1["handle_inline_pass1"]
  p1 --> code["代码段 CodeDelims"]
  p1 --> html["HTML 与自动链接"]
  p1 --> math["数学 MathDelims"]
  p1 --> link["链接 LinkStack"]
  hi --> p2["handle_emphasis_and_hard_break"]
  p2 --> emph["强调 InlineStack"]
  p2 --> quote["智能引号"]
  emph --> ev["item_to_event"]
  link --> ev

改写完的节点怎么变成事件、事件的范围怎么定,见事件模型;行内解析里哪些地方会分配字符串,见 CowStr。

💬 关联讨论

发起讨论
加载中...