c# - ANTLR4 - VisitChildren 返回 null,即使孩子返回某个对象
问题描述
我一直在尝试实现访问者模式,将一些特定的 SQL 语句解析为由 TableDefinition 和 ColumnDefinition 对象组成的内部对象结构。
这是语法中的一小部分(精简):
column_definition
: column_name datatype? column_constraint*
;
column_constraint
: ( K_CONSTRAINT name )?
( K_PRIMARY K_KEY ( K_CLUSTERED | K_NONCLUSTERED )? ( K_ASC | K_DESC )? K_AUTOINCREMENT?
| K_AUTOINCREMENT
| K_NOT? K_NULL
)
;
datatype
: K_CHAR ( '(' unsigned_integer ')' )? #char
| K_DATE #date
;
这是派生的 BaseVisitor 之一,它旨在返回 ColumnDefinitions:
namespace SqlParser.Visitor
{
public class DataTypeVisitor: SqlAnywhereParserBaseVisitor<ColumnDefinition>
{
public override ColumnDefinition VisitColumn_definition([NotNull] SqlAnywhereParser.Column_definitionContext context)
{
var res = VisitChildren(context);
var constraint = (SqlAnywhereParser.Column_constraintContext[])context.column_constraint();
if (res != null) // Add NULL attributes
{
if (constraint.Any(c => c.K_NULL() != null && c.K_NOT() == null))
res.IsNullable = true;
if (constraint.Any(c => c.K_NULL() != null && c.K_NOT() != null))
res.IsNullable = false;
}
return res;
}
public override ColumnDefinition VisitChar([NotNull] SqlAnywhereParser.CharContext context)
{
return new ColumnDefinition()
{
DataType = DbType.StringFixedLength,
Length = int.Parse(context.unsigned_integer()?.GetText() ?? "1")
};
}
}
}
当我调试该过程时,我可以观察到对 VisitChildren 的调用如何进入返回 ColumnDefinition 对象的 VisitChar。当 VisitChar 完成并且光标跳回以在 VisitColumn_definition 中继续时,变量 res 为空。
我错过了一些重要的事情还是我误解了访问者模式?在我尝试 VisitChildren 之前,我曾经使用 base.VisitColumn_definition(context) 调用,它基本上只调用 VisitChildren。
有没有人有提示,我犯了哪些错误?为什么我在 VisitChar 叶创建的 ColumnDefinition 结果没有冒泡?
下面是我的测试输入:
CREATE TABLE "DBA"."pbcattbl" (
"pbt_tnam" char(129) NOT NULL
,"pbt_tid" char(5) NULL
);
解决方案
我找到了一个解决方案:
protected override List<ColumnDefinition> AggregateResult(List<ColumnDefinition> aggregate, List<ColumnDefinition> nextResult)
{
if (aggregate != null && nextResult != null) aggregate.AddRange(nextResult);
return aggregate ?? nextResult;
}
我将结果转换为 List<ColumnDefinition> 并向 AggregateResult 添加了适当的覆盖。
感谢@kaby76 用您的评论为我指明了正确的方向。也感谢所有其他人的反馈和快速响应!
推荐阅读
- github - 如何在 GitHub Pages 上的根域和 WWW 子域上强制执行 HTTPS?
- vb.net - 如何确保在模拟中使用唯一的随机数?
- marklogic - system_time 大于当前日期时间
- javascript - 如何将一个jsp页面显示为另一个jsp页面中的弹出窗口
- python-3.x - 将数据组织到嵌套字典中:错误“列表索引必须是整数或切片,而不是 str”
- android - 为 UnityPlayerActivity 设置 android:launchmode
- python - python kivy小部件堆叠在底部
- node.js - 无法使用 Stripe API 更新争议证据
- laravel - Laravel 获得模型兄弟姐妹和自我 - 这是正确的方法吗?
- python - PyObject_CallMethod 泄漏/段错误