拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

Cap‘n Proto 模式语言 ANTLR v4 语法全解:grammars-v4 中 CapnProto.g4 的结构、词法与示例验证

Cap‘n Proto 模式语言 ANTLR v4 语法全解:grammars-v4 中 CapnProto.g4 的结构、词法与示例验证 编程语言编译器开发工具【免费下载链接】grammars-v4Grammars written for ANTLR v4; expectation that the grammars are free of actions.项目地址https://gitcode.com/gh_mirrors/gr/grammars-v4点击查看免费下载本篇技术指南系统讲解 grammars-v4 仓库中 capnproto/README.md 所定义的核心主题——Capn Proto 模式语言Schema Language的 ANTLR v4 语法实现。全文以 CapnProto.g4 为骨架结合 pom.xml 中的生成与测试配置、desc.xml 声明的目标语言以及examples/目录下 6 组真实 .capnp 文件逐层剖析该语法的顶层文档结构、struct/interface/enum/annotation/const 构造、词法规则与常量字面量体系。读完本文你将能够完整理解 Capn Proto 模式语言的 ANTLR 语法映射关系并掌握如何利用仓库自带的 Maven 测试配置与示例文件验证、复用它生成多语言解析器。一、语法文件概览纯语法的 Capn Proto Schema Languagecapnproto/README.md 明确指出本目录提供的是面向 Capn Proto 模式语言的 ANTLR v4 语法grammar for the Capn Proto schema language即用于描述 Capn Proto.capnp模式文件如struct、interface、enum、annotation、const等声明的解析器定义。仓库根目录的项目描述强调期望语法文件不含动作free of actions这一约定在 CapnProto.g4 中得到严格执行全文 228 行均为纯 ANTLR 语法规则8 条解析器规则族 10 个词法 token 与 2 个 fragment没有任何嵌入目标语言的语义动作action或语义谓词生成的解析器仅负责构建语法树语义处理完全留给访问者/监听器阶段。capnproto 目录结构如下CapnProto.g4 —— 唯一的语法源文件lexer parser 合并定义pom.xml —— 基于 antlr4-maven-plugin 的生成配置与 antlr4test-maven-plugin 的示例回归测试配置desc.xml —— 声明该语法支持生成的目标语言CSharp;Cpp;Dart;Go;Java;JavaScript;PHP;Python3;TypeScript;Antlr4ngexamples/ —— 覆盖多种真实场景的.capnp示例文件。二、顶层文档结构document 规则的语法骨架语法入口是顶层规则documentCapnProto.g4document : file_identifier using_import* namespace_? document_content* EOF ;一个合法的 Capn Proto 模式文件按顺序由四部分组成文件标识符file_identifier必选——以FILE_ID ;形式出现CapnProto.g4。FILE_ID词法规则为 HEXADECIMALCapnProto.g4即后跟十六进制数。所有示例文件首行均如此例如 addressbook.capnp 的0x9eb32e19f86ee174;与 calculator.capnp 的0x85150b117366d14b;。文件 ID 用于标识模式文件自身的全局唯一编号对应 Capn Proto 的演进兼容机制。import 声明using_import可多个——规则为using (NAME )? import TEXT (. NAME)? ;CapnProto.g4。支持两种形式带别名using Cxx import /capnp/c.capnp;见 addressbook.capnpNAME 部分是别名Cxx不带别名using import enums.capnp.EnumType2;见 lua-capnproto/example.capnp此时通过. NAME直接导入被导入文件中的具体类型EnumType2。可选的命名空间声明namespace_——规则为$ NAME .namespace ( TEXT ) ;CapnProto.g4。例如 addressbook.capnp 中的$Cxx.namespace(addressbook)与 node-capnp/test.capnp 中的$Cxx.namespace(capnproto_test::capnp::test)用于为生成的代码指定宿主语言命名空间此处依赖 C 的c.capnp注解。文档主体document_content零个或多个——由struct_def | interface_def | function_def | annotation_def | const_def | enum_def构成CapnProto.g4即结构体、接口、函数、注解、常量与枚举可在文件顶层平级声明。例如 node-capnp/test.capnp 顶层声明了globalInt、globalText、globalStruct等全局常量。注意document规则以EOF收尾且using_import*与namespace_?必须位于所有类型声明之前这与 Capn Proto 模式文件的书写惯例一致。三、类型系统type_ 与泛型内层类型 inner_type类型引用由两条规则构成CapnProto.g4type_ : NAME inner_type? (. type_)? ; inner_type : ( type_ inner_type? (, type_ inner_type?)* ) ;type_是一个递归结构语义为标识符 可选泛型参数 可选点号限定的嵌套类型基本类型直接以NAME引用如UInt32、Text、Data、Float64、Void、Bool以及自定义类型名这些内置类型名在 Capn Proto 中属于预定义语法层面统一以 NAME 吸收泛型类型通过inner_type表达如List(Person)addressbook.capnp、List(List(Int32))node-capnp/test.capnp、TestGenerics(Text, List(UInt8))capnp-rust/test.capnp。inner_type支持递归与逗号分隔的多参数因此可以表达List(List(List(Int16)))这样的深层嵌套见 capnp-rust/test.capnp嵌套限定的类型通过. type_表达如TestNestedTypes.NestedEnumnode-capnp/test.capnp以及带泛型的嵌套TestGenerics(TestAllTypes, List(UInt32)).Interface(Data)capnp-rust/test.capnp。这条递归类型规则是整个语法表达力的基石Capn Proto 的类型即名字 参数 限定路径模型被直接映射为语法结构解析器无需语义信息即可正确切分类型边界。四、结构体 struct字段、嵌套声明、union 与 group4.1 struct_def 与其内容集合struct_def规则CapnProto.g4struct_def : struct type_ annotation_reference? { struct_content* } ;struct关键字后跟类型名type_因此也支持struct Foo(T) {}这类泛型结构体声明见 capnp-rust/test.capnp 的struct TestGenerics(Foo, Bar)可选一个注解引用随后是花括号内的struct_content*。struct_contentCapnProto.g4允许嵌套出现field_def字段定义enum_def嵌套枚举named_union_def/unnamed_union_def命名/匿名 unioninterface_def嵌套接口如 calculator.capnp 在 interface 内嵌struct Expression与interface Value而 capnp-rust/test.capnp 在 struct 内嵌struct Innerannotation_def/struct_def/const_def嵌套注解、结构体与常量如 lua-capnproto/example.capnp 在struct T1内声明const welcomeText与const constT2group_def字段组inner_using局部 using 别名。4.2 字段定义 field_def 与定位符 LOCATOR字段是结构体的核心元素规则CapnProto.g4field_def : NAME LOCATOR : type_ ( const_value)? ; ;即字段名NAME 必选的定位符LOCATOR: 类型 可选的默认值 const_value 分号。例如 addressbook.capnpid 0 :UInt32; name 1 :Text; email 2 :Text; phones 3 :List(PhoneNumber);LOCATOR词法规则为 DIGIT !?CapnProto.g4后跟十进制序号尾部可带!。序号是 Capn Proto 字段编号ordinal用于保证跨版本序列化兼容——它不要求连续或有序声明node-capnp/test.capnp 的struct TestOutOfOrder特意将 8 个Text字段以3/2/8/0/6/4/1/7/5的乱序方式声明验证语法与代码生成对乱序编号的容忍。!后缀用于标记该字段被覆盖在后续 union 中union discriminant 的锚定字段例如 node-capnp/test.capnp 的union0 0! :union。默认值示例node-capnp/test.capnpboolField 1 :Bool true;、int8Field 2 :Int8 -123;、float64Field 11 :Float64 -123e45;、textField 12 :Text foo;等默认值语法由const_value统一承载见第七节。4.3 联合体 union命名与匿名Capn Proto 支持两种 union 形式CapnProto.g4named_union_def : NAME LOCATOR? :union { union_content* } ; unnamed_union_def : union { union_content* } ;命名 union字段名 可选 LOCATOR :union。如 addressbook.capnp 的employment :union { unemployed 4 :Void; employer 5 :Text; school 6 :Text; selfEmployed 7 :Void; }node-capnp/test.capnp 的union0 0! :union则展示带 LOCATOR 与!的形式。匿名 union直接union { ... }。如 calculator.capnp 中struct Expression内的匿名 union以及 lua-capnproto/example.capnp 的# unnamed union注释下的写法。union_content允许field_def、group_def、unnamed_union_def、named_union_def因此支持union 嵌套 unionnode-capnp/test.capnp 的struct TestUnionInUnion明确注释There is no reason to ever do this。4.4 字段组 groupgroup_def规则CapnProto.g4group_def : NAME :group { group_content* } ;group 是无编号的字段容器字段名后直接:group组内字段仍各自带 LOCATOR。典型用法见 calculator.capnpcall :group { function 3 :Function; params 4 :List(Expression); }以及 lua-capnproto/example.capnp 的g0 :group { ui2 15 :UInt32; }。group 常与 union 组合如 node-capnp/test.capnp 的struct TestGroupsunion 内三个:group分支group_content允许嵌套 field、命名/匿名 union。五、接口 interface方法、继承与泛型方法参数5.1 interface_def 与继承interface_def : interface type_ (extends ( type_ ))? { interface_content* } ;CapnProto.g4接口可以继承一个父接口如 node-capnp/test.capnpinterface TestExtends extends(TestInterface) { qux 0 (); corge 1 TestAllTypes - (); grault 2 () - TestAllTypes; }interface_contentCapnProto.g4允许字段、枚举、命名/匿名 union、嵌套接口、嵌套结构体与方法定义。接口内嵌结构体的典型例子是 calculator.capnp 的struct Expression与 node-capnp/test.capnp 的struct Box。5.2 方法定义 function_def方法规则是语法中形态最丰富的部分CapnProto.g4function_def : NAME LOCATOR? generic_type_parameters? (function_parameters | type_) ( - ( function_parameters | type_) )? ; ; generic_type_parameters : [ NAME (, NAME)* ] ; function_parameters : ( (NAME : type_ ( const_value)? ( , NAME : type_ ( const_value)?)*)? ) ;方法名NAME 可选LOCATOR可选的泛型类型参数generic_type_parameters[T, U]形式如 capnp-rust/test.capnp 的call 0 [T, U] (foo :T, bar :U) - TestGenerics(T, U);与call4 4 [T, U] TestGenerics(V, V) - TestGenerics(V, AnyPointer);参数列表function_parameters可为空()每个参数名称 : 类型且支持参数默认值 const_value如 node-capnp/test.capnp 的methodWithDefaults 8 (a :Text, b :UInt32 123, c :Text foo) - (d :Text, e :Text bar);返回值可为参数列表(value :Value)或单个类型TestAllTypes如 calculator.capnp 的evaluate 0 (expression :Expression) - (value :Value);。注意function_parameters中的参数类型同样复用type_规则因此支持List(Float64)、TestInterface等复杂类型作为参数/返回值见 capnp-rust/test.capnp 的interface TestInterface。六、枚举与注解enum_def、annotation_reference 与 annotation_def6.1 枚举 enumenum_def : enum NAME annotation_reference? { enum_content* } ; enum_content : NAME LOCATOR annotation_reference? ; ;CapnProto.g4枚举项由名称 LOCATOR 序号组成枚举自身可挂注解引用。示例遍布各测试文件addressbook.capnp 的enum Type { mobile 0; home 1; work 2; }、calculator.capnp 的enum Operator { add 0; ... }。6.2 注解引用 annotation_reference注解引用语法CapnProto.g4annotation_reference : $ type_ .ann? ( TEXT ) ;即$类型.成员名。三个典型用例addressbook.capnp$Cxx.namespace(addressbook)作为 namespace 声明复用$ NAME .namespace专用规则lua-capnproto/example.capnpenum EnumType1 $Lua.naming(lower_underscore) { ... }以及枚举项上的enum4 3 $Lua.literal(wEirdENum4)——这是annotation_reference挂在enum_def与enum_content上的直接体现lua-capnproto/enums.capnp同一枚举的多个枚举项分别使用$Lua.naming(upper_dash)、$Lua.naming(lower_underscore)等不同命名风格注解而这些注解由 lua.capnp 声明。type_规则天然支持Lua.naming这类带点号的注解路径因此annotation_reference可引用任意深度限定的注解名。6.3 注解声明 annotation_defannotation_def : annotation type_ annotation_parameters? : type_ ; ; annotation_parameters : ( struct ) ;CapnProto.g4注解声明形如annotation 名称(可选struct限定) : 类型;。从源码结构看当前语法对注解声明参数仅支持(struct)一种形式即仅可应用于 struct的限定。lua.capnp 中的annotation naming(en2um, enumerant) : Text;使用了形参名列表形式对应 Capn Proto 官方语法中注解的 enumerant 参数该写法未在本语法文件的annotation_parameters中体现属于语法覆盖范围与官方语言规范之间的差异点使用时需注意。capnp-rust/test.capnp 的annotation ann(struct) :Foo;则与annotation_parameters的(struct)形式完全吻合。七、常量与常量值const_def 与 const_value 字面量体系常量声明规则CapnProto.g4const_def : const NAME : type_ const_value ; ;常量可出现在文件顶层如 node-capnp/test.capnp 的const globalInt :UInt32 12345;或 struct 内部如 lua-capnproto/example.capnp 的顶层const pi :Float32 3.14159;与 lua-capnproto/struct.capnp 的const flag1 :UInt32 0x1;。const_value是该语法的字面量中枢CapnProto.g4const_value : -? .? NAME (. NAME)? | INTEGER | FLOAT | TEXT | BOOLEAN | HEXADECIMAL | VOID | literal_list | literal_union | literal_bytes ; literal_union : ( NAME union_mapping (, NAME union_mapping)* ) ; literal_list : [ const_value (, const_value)* ] ; literal_bytes : 0x TEXT ; union_mapping : ( NAME const_value ) | const_value ;各分支对应的真实用法字面量形式语法规则仓库示例枚举/限定常量引用-? .? NAME (. NAME)?enumField baznode-capnp/test.capnp.前缀引用全局常量.globalInt、.限定引用TestConstants.textConstnode-capnp/test.capnp十进制整数INTEGER : -? DIGITdu0 21 :UInt32 65535;lua-capnproto/example.capnp浮点数FLOAT : -? DIGIT (. DIGIT)? (e -? DIGIT)?const pi :Float32 3.14159;lua-capnproto/example.capnp、float64Field -123e45node-capnp/test.capnp字符串TEXT : ~[]*? const flag3 :Text Hello;lua-capnproto/struct.capnp布尔BOOLEAN : true \| falsedb0 22 :Bool true;lua-capnproto/example.capnp十六进制整数HEXADECIMAL : -? 0x HEX_DIGITconst flag1 :UInt32 0x1;lua-capnproto/struct.capnp、int8List [12, -34, -0x80, 0x7f]node-capnp/test.capnp空类型VOID : voidvoidField 0 :Void void;node-capnp/test.capnp、voidList [void, void, void]node-capnp/test.capnp列表字面量literal_list : [ const_value (, const_value)* ]int8List 19 :List(Int8) [111, -111];node-capnp/test.capnp结构体/union 字面量literal_union : ( NAME union_mapping (, ...)* )const constT2 :T2 (f0 12345.67, f1 9876.54, sd0 \0\1\2\3);lua-capnproto/example.capnp、嵌套的structField (textField nested, structField (textField really nested))node-capnp/test.capnp字节字面量literal_bytes : 0x TEXTdataField 13 :Data 0x62 61 72;capnp-rust/test.capnp其中union_mapping同时支持裸常量值const_value与嵌套的(NAME const_value)形式使 union 默认值可以进一步展开为子结构体字面量——这正是 node-capnp/test.capnp 中TestUnionDefaults用(union0 (u0f0s16 321), union1 (u1f0s8 123), ...)为多个 union 分支同时赋默认值所依赖的语法能力。八、词法规则token 定义与空白/注释处理词法部分CapnProto.g4共定义 8 个有效 token 与 2 个 fragmentToken正则定义语义FILE_ID HEXADECIMAL文件标识符如0x9eb32e19f86ee174LOCATOR DIGIT !?字段/方法序号可带!标记TEXT ~[]*? 双引号字符串不支持转义引号INTEGER-? DIGIT十进制整数含负号FLOAT-? DIGIT (. DIGIT)? (e -? DIGIT)?浮点数支持小数与指数HEXADECIMAL-? 0x HEX_DIGIT十六进制整数含负号HEX_DIGIT覆盖 0-9/A-F/a-fBOOLEANtrue \| false布尔字面量VOIDvoid空类型/空值NAME[a-zA-Z] [a-zA-Z0-9]*标识符字母开头可含数字两个值得注意的设计点COMMENT进入隐藏通道COMMENT : # ~[\n]* - channel(HIDDEN)CapnProto.g4。Capn Proto 模式语言使用#行注释语法将其送入HIDDEN通道而非直接丢弃这意味着注释 token 仍可被词法阶段捕获适用于自定义 token 流处理但不会进入解析器。WHITESPACE直接跳过WHITESPACE : [ \t\r\n] - skipCapnProto.g4。空白空格、制表符、换行被完全跳过因此模式文件的排版不敏感——capnp-rust/test.capnp 中struct Struct{}这种无空格的写法同样可被解析。由于NAME与关键字struct、union、enum、const、interface、using、import、annotation、extends、group、void、true、false等均为字母序列ANTLR 遵循先声明的字面量优先原则解析器规则中先出现的字面量 token 优先于后定义的NAME规则匹配。因此end 23 :Bool;lua-capnproto/example.capnpend是 Lua 保留字但并非本语法关键字中的end会作为NAME正常解析验证了关键字集合是封闭的、不受宿主语言保留字影响。九、示例验证examples 目录如何全覆盖语法规则pom.xml 中 antlr4test-maven-plugin 将exampleFiles指向examples/意味着该目录下的.capnp文件就是语法的回归测试语料。仓库中的示例按来源分组各自侧重不同语法面addressbook.capnpCapn Proto 官方教程——覆盖file_identifier、using_import带别名using Cxx import ...、namespace_$Cxx.namespace(...)、顶层struct、嵌套struct与enum、List(Person)泛型类型、命名 unionemployment :union、Void类型与默认字段。calculator.capnpRPC 计算器示例——覆盖interface的完整形态带注释的方法evaluate 0 (expression :Expression) - (value :Value)、接口内嵌struct与匿名unionunion { literal 0 :Float64; ... }、call :group字段组、嵌套interface Value、顶层enum Operator、接口类型作为字段类型previousResult 1 :Value。node-capnp/test.capnpnode-capnp 的测试模式——该文件近乎语法全覆盖压力测试全部 12 种基础类型与对应List(...)形式丰富的默认值含列表默认值、嵌套结构体默认值、union 默认值0!定位符与乱序字段编号TestOutOfOrder命名 unionunion0 0! :union、union 内嵌 union、union 内嵌 groupusing别名using OuterNestedEnum TestNestedTypes.NestedEnum;接口继承extends(TestInterface)、泛型方法参数[T, U]、参数/返回值默认值.globalInt与TestConstants.textConst形式的限定常量引用。capnp-rust/test.capnpcapnpc-rust 的测试模式——重点覆盖泛型体系struct TestGenerics(Foo, Bar)、泛型结构体嵌套、annotation ann(struct) :Foo;、接口泛型参数[T, U]、Map(Key, Value)泛型结构、interface GenericExtend extends(GenericBase(Data))泛型继承、0x62 61 72字节字面量以及TestKeywords中与 Rust 保留字同名的结构体验证 NAME 规则的健壮性。lua-capnproto/cloudflare/lua-capnproto 的三文件模式——lua.capnp 声明naming/literal注解enums.capnp 演示$Lua.naming(...)注解引用与using import lua.capnp导入struct.capnp 展示 struct 内常量example.capnp 综合了嵌套 struct、枚举注解、匿名/命名 union、group、Data/AnyPointer类型、List(Text)泛型、struct 内const与复杂结构体字面量默认值以及using import enums.capnp.EnumType2这类直接导入具体类型的写法。十、构建与测试Maven 配置与目标语言capnproto/pom.xml 继承仓库根pom.xmlorg.antlr.grammars:grammarsv4聚合工程通过两个插件完成生成 验证闭环1. antlr4-maven-plugin语法生成pom.xmlsourceDirectory设为${basedir}includes仅包含CapnProto.g4即从语法文件所在目录生成解析器同时开启visitor与listener为true确保生成标准的 ANTLR 访问者与监听器接口供用户在目标语言中实现语义处理语法本身不嵌入 action语义逻辑全部落在访问者/监听器层。2. antlr4test-maven-plugin示例回归测试pom.xmlgrammarNameCapnProto、entryPointdocument即以document作为入口规则对示例文件执行完整解析exampleFilesexamples/将上文第九节列举的全部.capnp文件作为测试语料任一文件解析失败即测试失败packageName为空、showTree关闭、verbose关闭保持输出精简。3. 目标语言声明_scripts/desc.xsd 校验的 desc.xml 声明该语法支持的生成目标为CSharp;Cpp;Dart;Go;Java;JavaScript;PHP;Python3;TypeScript;Antlr4ng涵盖主流 ANTLR 运行时。在实际使用中可在仓库根目录执行mvn -pl capnproto test或在capnproto/目录下执行mvn test触发上述流程antlr4-maven-plugin 先生成解析器源码antlr4test-maven-plugin 随即用examples/中的全部模式文件验证语法正确性。仓库根目录还提供了通用的 maven.sh、grun.sh 与 test.sh 等辅助脚本配套_scripts/antlr4-tools/下的工具链可用于生成后用grun以document为入口规则查看某.capnp文件的解析树。十一、在自己的项目中复用该语法要复用这套 Capn Proto 模式语言解析器只需三步获取语法将 CapnProto.g4 拷贝到目标工程的 ANTLR 源目录或直接依赖本仓库多模块工程中的capnproto模块。该文件无依赖其他.g4、无嵌入了 action任何 ANTLR v4 运行时均可直接生成。生成解析器使用 ANTLR 工具IDE 插件或构建工具以document为入口规则生成目标语言代码若使用 Maven参考 pom.xml 的 antlr4-maven-plugin 配置sourceDirectory、includes、visitor/listener开关即可。接入业务语法仅负责构建解析树建议基于生成的监听器Listener或访问者Visitor遍历树在document、struct_def、field_def、const_def等上下文各规则的锚点见本文第二至七节的行号引用中提取类型信息、字段编号与默认值进而实现 Capn Proto 模式到本语言类型系统的映射、IDL 校验或代码生成。若需对既有模式做 AST 级改写如重命名规则仓库根目录还提供了 rename_rules.py 与 reorder_parser.py 等工具作为参考。结语作为 grammars-v4 聚合仓库的一部分capnproto模块以一份 228 行的纯语法文件完整覆盖了 Capn Proto 模式语言的核心构造从document顶层的文件 ID、import 与命名空间到 struct 的字段/union/group 体系、interface 的方法/继承/泛型参数再到 enum、annotation 与全字面量常量体系词法层则通过FILE_ID、LOCATOR、隐藏通道注释与跳过空白等设计保证了模式的演进兼容性与排版自由。配合examples/下覆盖官方教程、RPC、Rust、Node、Lua 等多生态的真实示例与 pom.xml 中的生成回归测试配置任何 ANTLR v4 使用者都能快速将其接入自己的工具链构建面向 Capn Proto 的解析、校验与代码生成能力。赞分享编程语言编译器开发工具【免费下载链接】grammars-v4Grammars written for ANTLR v4; expectation that the grammars are free of actions.项目地址https://gitcode.com/gh_mirrors/gr/grammars-v4点击查看免费下载相关推荐用 ANTLR v4 解析 B 语言grammars-v4 仓库 b/b.g4 语法全解与实战验证用 ANTLR v4 解析 B 语言grammars v4 仓库 b/b.g4 语法全解与实战验证 本文围绕 grammars v4 仓库中 b/README编程语言编译器开发工具grammars-v4 中的 HyperTalk 语法用 ANTLR v4 解析 HyperCard 脚本语言grammars v4 中的 HyperTalk 语法用 ANTLR v4 解析 HyperCard 脚本语言 导读 本文讲解 grammars v4 htt编程语言编译器开发工具深入解析 grammars-v4 中的 BibTeX ANTLR v4 语法词法规则、条目结构与实战解析深入解析 grammars v4 中的 BibTeX ANTLR v4 语法词法规则、条目结构与实战解析 本篇文章以 bibtex/readme.md htt编程语言编译器开发工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表