1

rule1 に subrule 、 rule2 がある antlr スクリプトを作成しようとしています。ルール 1 で StringTemplate を使用しています。

私がやりたいことは、rule1 によって消費/使用される前に、rule2 に一致するテキストを再構築することです。それ、どうやったら出来るの ?

options{
output=template;
}

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

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

ここで「meth」はstringtemplate呼び出しです

サブルール 4 が "select * from dual;" に一致する場合、これを rule1 "#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 )+
    ;
4

1 に答える 1

2

次のように、ルールが何を返すことができるかを具体的に定義できます。

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

次のように使用できるsub_rule2a を返します。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})
  ;
于 2011-11-14T08:21:46.127 に答える