prism4cj如何添加一门新语言支持:从正则模式到完整语法对象的实战教程
【免费下载链接】prism4cj一个轻量的语法高亮库项目地址: https://gitcode.com/Cangjie-TPC/prism4cj
本文面向新手,带你用 prism4cj 这个轻量级语法高亮库,亲手完成一门新语言支持的完整流程:从编写正则模式(Pattern)、组合 Token 标记,到构建完整的语法对象(Grammar)并注册到语法加载器,最终通过测试用例验证高亮效果。
先认识 prism4cj 的三层构件
prism4cj 的语法高亮遵循"语言查询 → 代码解析 → 渲染输出"的流水线,整个架构分为核心层与语言包两层,非常清晰:
添加一门新语言,本质上就是搭好三个构件,它们自底向上层层组合:
| 构件 | 作用 | 核心源码 |
|---|---|---|
| Pattern 模式 | 描述"长什么样的代码片段",由正则表达式驱动 | src/prism/pattern.cj |
| Token 标记 | 给一类片段起个名字(如 keyword、number),可挂多个模式 | src/prism/token.cj |
| Grammar 语法对象 | 用"语言名 + Token 集合"打包一门语言的完整规则 | src/prism/grammar.cj |
💡 记住这条公式:正则 → Pattern → Token → Grammar → 注册加载器,后文每一步都对应公式中的一环。
第1步:写出第一条正则模式
高亮的最小单元是Prism.pattern,它把一个正则包装成模式对象。以 src/languages/prism_brainfuck.cj 为参考,你的新语言只需要为"关键词、数字、字符串、注释"这几类片段各写一条正则即可:
Prism.token("keyword", Prism.pattern(Regex("\\b(?:if|else|while)\\b"))) Prism.token("number", Prism.pattern(Regex("\\b\\d+\\.?\\d*\\b"))) Prism.token("comment", Prism.pattern(Regex("//[^\\n]*")))pattern最多支持 5 个参数,新手建议先只传第一个,其余按需开启:
| 参数 | 说明 |
|---|---|
| regex | 正则对象,核心 |
| lookbehind | 是否允许后行断言,影响匹配起点 |
| greedy | 是否贪婪匹配 |
| alias | 别名,让片段复用其他类型的样式 |
| inside | 嵌套语法,对"片段内部的片段"再高亮 |
第2步:组合 Token,生成完整语法对象
把若干 Token 放进ArrayList,连同语言名一起交给GrammarImpl,一门语言的高亮规则就成型了:
let mylang = GrammarImpl("mylang", ArrayList<Token>([...]))组合完成后,高亮器就能把代码切分为"文本 + 标记"两类节点。下图中类名、注解、关键字等不同片段被分别识别标记,正是 Token 名称起作用的结果:
📌 建议:Token 命名沿用库内既有习惯(keyword、string、comment、number、operator),这样默认样式即可生效,无需额外配置。
第3步:复用父类语法,偷懒但正确地省工作量
如果新语言与已有语言同族(例如 C++ 之于 C、Dart 之于 Clike 风格),不要从零写起。prism4cj 提供了语法继承三件套,src/languages/prism_c.cj 是绝佳范例:
GrammarUtils.require(prism, "clike"):取回父语法GrammarUtils.extendGrammar(...):覆盖/追加本语言的 Token,并用过滤器剔除不需要的GrammarUtils.insertBeforeToken(...):在指定 Token 前插入新规则(如 C 的 macro 宏定义)
这三类工具的完整签名见 doc/feature_api.md,照着 test/LLT/testC.cj 就能快速上手。
第4步:把新语言注册到语法加载器
规则写好后,最后一步是让它"可被按名查询"。打开 src/grammar_locator_grammar_utils.cj,做三处小改动:
obtainGrammar的 match 分支中加一行:case "mylang" => grammar = PrismMylang.create(prism)languages()集合中set.add("mylang")- (可选)在
realLanguageName中为新语言配置别名,例如"js" => "javascript"这类映射
✅ 注意:本库默认预创建全部已支持语法,因此测试时请求的语言名必须与注册名一一对应,否则会得到None。
第5步:编写测试用例验证高亮效果
复制一份现成用例作为骨架是最快的方式,推荐参考 test/LLT/testBrainfuck.cj:它演示了"读用例文件 → 按名取语法 → tokenize → 断言"的完整流程,公共工具集中在 test/LLT/testUtils.cj。
行为级用例则放在 HLT 目录,按功能一个文件,如 test/HLT/function/languages/brainfuck/all_feature.test。编译执行步骤(cjpm build及cjc命令参数说明)详见 README.md 的"执行用例"一节。
常见问题速查
- grammar 返回 None?检查第4步注册是否完整:match 分支、languages() 集合、语言名拼写三者都要对上。
- 高亮范围不准?优先调整正则;需要断言边界时再考虑 lookbehind,需要嵌套高亮时才使用 inside。
- 想查某个类的完整接口?直接看 doc/feature_api.md,所有 Pattern/Token/Grammar/Visitor 接口都有注释。
小结与参考路径
添加新语言支持 = 正则模式 + Token 组合 + 语法对象 + 加载器注册 + 测试验证,五步走完即可上线一门语言。核心文件速查:
- 语言规则示例:src/languages/prism_brainfuck.cj、src/languages/prism_c.cj
- 核心类实现:src/prism/pattern.cj、src/prism/token.cj、src/prism/grammar.cj
- 加载器注册:src/grammar_locator_grammar_utils.cj
- 接口文档:doc/feature_api.md
- 测试骨架:test/LLT/testBrainfuck.cj
- 构建配置:cjpm.toml
【免费下载链接】prism4cj一个轻量的语法高亮库项目地址: https://gitcode.com/Cangjie-TPC/prism4cj
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考