Hello ANTLR创建者/用户,
一些上下文 - 我正在使用PlSql ANTLR4解析器对oracle sql中的一些查询进行一些轻量级的转换,比方说,spark sql。我有我的监听器类设置,它扩展了基本监听器。
问题示例 - 假设输入类似于 -
SELECT to_char(to_number(substr(ATTRIBUTE_VALUE,1,4))-3)||'0101') from xyz;
现在,我想替换||使用CONCAT和to_char,CAST为STRING,以便最终查询看起来像 -
SELECT CONCAT(CAST(to_number(substr(ATTRIBUTE_VALUE,1,4))-3) as STRING),'0101') from xyz;
在我的监听器类中,我将覆盖基本监听器中的两个函数来执行此操作 - 连接和string_function。在那些,我使用tokenStreamRewriter的替换来进行必要的转换。由于tokenStreamRewriter被懒惰地评估,我正在运行发布 - >
java.lang.IllegalArgumentException: replace op boundaries of
<ReplaceOp@[@38,228:234='to_char',<2193>,3:15]..[@53,276:276=')',
<2214>,3:63]:"CAST (to_number(substr(ATTRIBUTE_VALUE,1,4))-3 as STRING)">
overlap with previous <ReplaceOp@[@38,228:234='to_char',<2193>,3:15]..
[@56,279:284=''0101'',<2209>,3:66]:"CONCAT
(to_char(to_number(substr(ATTRIBUTE_VALUE,1,4))-3),'0101')">
显然,问题是我的两个侦听器函数试图在重叠边界上替换/转换文本。
对于ANTLR4的区域重叠问题,是否有任何解决方法?我相信人们可能会一直遇到这样的事情。
我很感激任何解决方法,即使在这个时候也很脏:)
我确实意识到ANTLR4不允许我们修改原始AST,否则这将更容易解决。
谢谢!
答案 0 :(得分:0)
研究tokenstreamrewriter的工作方式会导致以下理解:
让我们看看如何实现修改操作:
因此,对于tokenstreamrewriter,不可能进行重叠替换,因为当您进行替换时,您将跳到要替换的令牌范围的末尾。特别是,在删除重叠检查的情况下,将仅操作第一个替换,因为之后,令牌索引超过了另一个替换。
基本上,这样做是因为在使用重叠替换时,无法轻松分辨应该替换哪些令牌。您需要进行符号识别和匹配。
因此,您要尝试执行的操作如下(对于每个步骤,“ *”之间的部分都将被修改):
<button>
</button>
要实现转换,您可以替换:
并且,通过在解析令牌时使用一些智能,就像有一个'||'用我的令牌知道它是否为字符串,您将知道要替换什么。
致谢
答案 1 :(得分:0)
我在基于ANTLR的多个项目中解决该问题的方法是:我将ANTLR解析树转换为使用Kolasu编写的AST,AST是我们在Strumenta开发的开源库。
Kolasu具有各种各样的实用程序来处理和变异AST。对于所有不重要的项目,我最终都会在AST上进行转换。