当前位置: 首页 > 知识库问答 >
问题:

如何用正确的行号和字符索引在ANTLR4中实现分离岛语法?

郑佐
2023-03-14

我一直在开发一个支持嵌入式SQL语句的COBOL语法。对于不熟悉COBOL的人,这里有一个示例。

MOVE A TO B.
EXEC SQL
    SELECT C FROM T WHERE ID=1
    INTO :E
END-EXEC
MOVE F TO G

“exec SQL”和“end-exec”之间的代码使用了(经过特殊扩充的)SQL语法,这是孤岛语法的一个完美示例。

我知道这可以在ANTLR4中用Lexer模式实现。但我有另一个要求,即SQL语法应该与COBOL语法分离,以便SQL语法在嵌入到其他语言(如PL1)中时可以重用,而无需复制粘贴编程。

因此,我所做的是使用一个简单的lexer模式来捕获“exec SQL”和“end-exec”之间的任何内容,将SQL代码提取为字符串,并将其交给单独的SQL lexer(和解析器)。

所以问题是:在ANTLR4中是否有一种更简单的方法来单独实现岛语法(lexer和parser都是分开的),同时仍然在为岛部分生成的标记中保留正确的行号和char索引?

更新:我发现ANTLR4中有语法导入功能,我的同事告诉我我们一直在尝试,但失败了。问题是导入语法中的lexer模式不受支持,导致编译错误。这里正在跟踪这个问题。

共有1个答案

云项禹
2023-03-14

为了扩展Bill的注释,在实例化SQL Parser/Lexer时,将EXEC块开头的行偏移量传递给它。实现一个定义SQL标记,该标记将行号报告为偏移量加上SQL文本相对行号。让SQL TokenFactory将偏移量作为常量注入到生成的每个令牌中。

更新

使用模式来实现一个惯用的孤岛语法,不管是否使用include(至少对我来说很好),都是最自然的方法。

例如,如果解析树计算提供了一个用于动态执行SQL exec块的值,或者相反,依赖于这种执行返回的值,那么实际上您必须使用符号表,并将SQL执行的启动推迟到Walker。当然,您可以缓存每个不同的生成的SQL解析树,并用实例特定的数据重新初始化它们的符号表以便重用,而无需重新解析SQL块。

只是取决于你的真正要求是什么。

 类似资料:
  • 我正在使用Antrl4解析一种类似java的语言,在这种语言中,可以使用专有的查询语言在括号中编写表达式。假设在Java方法中,应该允许以下行: 但这会导致第一个括号字符上的令牌识别错误。 这种做法有什么问题吗?有人能指出我正在犯的错误吗?

  • 问题内容: 我想在文档中搜索“社交网络营销”。全部一起。但是我继续得到结果,单词分开。我有以下DSL查询: 我没有包含此短语和标题的文档,但是我也得到了包含短语单词的搜索结果(文档)以进行拆分。我要严格搜索。如果没有任何文档使用此短语,则不要检索任何文档或仅检索具有该标题的文档。为什么 运算符又 不起作用? 问题答案: 您可以使用类型词组尝试以下方法吗?看到这里说, 查询首先分析查询字符串以生成术

  • 我在第16行中遇到了一个错误(从“

  • 问题内容: 如何获得“ E”输出而不是69? Golang是否具有将字符转换为字节,反之亦然的功能? 问题答案: 解释的字符串文字是使用单个字符的UTF-8编码(可能是多字节)在双引号“”之间的字符序列。在UTF-8中,ASCII字符是单字节,对应于前128个Unicode字符。字符串的行为就像字节片。符文是标识Unicode代码点的整数值。因此, 输出: 读: 进入转换的编程语言规范部分。 Go

  • 如何得到一个“E”的输出而不是69? Golang是否有将字符转换为字节的功能,反之亦然?

  • 问题内容: 我想从字符串中删除一个双引号(“)开头和结尾。 如何在Java中实现呢?谢谢! 问题答案: 您可以为此使用模式。 例如 要了解有关正则表达式的更多信息,请访问http://regular-expression.info。 也就是说,这有点像您要发明CSV解析器的味道。如果是这样,我建议您四处看看现有的库,例如OpenCSV。