我正在尝试编写一个antlr脚本,其中,rule1有一个子规则,rule2。我在规则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 )+
;
答案 0 :(得分:2)
您可以专门定义规则可以返回的内容:
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})
;