antlr 重写规则的输出

发布于 2024-12-15 15:01:12 字数 1726 浏览 2 评论 0原文

我正在尝试编写一个antlr脚本,其中rule1有一个子规则rule2。我在规则 1 上使用 StringTemplate。

我想要做的是在规则 1 消耗/使用规则 2 匹配的文本之前重构它。我该怎么做?

options{
output=template;
}

rule1 :
  begin sub-rule2 end ';' -> meth(body={rule1.text})

sub-rule2 :
   sub-rule3
 | sub-rule4
 | sub-rule5;

这里“meth”是字符串模板调用

如果说子规则4匹配“select * from Dual;”,我希望将其传递给规则1“#sql (select * from Dual);”。

这是我的实际代码,我希望将 select_statement 规则匹配的语句包装在“#sql()”中,并在“stats”列表中传递到“meth”模板的“body”属性:

body 
@init {
      List stats = new ArrayList();
    }   :   
    BEGIN s=statement{ stats.add($s.text); } SEMI ( s=statement{ stats.add($s.text); } SEMI | pragma SEMI )*
    ( EXCEPTION exception_handler+ )? END ID? -> method(modifiers={"public"},returnType={"void"},name={"execute"},body={stats})
    ;


statement :
    label*
    ( assign_or_call_statement
    | case_statement
    | close_statement
    | continue_statement
    | basic_loop_statement
    | execute_immediate_statement
    | exit_statement
    | fetch_statement
    | for_loop_statement
    | forall_statement
    | goto_statement
    | if_statement
    | null_statement
    | open_statement
    | plsql_block
    | raise_statement
    | return_statement
    | sql_statement 
    | while_loop_statement
    ) 
    ;

    sql_statement
    : (commit_statement
    | delete_statement
    | insert_statement
    | lock_table_statement
    | rollback_statement
    | savepoint_statement
    | select_statement 
    | set_transaction_statement
    | update_statement )
    ;


    select_statement :
        SELECT swallow_to_semi 
    ;

    SELECT  :   'select';

    swallow_to_semi :
        ~( SEMI )+
    ;

I am trying to write an antlr script where in, rule1 has a subrule , rule2. I am using StringTemplate on rule 1.

What I want to do, is restructure the text matched by rule2 before it is consumed/used by rule1. How do I do that ?

options{
output=template;
}

rule1 :
  begin sub-rule2 end ';' -> meth(body={rule1.text})

sub-rule2 :
   sub-rule3
 | sub-rule4
 | sub-rule5;

here "meth" is the stringtemplate call

If say sub-rule 4 matches "select * from dual;", I would like this to be passed to rule1 "#sql (select * from dual);".

Here is my Actual code I would like the statements matched by the select_statement rule to be wrapped in '#sql()' and to be passed in "stats" list to the "body" attribute of the "meth" template :

body 
@init {
      List stats = new ArrayList();
    }   :   
    BEGIN s=statement{ stats.add($s.text); } SEMI ( s=statement{ stats.add($s.text); } SEMI | pragma SEMI )*
    ( EXCEPTION exception_handler+ )? END ID? -> method(modifiers={"public"},returnType={"void"},name={"execute"},body={stats})
    ;


statement :
    label*
    ( assign_or_call_statement
    | case_statement
    | close_statement
    | continue_statement
    | basic_loop_statement
    | execute_immediate_statement
    | exit_statement
    | fetch_statement
    | for_loop_statement
    | forall_statement
    | goto_statement
    | if_statement
    | null_statement
    | open_statement
    | plsql_block
    | raise_statement
    | return_statement
    | sql_statement 
    | while_loop_statement
    ) 
    ;

    sql_statement
    : (commit_statement
    | delete_statement
    | insert_statement
    | lock_table_statement
    | rollback_statement
    | savepoint_statement
    | select_statement 
    | set_transaction_statement
    | update_statement )
    ;


    select_statement :
        SELECT swallow_to_semi 
    ;

    SELECT  :   'select';

    swallow_to_semi :
        ~( SEMI )+
    ;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

沉睡月亮 2024-12-22 15:01:12

您可以像这样具体定义规则可以返回什么:

sub_rule2 returns [String x] 
  :  sub_rule3 {$x = ... }
  |  sub_rule4 {$x = "#sql (" + $sub_rule4.text + ");";}
  |  sub_rule5 {$x = ... }
  ;

现在 sub_rule2 返回一个 String x,您可以像这样使用它:

rule1
  :  ... sub_rule2 ... -> meth(body={sub_rule2.x})
  ;

注意 sub_rule2.x >。

编辑

您还可以创建一个自定义方法来检查要添加到 List 的文本是否以 "select " 开头,如下所示:

grammar YourGrammarName;

options{
  output=template;
}

@parser::members {
  private void addStat(String stat, List<String statList>) {
    // 1. if `stat` starts with "select ", wrap "#sql(...)" around it.
    // 2. add `stat` to `statList`
  }
}

body 
@init {
  List<String> stats = new ArrayList<String>();
}   
  :  BEGIN s=statement { addStat($s.text, stats); } SEMI 
     ( s=statement     { addStat($s.text, stats); } SEMI 
     | pragma                                      SEMI
     )*
     (EXCEPTION exception_handler+)? END ID? 

     -> method(modifiers={"public"},returnType={"void"},name={"execute"},body={stats})
  ;

You can specifically define what a rule can return like this:

sub_rule2 returns [String x] 
  :  sub_rule3 {$x = ... }
  |  sub_rule4 {$x = "#sql (" + $sub_rule4.text + ");";}
  |  sub_rule5 {$x = ... }
  ;

Now sub_rule2 returns a String x which you can use like this:

rule1
  :  ... sub_rule2 ... -> meth(body={sub_rule2.x})
  ;

Note the sub_rule2.x.

EDIT

You could also create a custom method that checks if the text to be added to the List starts with "select " like this:

grammar YourGrammarName;

options{
  output=template;
}

@parser::members {
  private void addStat(String stat, List<String statList>) {
    // 1. if `stat` starts with "select ", wrap "#sql(...)" around it.
    // 2. add `stat` to `statList`
  }
}

body 
@init {
  List<String> stats = new ArrayList<String>();
}   
  :  BEGIN s=statement { addStat($s.text, stats); } SEMI 
     ( s=statement     { addStat($s.text, stats); } SEMI 
     | pragma                                      SEMI
     )*
     (EXCEPTION exception_handler+)? END ID? 

     -> method(modifiers={"public"},returnType={"void"},name={"execute"},body={stats})
  ;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文