ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

ctags 解析 reStructuredText 替换定义(Substitution Definition):从 substdef.d 测试用例到 parsers/rst.c 实现剖析

ctags 解析 reStructuredText 替换定义(Substitution Definition):从 substdef.d 测试用例到 parsers/rst.c 实现剖析 开发工具CLI【免费下载链接】ctagsA maintained ctags implementation项目地址https://gitcode.com/gh_mirrors/ct/ctags点击查看免费下载reStructuredTextreST中的替换定义substitution definition是文档写作中常用的宏机制而 ctags 的 ReStructuredText 解析器会将其识别为一种独立的 tag 种类kind。本文以仓库内 substdef.d 测试用例 为骨架结合 parsers/rst.c 源码逐层讲解 ctags 如何识别.. |name| replace:: ...形式的替换定义、如何为它生成 tag以及如何通过 Units 测试体系复现与验证这一行为。读完本文你将能够理解 ctags 中 ReStructuredText 解析器的整体结构、substdef 种类的定位与字段体系并能独立运行测试、扩展或排查相关解析问题。一、reStructuredText 替换定义语法回顾在 reStructuredText 中替换定义substitution definition的语法是显式标记explicit markup的一种标准形式为.. |替换名| replace:: 替换内容其中..是显式标记的前缀|替换名|是替换名substitution namereplace::指明替换指令。定义之后文档正文中凡是出现|替换名|的位置都会在渲染时被替换为指定内容。这类结构常被用来定义术语缩写、版权符号、跨文档复用的超链接等。本文核心的测试输入文件 substdef.d/input.rst 正是这一语法的典型样例其内容取自 Linux 内核文档Documentation/admin-guide/pm/cpuidle.rst的片段.. SPDX-License-Identifier: GPL-2.0 This text is partially taken from Documentation/admin-guide/pm/cpuidle.rst of Linux kernel. .. include:: isonum.txt .. |struct cpuidle_state| replace:: :c:type:struct cpuidle_state cpuidle_state .. |cpufreq| replace:: :doc:CPU Performance Scaling cpufreq CPU Idle Time Management :Copyright: |copy| 2018 Intel Corporation :Author: Rafael J. Wysocki rafael.j.wysockiintel.com这份输入文件里实际包含了多种 reST 结构注释SPDX 头、.. include::指令引用 docutils 的isonum.txt、两条替换定义、一个带 overline/underline 的文档标题以及两个文档字段field list。ctags 会从中识别出哪些 tag正是本测试用例要回答的问题。二、测试用例全景input.rst、args.ctags 与 expected.tagsUnits 测试目录下每个用例由三部分组成输入文件、运行参数、期望输出。substdef 用例的文件都在 Units/parser-restructuredtext.r/substdef.d/ 下。1. 运行参数args.ctagsargs.ctags 只有一行--sortno它指示 ctags 关闭 tag 排序按输入文件中的出现顺序输出便于与期望文件逐行对比。这是 Units 测试最常见的参数之一。2. 期望输出expected.tagsexpected.tags 给出了 ctags 对上述输入的处理结果struct cpuidle_state input.rst /^.. |struct cpuidle_state| replace:: :c:type:struct cpuidle_state cpuidle_state$/; d cpufreq input.rst /^.. |cpufreq| replace:: :doc:CPU Performance Scaling cpufreq$/; d CPU Idle Time Management input.rst /^CPU Idle Time Management$/; H逐行解读这个结果字段含义第一列tag 名即替换名或标题文本第二列源文件路径这里统一为输入文件input.rst第三列tag 的定位命令pattern即匹配源行的正则表达式第四列;之后kind 字母d表示替换定义substdefH表示文档标题title可以看到.. |struct cpuidle_state| replace:: ...被识别为名为struct cpuidle_state的 substdefkindd.. |cpufreq| replace:: ...被识别为名为cpufreq的 substdefkinddCPU Idle Time Management被识别为文档标题kindH。而文件中的.. SPDX-License-Identifier:注释、.. include:: isonum.txt指令、:Copyright:/:Author:字段列表都不会产生 tag——它们不在解析器的捕获范围内。3. 为什么只产生三个 taginclude 指令的影响输入中使用了|copy|在:Copyright: |copy| 2018 Intel Corporation中但该替换定义并未出现在本文件中而是来自.. include:: isonum.txt所引用的外部文件。ctags 的 reST 解析器不展开 include 指令、不读取被包含的文件因此|copy|在本文件内没有对应定义自然不会生成 substdef tag。这也解释了为什么期望输出中只有本地定义的两条替换struct cpuidle_state、cpufreq——这正是该用例设计上要验证的边界行为。三、解析器视角RstKinds 种类表与 substdef 的定位替换定义的识别只是整个 ReStructuredText 解析器功能的一部分。解析器定义位于 parsers/rst.c其种类表RstKinds共定义 9 个 kindparsers/rst.ckind 字母名称描述Htitle文档标题hsubtitle副标题cchapter章ssection节Ssubsection小节tsubsubsection子小节Ccitation引用Ttarget目标超链接锚点dsubstdef替换定义substitute definitions对应的枚举parsers/rst.c中K_SUBSTDEF排在K_CITATION之后、SECTION_COUNT之外说明它和 citation、target 一样属于「非层级」的辅助 tag不参与章节嵌套层级nesting level的计算。在 findRstTags 主循环 中每一行都会先尝试匹配三类显式标记.. _target:→ targetparsers/rst.c.. [citation]→ citationparsers/rst.c.. |substdef|→ substdefparsers/rst.c。三个分支共用同一个前缀检测函数 is_markup_line_with_char只有当一行的前四个字符恰好是..点、点、空格且第五个字符为指定类型标记_、[、|时才命中。这正是.. include::、:Copyright:等行被跳过的直接原因——它们的前缀不符合该模式。四、capture_markup替换定义捕获的底层实现三条显式标记分支最终都调用 capture_markup 完成名称提取与 tag 生成。以 substdef 为例调用方式为capture_markup (markup_line, |, K_SUBSTDEF)其中markup_line指向.. |之后的第一个字符|是默认终止符defaultTerminatorK_SUBSTDEF是目标 kind。1. 名称起止规则函数先判断名称的起始方式parsers/rst.c若起始字符是反引号则终止符为反引号允许捕获带空格的名称如.. |section target0|这类写法否则若起始字符是非空白、非空字符则按 docutils 的「简单引用名」规则捕获单个词字母数字加内部连字符、下划线、句点、冒号、加号不允许空白终止符使用默认值|若起始即空白或空字符则直接放弃goto out。2. 转义处理名称捕获循环内部处理了反斜杠转义parsers/rst.c遇到\时连同转义字符本身一起放入名称后续字符原样追加。因此替换名中的\:会被保留这与 target 用例中.. _INCLUDING \: in name:的处理方式一致。3. 生成 tag名称非空时函数调用 makeTargetRstTag 生成 tag并尝试从当前 nesting level 取出scopeIndex作为作用域scope。在 substdef.d 用例中两条替换定义都出现在标题之前此时嵌套栈为空因此输出中没有 scope 字段。五、运行与验证复现 substdef 测试结果1. 手工复现用仓库构建出的ctags可执行文件对输入文件执行与测试参数一致的命令ctags --optionsNONE --sortno -o - Units/parser-restructuredtext.r/substdef.d/input.rst即可得到与 expected.tags 一致的三行输出。--optionsNONE用于隔离用户配置文件的影响保证结果只由解析器决定。2. 通过 Units 测试框架运行ctags 的测试体系支持按语言筛选运行。在完成构建后可以执行make units LANGUAGESReStructuredText它会遍历 Units/parser-restructuredtext.r/ 下的全部用例包括 substdef.d读取各自的args.ctags与expected.tags并逐一比对。若解析行为与期望不符测试会给出 diff 供定位。3. 兄弟用例与字段验证substdef.d 只是 ReStructuredText 测试集的一员同目录下的其他用例分别覆盖了不同语法面可互为参照simple-restructuredtext.d纯章节标题嵌套验证 chapter/section/subsection/subsubsection 的层级与sectionMarker字段target-restructuredtext.d.. _target:锚点识别与作用域归属citation.d.. [citation]引用的识别以及 overline 风格标题的overline:字段title.d、code-blocks.d标题等级调整与代码块内 guest 语言解析。例如在 citation.d 的期望输出中可以看到.. [atomic-ops]被识别为Ccitation且带有chapter:References作用域这有助于理解显式标记类 tag 的 scope 归属规则与 substdef 用例的差异。六、解析器的附加能力字段、代码块与章节等级调整虽然 substdef 用例本身不涉及但了解这些能力有助于理解expected.tags中为何某些字段出现、某些不出现解析器字段RstFields定义了两个字段parsers/rst.c——sectionMarker声明章节所用的字符如、-、*、~与overline是否使用上划线下划线声明章节布尔类型。二者默认关闭enabled false只有通过--fieldsK之类选项开启后才会出现在输出中substdef.d 的期望输出未开启字段因此看不到它们。章节等级调整reST 的标题等级由「首次出现的标记字符顺序」决定解析器通过sectionTracker记录每个标记字符首次出现的顺序并在收尾阶段用 adjustSectionKinds 统一调整。文档只有一个标题时它保持Htitle这正是 substdef.d 中CPU Idle Time Management被标为H而非cchapter的原因而 citation.d 中出现多个同标记标题时等级会相应提升。guest 语言解析当启用--extrasgguest时.. code-block:: language块内的代码会交给对应语言的解析器以 promise 机制二次解析见 parsers/rst.c 的submit_codeblock。该机制默认关闭这也是 substdef.d 输出中不出现任何代码块 tag 的前提之一。此外仓库文档 docs/README.md 中关于 reStructuredText Markup Rules 的说明章节标记使用、-、~等反引号与双反引号的含义区别与上述实现相互印证可作为阅读本文时的补充参考。七、小结替换定义的识别链路将本文内容串成一条完整的识别链路findRstTags逐行读取输入遇到形如.. |的行is_markup_line_with_char 判定调用capture_markup(markup_line, |, K_SUBSTDEF)捕获替换名处理反引号名称、简单词名称与转义通过makeTargetRstTag生成 kind 为dsubstdef的 tag并视嵌套栈情况附加 scope遇到.. include::、注释、字段列表等非目标结构时直接跳过不展开外部文件文件结束时调整章节等级并内联 scope输出最终 tag 列表。这一实现既保证了替换定义这类「文档宏」能被 Vim/Emacs 等编辑器跳转索引又通过 Units 测试用例substdef.d 及其兄弟用例固化了行为边界为后续维护与扩展提供了可回归验证的基准。若需深入建议继续阅读 parsers/rst.c 全文并结合 simple-restructuredtext.d 与 citation.d 的期望输出逐行对照。赞分享开发工具CLI【免费下载链接】ctagsA maintained ctags implementation项目地址https://gitcode.com/gh_mirrors/ct/ctags点击查看免费下载相关推荐ctags ReStructuredText 标题解析与测试用例解析从 section 层级识别到 scope 追踪ctags ReStructuredText 标题解析与测试用例解析从 section 层级识别到 scope 追踪 reStructuredTextreS开发工具CLIPandoc 定义列表Definition Lists语法详解从命令行测试用例到 Markdown 解析器实现Pandoc 定义列表Definition Lists语法详解从命令行测试用例到 Markdown 解析器实现 导读 test/command/10889文档开发工具CLIPandoc reStructuredText 的 csv-table 指令深度解析从命令测试用例到源码实现Pandoc reStructuredText 的 csv table 指令深度解析从命令测试用例到源码实现 Pandoc 作为通用标记格式转换器Unive文档开发工具CLI上一篇React-Amap 终极指南10分钟快速上手高德地图React组件下一篇探秘高效的软件管理工具 —— asdf 插件仓库创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表