对Hplsql.g4或Hive.g4的阵列支持

对Hplsql.g4或Hive.g4的阵列支持,hive,antlr4,Hive,Antlr4,大家好,, 我正在使用antlr4为配置单元SQL(Hplsql.g4)创建解析器和词法分析器。 我相信这是最新的语法文件。 但是,我发现至少需要添加两个索引:IF和数组索引。 例如,在select语句中,我可能有: a) 从x中选择(a>8,12,20) b) 从x中选择列名称[2] 这两者在配置单元中都是有效的,但是当我从上面的Hplsql.g4创建java解析器和lexer时,它们都不会解析。我为IF添加了一个表达式,它似乎可以工作 我补充说 expr : ...

大家好,, 我正在使用antlr4为配置单元SQL(Hplsql.g4)创建解析器和词法分析器。
我相信这是最新的语法文件。

但是,我发现至少需要添加两个索引:IF和数组索引。 例如,在select语句中,我可能有: a) 从x中选择(a>8,12,20)
b) 从x中选择列名称[2]

这两者在配置单元中都是有效的,但是当我从上面的Hplsql.g4创建java解析器和lexer时,它们都不会解析。我为IF添加了一个表达式,它似乎可以工作

我补充说

 expr :
     ...
     | expr_if  //I added
还有一条新规则:

expr_if : 
       T_IF T_OPEN_P bool_expr T_COMMA expr T_COMMA expr T_CLOSE_P  //I added
     ;
但是,找出如何允许数组索引并不容易,因为语法允许别名:

select a from x
select a alias_of_a from x
select a[1] from x
select a[1] alias_of_a from x
都应该是有效的。 我尝试为此添加一个新表达式,如下所示:

expr :
     ...
     | expr_array //I added

expr_array : 
       T_OPEN_SB L_INT T_OPEN_CB  //I added
     ;
这对我不起作用。(T_OPEN_SB L_INT T_OPEN_CB分别为[整数])。我也尝试了很多不同的方法。我的问题是:

  • 我是否使用了正确的语法文件-如果没有,是否有一个新的语法文件具有if和数组处理
  • 有人成功地扩展了这个语法来处理我上面的案例吗

  • 根据Bart的建议: 我更新了标识。
    我更新了expr\u atom。
    我添加了数组索引。
    我之前已经注释掉了“[”*?“]”

    测试Sql:从t中选择[0]
    结果: 第1行:8输入“selecta[0]”时没有可行的替代方案
    第1行:8不匹配的输入“[0]”

    树 (程序(块stmt(stmt选择)(stmt(expr_stmt)(expr(expr_原子(标识a 1077;ее))))[0]自t)

    我觉得这个问题与下面选择的别名有关。 当包含ident和T_的select_list_别名为可选时,ident与数组索引匹配。 我无法解释为什么会发生这种情况,特别是因为ident已经更新

    摘自Hplsql.sql:

    select_list :           
           select_list_set? select_list_limit? select_list_item (T_COMMA select_list_item)*
         ;
    select_list_item :
           (ident T_EQUAL)? expr select_list_alias? 
         | select_list_asterisk   
         ;
    select_list_alias :
           {!_input.LT(1).getText().equalsIgnoreCase("INTO") && !_input.LT(1).getText().equalsIgnoreCase("FROM")}? T_AS? ident
         | T_OPEN_P T_TITLE L_S_STRING T_CLOSE_P
         ;
    
    如果我将一个简单的SQL stmt传递给grun,例如

    select a[1] from t
    
    解析树的外观应类似于以下内容:

    我希望看到的不是expr_atom,而是expr_数组,它将拆分为a的expr_atom和[1]的array_索引

    请注意,这里有一条SQL语句。在我现有的g4中,数组索引[1](以及stmt的其余部分)被解析为一个单独的SQL语句

    Bart,我从你的解析树中看到,解析导致了“从t中选择a[0]”中的两条SQL语句——我得到了相同的情况


    我将继续探索不同的方法-我仍然怀疑select_list_别名,它有
    T_AS?结尾处的标识
    。为了确认,我已经注释掉了ident_part中的一行,如下所示://|“[”.*?]”

    如注释中所述:
    […]
    将标记为
    L_ID
    标记。如果你没有;如果您不想这样做,请删除
    |'['.*.']'
    部分:

    fragment
    L_ID_PART  :
                 [a-zA-Z] ([a-zA-Z] | L_DIGIT | '_')*                           // Identifier part
                | ('_' | '@' | ':' | '#' | '$') ([a-zA-Z] | L_DIGIT | '_' | '@' | ':' | '#' | '$')+     // (at least one char must follow special char)
                | '"' .*? '"'                                                   // Quoted identifiers
                // | '[' .*? ']' <-- removed
                | '`' .*? '`'
                ;
    
    它将正确地解析
    从[identifier]
    中选择一个[1]别名\u of a,但对整个语法(或对HPL/SQL的深入了解)没有很好的了解,无法确定这是否会搞乱其他事情:)

    编辑 根据我提议的修改,语法如下:(由于字符限制,我无法在此发布)

    解析
    从t
    中选择[0],这将导致解析树:

    并且解析
    从[t]
    中选择[0],这将导致此解析树:

    您还可以通过运行以下Java代码对其进行测试:

    String source=“从[t]中选择[0]”;
    HplsqlLexer lexer=新的HplsqlLexer(CharStreams.fromString(source));
    HplsqlParser parser=newhplsqlparser(newcommontokenstream(lexer));
    ParseTree root=parser.program();
    JFrame=新JFrame(“Antlr AST”);
    JPanel面板=新的JPanel();
    TreeViewer=newTreeViewer(Arrays.asList(parser.getRuleNames()),root);
    查看器设置刻度(1.5);
    面板。添加(查看器);
    框架。添加(面板);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack();
    frame.setVisible(true);
    
    嗨,巴特,谢谢你的评论。是的,我在语法里看到了。看起来像是选择列表别名:{!\u input.LT(1).getText().equalsIgnoreCase(“INTO”)和&!\u input.LT(1).getText().equalsIgnoreCase(“FROM”)}?图亚斯?ident导致了与ident的匹配,但是,我认为解析器首先匹配最长的规则(最长的令牌集)。巴特,谢谢你-我将阅读。我正在考虑删除单独的标记“[”和“]”,以便将它们专用于数组索引大小写(作为解析器规则)。我担心这是一个糟糕的方法。如果我明白你的意思,就没有办法添加数组索引处理了?回答得很好。事实上,我并没有说我已经注释掉了://|'['.*.']'巴特,我在原始帖子的末尾添加了我的测试结果-我的评论中没有足够的空间。请检查我的编辑@MikeLapenna。不确定我的观点是否被理解:
    '['.*?']'
    需要删除,否则它将无法工作,因为lexer是如何工作的(此处解释:)签出my EDIT@Bart(再次感谢您对此的研究)。注意,解析结果是一个SQL smt。啊,两个stmt,是的,我刚才看到了。嗯,我想我没有一个快速的解决办法。如果我能花更多的时间在上面,我可能会看看语法,否则我会删除这个答案。
    expr_atom :
           date_literal
         | timestamp_literal
         | bool_literal
         | expr_array // <-- added
         | ident
         | string
         | dec_number
         | int_number
         | null_const
         ;
    
    // new rule
    expr_array
         : ident array_index+
         ;
    
    // new rule
    array_index
         : T_OPEN_SB expr T_CLOSE_SB
         ;
    
    ident :
           L_ID
         | T_OPEN_SB ~T_CLOSE_SB+ T_CLOSE_SB // <-- added
         | non_reserved_words
         ;