如何使用ANTLRv4解析来自日志文件和网络协议的sql查询

如何使用ANTLRv4解析来自日志文件和网络协议的sql查询,sql,parsing,antlr4,Sql,Parsing,Antlr4,我需要解析可以使用网络协议(例如MySQL协议)提交或存储在日志文件中的SQL查询 我基于ANTLRv4构建了一个解析器 以下文本在此语法中有效: select 1 select 2 select 3 选择1选择2选择3 同时,它们对于网络协议应该无效,因为xSQL服务器将删除\n,并且最终查询将等于select 1 select 2 select 3 是否有可能创建一个同时处理这两种情况的语法?或者我应该创建并支持两个语法:第一个语法用于解析日志,第二个语法用于解析网络查询? 我可以用语义谓

我需要解析可以使用网络协议(例如MySQL协议)提交或存储在日志文件中的SQL查询

我基于ANTLRv4构建了一个解析器

以下文本在此语法中有效:

select 1
select 2
select 3
选择1选择2选择3

同时,它们对于网络协议应该无效,因为xSQL服务器将删除
\n
,并且最终查询将等于
select 1 select 2 select 3

是否有可能创建一个同时处理这两种情况的语法?或者我应该创建并支持两个语法:第一个语法用于解析日志,第二个语法用于解析网络查询?
我可以用语义谓词来解决这个问题吗?

我想出了两种方法:

  • 在语法中使用代码片段:
  • Delcare
    textMode
    标记位于
    @lexer::members
    部分
  • SPACE
    令牌替换为以下令牌:
    ANTLR
    空白:[\t]->通道(隐藏);
    换行符:'\r'?'\不
    {if(文本模式)
    通道(隐藏);
    其他的
    AddParseError();
    }
    
  • 检查无语法修改的标记:
  • 标记化导入。在此步骤之后,我们有以下令牌:
    选择WS()编号(1)WS(\n)选择WS()编号(2)WS(\n)选择WS()编号(2)WS(\n)
  • 循环标记并对每个标记执行以下操作:
    • 如果激活了“文本模式”,只需忽略隐藏标记(空格和换行符) 在这一步之后,我们有以下标记:
      selectnumber(1)selectnumber(2)selectnumber(2)
      ,它传递给解析器
    • 如果激活了“网络协议模式”,请在带有换行符值的
      WS
      令牌上添加自定义错误(
      \r
      \n

你在文章末尾提出了三个问题,但我只提供一个对我有用的答案:只需创建两个语法。这并不像听起来那么糟糕,可以澄清问题


您可以使两个语法中的所有内容都相同,然后使用
import
构造只包含不同的部分。我在医疗HL7文件中使用过这种方法,它使用并重用了许多公共段。

这两种方法都不能解决主要问题:
select 1 select 2 select 3
将被解析为有效查询,但它不是真的。