
Carbon 语言注释语法完全指南//行注释与行尾注释的词法规则、样式与实践【免费下载链接】carbon-langCarbon Languages main repository: documents, design, implementation, and related tools. (NOTE: Carbon Language is experimental; see README)项目地址: https://gitcode.com/GitHub_Trending/ca/carbon-langCarbon 语言Carbon Language的注释系统只有一种词法元素以//开头、持续到行尾的行注释同时支持整行注释与行尾注释trailing comment并刻意不提供块注释。本文以 comments.md 为核心结合其背后两份正式提案p000198-comments.md 与 p007441-trailing-comments.md以及词法器源码完整讲解注释的语法规则、保留语法空间、样式建议、词法实现原理与测试验证方式帮助你写出符合 Carbon 规范、可被工具链正确解析的注释并理解其设计动机。注释的整体定义在 Carbon 中注释comment是一种词法元素以字符//开头一直延续到当前行末尾。Carbon 没有物理续行机制因此注释行末尾的反斜杠\不会把注释延续到下一行。这一点与 C/C 中// ... \可以续行的行为不同// This is a comment and is ignored. \ This is not a comment.上面例子中\之后的内容This is not a comment.会被当作普通代码处理而不是注释的一部分因为它位于行尾之后的新行上。从使用形态上注释可以分成两种整行注释full-line comment注释占据整行内容通常用于引出其下方将要出现的代码行尾注释trailing comment注释位于同一行其他内容之后用于标注该行自身的内容。词法细节//之后的空白要求Carbon 对注释提出了一条硬性词法规则//之后的第一个字符必须是空白字符whitespace。换行newline本身也是空白字符所以一行只包含//的情况是合法注释文件结束符end of file同样被视为空白因此文件末尾的//也是合法注释。反之//之后没有空白字符的写法例如//rejected是非法注释会触发词法错误NoWhitespaceAfterCommentIntroducerwhitespace is required after //该诊断定义于 lex.cppvar x: i32 0; //rejected: whitespace is required after //所有注释都在 token 形成之前被移除注释本身不产生任何 token。这意味着注释不会进入语法分析阶段纯注释行在语法上等价于空白行。这一点在词法器源码中有明确体现注释由专门的LexComment处理器消费直接推进到行尾不经过 token 生成路径见 lex.cpp。保留注释reserved comments//后无空白的语法空间//之后没有空白字符的序列被保留给未来扩展。设计团队预见到未来可能新增的注释形态包括块注释block comments文档注释documentation comments代码折叠区域标记code folding region markers。之所以要保留这一语法空间是因为它易于让程序主动避开——只要所有现有的合法注释都强制要求//后跟空白未来新增注释种类就可以作为非破坏性变更加入语言而不会与已有代码冲突。这也解释了为什么//rejected是错误而非单纯的普通注释它属于尚未定义的保留语法详见 p000198-comments.md。不支持块注释大段注释与禁用代码的处理方式Carbon目前不支持块注释。如果要注释掉较大范围的人类可读文本或代码唯一的方式是给区域内每一行都加上//前缀。这一决策背后有明确的理性考量见 p000198-comments.mdC/C 风格的/* ... */块注释不嵌套可能被//注释或字符串字面量中出现的*/提前终止无法可靠地用于注释掉一段代码#if 0 ... #endif需要文本之间是大体合法的 token 序列无法容纳不完整代码且 Carbon 不打算引入一般意义上的预处理器发明全新语法的成本很高而禁用代码是短暂且罕见的用例用行注释逐行注释虽然繁琐但恰好可以作为一次实验观察这种摩擦是否足以证明引入新注释形态的必要性。因此代码禁用场景通过逐行注释、必要时对单行内片段做重排或复制来解决。样式指南整行注释与行尾注释的分工整行注释和行尾注释服务于不同目的Carbon 给出的样式指导是见 comments.md文档性说明优先使用整行注释它受行长line-length压力的影响更小且当被描述的代码发生变化时更容易保持与代码的关联行尾注释仅用于标注或标记特定一行当把注释放到上一行会显得别扭、冗长或不精确时才使用行尾注释。两者可以自然共存一个典型示例// Compute the smallest prime factor. var factor: i32 SmallestFactor(n); // TODO: i32 - i64这里整行注释引出代码意图行尾注释标注了具体的后续工作项。行尾注释trailing comments从实验性限制到正式特性值得说明的是行尾注释并非 Carbon 一开始就支持的特性。p000198-comments.md 最初规定注释必须独占一行行内//之前不允许出现其他内容并明确将其标记为实验性决定等待完整语言设计的经验反馈。后来 p007441-trailing-comments.md 移除了这一限制允许注释跟随同一行的其他内容其余规则以//开头、//后必须有空白、延续到行尾、仍只有行注释全部保持不变。促成这一转变的三个观察短注释annotation需求行尾注释非常适合附着在某个具体实体或值上的短标注在示例、演示和讨论代码时尤其有用词法器成本反转当词法器采用表驱动分发后识别行尾注释几乎零成本反而是拒绝行尾注释需要额外的检查逻辑详见下文源码分析C 迁移需求C 代码中行尾注释无处不在允许它意味着迁移代码时可以原样保留布局而不是重排每一条注释。这一变更只把此前非法的程序变为合法对已有代码零迁移成本属于严格的放松式变更支撑了 Carbon 的软件与语言演进目标见 p007441-trailing-comments.md。词法规则统一行尾注释与整行注释在词法上完全一致以//开头、//后必须有空白换行与文件末尾算空白、持续到行尾且在 token 形成前被移除、不产生 token。唯一区别是它不再要求独占一行。行尾注释的合法位置行尾注释可以跟随任何内容以下代码现在全部合法此前均为词法错误var count: i32 0; // a) A local variable, fn Render(frame: Frame) { Draw(frame); // b) A function call, Flush(); } // c) And a closing brace.它甚至可以紧贴前一个 token、中间不加空格var c: i32 3;// no space before this comment这一行为在 trailing_comments.carbon 测试中有直接验证注释不产生 token 也不产生错误下一行第一个 tokenvar仍会被标记为具有前导空白has_leading_space: true。块字符串字面量引入行上的行尾注释一个特殊场景是块字符串字面量block string literal的引入行该行由和一个可选的 file type 指示符组成也可以携带行尾注释。这是普通的行尾注释行为与其他位置一致语法高亮把它渲染为注释、carbon format会保留它、检查注释的工具能看到它。唯一需要特殊规则的原因是file type 指示符原本会一直延续到行尾而行尾注释会像行尾空白一样终结 file type 指示符。由于注释不属于指示符内容注释中允许出现、#、即使指示符本身不允许var query: String sql // TODO: switch to a prepared statement SELECT * FROM t ;空字符字面量与的歧义消解允许注释出现在引入行上、且允许注释包含会引入一个词法歧义考虑foo // 这既可能被理解为块字符串字面量引入行file type 为foo 注释也可能被理解为空字符字面量后跟字符字面量foo // 。p007441-trailing-comments.md 的解决方式是规定字符字面量永远不可能是空的——永远不会开始一个字符字面量因此无歧义地开始或结束一个块字符串字面量。这一规定并不改变任何合法程序工具链此前就已拒绝只是把既有行为固化为消歧规则也让词法器无需额外前瞻即可归类。作为配套file type 指示符仍然限制字符集不允许、#、以改善错误恢复若指示符包含这些字符会被诊断为错误而非打开一个块字符串字面量避免整个文件被当作字符串内容处理。源码实现词法器如何解析注释Carbon 词法器位于 toolchain/lex对注释的处理体现了表驱动分发 最大吞噬max-munch 性能优化的设计。表驱动分发与/的分派词法器是一个表驱动循环每个词法元素的首字节选择对应的 handler/被接到DispatchLexCommentOrSlash见 lex.cpp 与 lex.cpp。LexCommentOrSlash用最大吞噬规则消歧如果当前字符后的下一个字符也是/就按注释处理并进入LexComment否则按/符号slash symbol处理生成 token见 lex.cpp。该分派不依赖/出现在行内的什么位置——行中间的//与行首的//走完全相同的路径。行尾注释的判定与记录LexComment中词法器通过比较/的位置与行内第一个非空白字节的位置来判定注释是否为行尾注释见 lex.cppconst bool is_trailing position ! line_info.start line_info.indent;两种注释的吞噬方式相同从//到行尾但记录时会区分使工具能分辨标注本行代码的注释与引出下方代码的注释。行尾注释永远不会与相邻的整行注释合并即使它们对齐因为它属于自己所在行的内容。这一区分被编码进CommentData结构is_trailing占用了长度字段的高 1 位使整个结构恰好打包为 8 字节见 tokenized_buffer.h。整行注释的 SIMD 块跳过优化对于整行注释词法器有一个重要的性能优化连续多行、缩进和注释前缀完全相同的注释块会被批量跳过。借助 SIMDARM NEON 或 x86-64 SSE一次性比较 16 字节前缀可以极快地扫描这类注释块见 lex.cpp。行尾注释因为无法参与块合并且预期相对稀少走的是逐行处理的普通路径见 lex.cpp。//...工具指令仍是整行注释以//开头的工具指令如//dump-sem-ir-begin、//dump-sem-ir-end、//include-in-dumps只在整行注释位置被识别因为它们是面向行的标记见 lex.cpp。在行尾位置//就是//后未跟空白属于保留当前非法注释。这些指令本身也会被记录为注释以确保 token 与注释合起来可以完整还原源码例如格式化工具不会静默丢弃指令行。格式化工具的行为carbon format会把行尾注释保留在其标注的那一行与前导内容之间用单个空格分隔而不是把它挪到单独一行。这是作者写注释时的本意也让从 C 迁移的代码保留原有的注释布局见 p007441-trailing-comments.md。至于更激进的重新排版如维护对齐的注释列、把过长的行尾注释移到独立行属于格式化质量问题而非语言问题可以在不改动语言的前提下逐步改进。唯一一个当前已知的工具链例外块字符串字面量引入行上的行尾注释目前随字符串字面量 token 的 spelling 保存由carbon format原样保留而不是进入词法器的注释记录将其通过注释记录暴露、以及诊断 file type 指示符内的保留//序列是后续工具链改进项。测试验证注释词法行为有专门的测试数据覆盖trailing_comments.carbon验证行尾注释不产生 token、不产生错误、可紧贴前一个 token、且下一行首 token 仍标记前导空白fail_bad_comment_introducers.carbon 与 fail_bad_comment_introducers_mid_block_indent_change.carbon覆盖//后缺少空白的非法引入符诊断以及注释块中途缩进变化的场景。如需单独运行测试文件可按测试文件头部提示执行bazel test //toolchain/testing:file_test \ --test_arg--file_teststoolchain/lex/testdata/trailing_comments.carbon备选方案为什么是现在的形态设计过程中曾考虑过多种替代方案详见 p000198-comments.md 与 p007441-trailing-comments.md这里摘要核心结论行内注释intra-line comments如 C 风格f(/*use_world_coords*/true)不被采纳。这类用途预期由语法扩展如命名参数、属性注解以代码而非注释的形式表达使工具也能理解同时它给格式化工具带来注释附着于哪个语法元素的复杂难题。多行文本注释不支持统一采用每行前缀//的方式消除非局部状态、减少风格差异。块注释评估了行导向、完整词法化、//\{///\}混合方案、/* */复用等多种选项因用例有限且不愿过度发明而全部放弃。文档注释有意不纳入注释体系。设计方向更倾向于用不形似注释的语法例如属性语法...附着字符串字面量来表达文档这将在未来提案中探索。代码折叠注释编辑器折叠可通过行注释内的普通文本如// #region实现无需额外语法但保留新增专用语法的可能性。方向性标记如/////行内注释标记被搁置——行尾注释的边界与对象本行内容天然清晰无需标记。限制行尾注释的出现位置如仅允许在;、枚举项、结构体字段之后被拒绝——注释可跟随本行任意内容的统一规则更简单、更易学易实现位置限制换来的只是投机性的工具便利。设计理性一条主线贯穿这些决策的核心理念是 Carbon 的三大目标见 goals.md易读、易理解、易编写唯一且一致的注释风格行尾注释支持行级短标注便于解释和讨论代码软件与语言演进//后必须空白的规则为未来注释形态预留了非破坏性的语法空间行尾注释是实验性限制的计划内重访是严格放松式变更与 C 互操作与迁移沿用//作为注释引入符避免 C 程序员与代码库的不必要迁移摩擦同时让迁移的 C 代码保留原布局。总结Carbon 的注释体系可以浓缩为四条规则其一注释以//开头、延续到行尾无物理续行其二//后必须有空白换行与文件末尾也算否则属于保留语法其三注释在 token 形成前被移除、不产生 token其四只有行注释——整行注释用于文档与引出代码行尾注释用于标注本行内容块注释与行内注释刻意缺席。理解了这些规则及其在 lex.cpp 中的实现方式你就能准确判断任何一段 Carbon 代码中注释的合法性并写出既符合规范、又能被格式化与工具链良好处理的注释。【免费下载链接】carbon-langCarbon Languages main repository: documents, design, implementation, and related tools. (NOTE: Carbon Language is experimental; see README)项目地址: https://gitcode.com/GitHub_Trending/ca/carbon-lang创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考