Antlr rewrite rule output

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

What I want to do is restructure the text consistent with rule2 before it is used / used by rule1. How to do it?

options{ output=template; } rule1 : begin sub-rule2 end ';' -> meth(body={rule1.text}) sub-rule2 : sub-rule3 | sub-rule4 | sub-rule5; 

here "meth" is a call to stringtemplate

If we say that the corrective 4 corresponds to "select * from dual;", I would like this to be passed to rule1 "#sql (select * from dual)".

Here is my valid code. I would like for the instructions matching the select_statement rule to be wrapped in '#sql ()' and passed to the stats list for the body attribute for 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 )+ ; 
+1
source share
1 answer

You can specifically determine which rule can return as follows:

 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 as follows:

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

Pay attention to sub_rule2.x .

EDIT

You can also create a custom method that checks whether the text to be added to the List starts with "select " as follows:

 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}) ; 
+2
source

Source: https://habr.com/ru/post/1380692/


All Articles