使用ANTLR解析Protobuf3语法时如何高效获取type_节点的类型信息
实现方案
完全不需要逐个判断所有基础类型分支,有两种极简实现方式:
- 直接取type_节点原始文本(最省事)
不管type_匹配到的是基础类型关键字,还是自定义消息/枚举类型,节点的getText()返回值就是你需要的类型名称:基础类型返回double、int32这类关键字,复杂类型返回对应的定义名,甚至带全限定路径的名称也能完整获取。 - 区分基础/复杂类型只需判断2个分支
如果你需要额外标记字段是基础类型、消息类型还是枚举类型,只需要判断type_上下文的两个复杂类型子规则是否存在即可,剩下的所有情况都是基础类型,不需要逐个校验13种基础类型终端。
代码示例
@Override public void enterField(Protobuf3Parser.FieldContext ctx) { MessageDefinition messageDefinition = this.messageStack.peek(); Field field = new Field(); // 直接获取类型名,无需判断分支 String typeName = ctx.type_().getText(); field.setType(typeName); field.setName(ctx.fieldName().ident().getText()); field.setPosition(ctx.fieldNumber().getAltNumber()); // 仅当需要区分类型分类时添加以下逻辑 Protobuf3Parser.Type_Context typeCtx = ctx.type_(); if (typeCtx.messageDefinition() != null) { field.setTypeCategory(Field.TypeCategory.MESSAGE); } else if (typeCtx.enumType() != null) { field.setTypeCategory(Field.TypeCategory.ENUM); } else { field.setTypeCategory(Field.TypeCategory.SCALAR); } messageDefinition.addField(field); super.enterField(ctx); }
原理解释
ANTLR为每个语法规则生成的上下文类中,所有可选子规则都会对应生成getter方法:如果该子规则被匹配到,getter返回对应的上下文对象,否则返回null。你用到的type_规则只有messageDefinition和enumType两个非终端子规则,其余全是基础类型的终端节点,因此只需要判断这两个子规则的返回值就能区分类型分类,不需要逐个处理基础类型分支。
内容的提问来源于stack exchange,提问作者Vinicius Carvalho
相关产品推荐
相关产品推荐

