删除这种左递归方式来定义 SELECT 语句

2024-02-16

我正在尝试解析以下内容SELECT陈述:

select 1 union all (select 1) union all (with cte as (select 1) select 1 from tbl limit 1) 
union all select 1 union all (select 1 limit 1)

这是我目前拥有的语法(至少能够重现该问题):

parser grammar DBParser;
options { tokenVocab = DBLexer;}

root
    : selectStatement SEMI? EOF
    ;

selectStatement
    : withClause?
    ( selectClause | OPEN_PAREN selectStatement CLOSE_PAREN | selectStatement setOperand selectStatement)
    orderLimitClause?
    ;

withClause
    : WITH IDENTIFIER AS OPEN_PAREN selectClause CLOSE_PAREN
    ;

orderLimitClause
    : LIMIT NUMBER
    ;

selectClause
    : SELECT NUMBER ( FROM IDENTIFIER )?
    ;

setOperand
    : UNION ALL?
    ;
lexer grammar DBLexer;
options { caseInsensitive=true; }
SELECT              :           'SELECT';                   // SELECT *...
LIMIT               :           'LIMIT';                    // ORDER BY x LIMIT 20
ALL                 :           'ALL';                      // SELECT ALL vs. SELECT DISTINCT; WHERE ALL (...); UNION ALL...
UNION               :           'UNION';                    // Set operation
FROM                :           'FROM';                    // Set operation
AS                  :           'AS';                      // Set operation
WITH                :           'WITH';                    // Set operation

SEMI                :           ';';                        // Statement terminator
OPEN_PAREN          :           '(';                        // Function calls, object declarations
CLOSE_PAREN         :           ')';

NUMBER
     : [0-9]+
    ;
IDENTIFIER
    : [A-Z_] [A-Z_0-9]*
    ;
WHITESPACE
    : [ \t\r\n] -> skip
    ;

问题是selectStatement它引用自身而没有可能的替代:

selectStatement
    : withClause?
    ( selectClause | OPEN_PAREN selectStatement <-- here 
    ;

解决这个问题的可能方法是什么?请注意,SQL 语法的主要部分来自here https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax,它给出了事物的一个漂亮的干净/彩色表示(当然我已经简化了select条款以及其他所有内容):


您需要更高级别的规则。也许这个:

selectStatement
   : simpleSelectStatement (setOperand selectStatement)?

simpleSelectStatement
    : withClause?
    ( selectClause | OPEN_PAREN selectStatement CLOSE_PAREN)
    orderLimitClause?
    ;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

删除这种左递归方式来定义 SELECT 语句 的相关文章

随机推荐