上下文相关的 ANTLR4 ParseTreeVisitor 实现
Context dependent ANTLR4 ParseTreeVisitor implementation
我正在开展一个项目,我们将 大量 (超过 12000)个视图从 Oracle 迁移到 Hadoop/Impala。我已经编写了一个小的 Java 实用程序来从 Oracle 中提取视图 DDL,并希望使用 ANTLR4 遍历 AST 并生成一个 Impala 兼容的视图 DDL 语句。
大部分工作相对简单,只涉及将一些 Oracle 特定的语法怪癖重写为 Impala 风格。但是,我面临一个问题,我不确定我是否有最佳答案:我们有许多特殊情况,在多个嵌套函数调用中提取日期字段中的值。例如,以下从日期字段中提取日期:
TO_NUMBER(TO_CHAR(d.R_DATE , 'DD' ))
我有一个为 Oracle SQL 声明的 ANTLR4 语法,因此当它到达 TO_NUMBER
和 TO_CHAR
时也会得到访问者回调,但我想对这个特例。
除了外层函数实现handler方法,然后通过手动遍历嵌套结构看看有没有别的办法
我在生成的访客中有类似的东西 class:
@Override
public String visitNumber_function(PlSqlParser.Number_functionContext ctx) {
// FIXME: seems to be dodgy code, can it be improved?
String functionName = ctx.name.getText();
if (functionName.equalsIgnoreCase("TO_NUMBER")) {
final int childCount = ctx.getChildCount();
if (childCount == 4) {
final int functionNameIndex = 0;
final int openRoundBracketIndex = 1;
final int encapsulatedValueIndex = 2;
final int closeRoundBracketIndex = 3;
ParseTree encapsulated = ctx.getChild(encapsulatedValueIndex);
if (encapsulated instanceof TerminalNode) {
throw new IllegalStateException("TerminalNode is found at: " + encapsulatedValueIndex);
}
String customDateConversionOrNullOnOtherType =
customDateConversionFromToNumberAndNestedToChar(encapsulated);
if (customDateConversionOrNullOnOtherType != null) {
// the child node contained our expected child element, so return the converted value
return customDateConversionOrNullOnOtherType;
}
// otherwise the child was something unexpected, signalled by null
// so simply fall-back to the default handler
}
}
// some other numeric function, default handling
return super.visitNumber_function(ctx);
}
private String customDateConversionFromToNumberAndNestedToChar(ParseTree parseTree) {
// ...
}
对于遇到同样问题的任何人,要走的路似乎是:
更改语法定义并引入自定义子类型
嵌套函数的封装表达式。
然后,我就可以准确地在 Parse 树的所需位置挂接处理。
使用第二个自定义 ParseTreeVisitor
捕获函数调用的值并将其余子树的处理委托给主树,"outer" ParseTreeVisitor
。
一旦第二个自定义 ParseTreeVisitor
完成了对所有子 ParseTree
的访问,我就获得了所需的上下文信息,并且正确访问了所有子树。
我正在开展一个项目,我们将 大量 (超过 12000)个视图从 Oracle 迁移到 Hadoop/Impala。我已经编写了一个小的 Java 实用程序来从 Oracle 中提取视图 DDL,并希望使用 ANTLR4 遍历 AST 并生成一个 Impala 兼容的视图 DDL 语句。
大部分工作相对简单,只涉及将一些 Oracle 特定的语法怪癖重写为 Impala 风格。但是,我面临一个问题,我不确定我是否有最佳答案:我们有许多特殊情况,在多个嵌套函数调用中提取日期字段中的值。例如,以下从日期字段中提取日期:
TO_NUMBER(TO_CHAR(d.R_DATE , 'DD' ))
我有一个为 Oracle SQL 声明的 ANTLR4 语法,因此当它到达 TO_NUMBER
和 TO_CHAR
时也会得到访问者回调,但我想对这个特例。
除了外层函数实现handler方法,然后通过手动遍历嵌套结构看看有没有别的办法
我在生成的访客中有类似的东西 class:
@Override
public String visitNumber_function(PlSqlParser.Number_functionContext ctx) {
// FIXME: seems to be dodgy code, can it be improved?
String functionName = ctx.name.getText();
if (functionName.equalsIgnoreCase("TO_NUMBER")) {
final int childCount = ctx.getChildCount();
if (childCount == 4) {
final int functionNameIndex = 0;
final int openRoundBracketIndex = 1;
final int encapsulatedValueIndex = 2;
final int closeRoundBracketIndex = 3;
ParseTree encapsulated = ctx.getChild(encapsulatedValueIndex);
if (encapsulated instanceof TerminalNode) {
throw new IllegalStateException("TerminalNode is found at: " + encapsulatedValueIndex);
}
String customDateConversionOrNullOnOtherType =
customDateConversionFromToNumberAndNestedToChar(encapsulated);
if (customDateConversionOrNullOnOtherType != null) {
// the child node contained our expected child element, so return the converted value
return customDateConversionOrNullOnOtherType;
}
// otherwise the child was something unexpected, signalled by null
// so simply fall-back to the default handler
}
}
// some other numeric function, default handling
return super.visitNumber_function(ctx);
}
private String customDateConversionFromToNumberAndNestedToChar(ParseTree parseTree) {
// ...
}
对于遇到同样问题的任何人,要走的路似乎是:
更改语法定义并引入自定义子类型 嵌套函数的封装表达式。
然后,我就可以准确地在 Parse 树的所需位置挂接处理。
使用第二个自定义
ParseTreeVisitor
捕获函数调用的值并将其余子树的处理委托给主树,"outer"ParseTreeVisitor
。
一旦第二个自定义 ParseTreeVisitor
完成了对所有子 ParseTree
的访问,我就获得了所需的上下文信息,并且正确访问了所有子树。