rbatis_codegen/codegen/
parser_pysql.rs1use crate::codegen::parser_html::parse_html;
2use crate::codegen::proc_macro::TokenStream;
3use crate::codegen::syntax_tree_pysql::bind_node::BindNode;
4use crate::codegen::syntax_tree_pysql::break_node::BreakNode;
5use crate::codegen::syntax_tree_pysql::choose_node::ChooseNode;
6use crate::codegen::syntax_tree_pysql::continue_node::ContinueNode;
7use crate::codegen::syntax_tree_pysql::error::Error;
8use crate::codegen::syntax_tree_pysql::foreach_node::ForEachNode;
9use crate::codegen::syntax_tree_pysql::if_node::IfNode;
10use crate::codegen::syntax_tree_pysql::otherwise_node::OtherwiseNode;
11use crate::codegen::syntax_tree_pysql::set_node::SetNode;
12use crate::codegen::syntax_tree_pysql::string_node::StringNode;
13use crate::codegen::syntax_tree_pysql::trim_node::TrimNode;
14use crate::codegen::syntax_tree_pysql::when_node::WhenNode;
15use crate::codegen::syntax_tree_pysql::where_node::WhereNode;
16use crate::codegen::syntax_tree_pysql::{DefaultName, Name, NodeType};
17use crate::codegen::ParseArgs;
18use quote::ToTokens;
19use std::collections::HashMap;
20use syn::ItemFn;
21
22pub trait ParsePySql {
23 fn parse_pysql(arg: &str) -> Result<Vec<NodeType>, Error>;
24}
25
26pub fn impl_fn_py(m: &ItemFn, args: &ParseArgs) -> TokenStream {
27 let fn_name = m.sig.ident.to_string();
28 let mut data = {
29 let mut s = String::new();
30 for x in &args.sqls {
31 s = s + &x.to_token_stream().to_string();
32 }
33 s
34 };
35 if data.ne("\"\"") && data.starts_with("\"") && data.ends_with("\"") {
36 data = data[1..data.len() - 1].to_string();
37 }
38 data = data.replace("\\n", "\n");
39 let nodes = NodeType::parse_pysql(&data).expect("[rbatis-codegen] parse py_sql fail!");
40 let htmls = crate::codegen::syntax_tree_pysql::to_html(
41 &nodes,
42 data.starts_with("select") || data.starts_with(" select"),
43 &fn_name,
44 );
45 return parse_html(&htmls, &fn_name, &mut vec![]).into();
46}
47
48impl ParsePySql for NodeType {
49 fn parse_pysql(arg: &str) -> Result<Vec<NodeType>, Error> {
51 let line_space_map = Self::create_line_space_map(&arg);
52 let mut main_node = vec![];
53 let ls = arg.lines();
54 let mut space = -1;
55 let mut line = -1;
56 let mut skip = -1;
57 for x in ls {
58 line += 1;
59 if x.is_empty() || (skip != -1 && line <= skip) {
60 continue;
61 }
62 let count_index = *line_space_map
63 .get(&line)
64 .ok_or_else(|| Error::from(format!("line_space_map not heve line:{}", line)))?;
65 if space == -1 {
66 space = count_index;
67 }
68 let (child_str, do_skip) =
69 Self::find_child_str(line, count_index, arg, &line_space_map);
70 if do_skip != -1 && do_skip >= skip {
71 skip = do_skip;
72 }
73 let parserd;
74 if !child_str.is_empty() {
75 parserd = Self::parse_pysql(child_str.as_str())?;
76 } else {
77 parserd = vec![];
78 }
79 Self::parse_pysql_node(
80 &mut main_node,
81 x,
82 *line_space_map
83 .get(&line)
84 .ok_or_else(|| Error::from(format!("line:{} not exist!", line)))?
85 as usize,
86 parserd,
87 )?;
88 }
89 return Ok(main_node);
90 }
91}
92
93impl NodeType {
94 fn parse_pysql_node(
95 main_node: &mut Vec<NodeType>,
96 x: &str,
97 space: usize,
98 mut childs: Vec<NodeType>,
99 ) -> Result<(), Error> {
100 let mut trim_x = x.trim();
101 if trim_x.starts_with("//") {
102 return Ok(());
103 }
104 if trim_x.ends_with(":") {
105 trim_x = trim_x[0..trim_x.len() - 1].trim();
106 if trim_x.contains(": ") {
107 let vecs: Vec<&str> = trim_x.split(": ").collect();
108 if vecs.len() > 1 {
109 let len = vecs.len();
110 for index in 0..len {
111 let index = len - 1 - index;
112 let item = vecs[index];
113 childs = vec![Self::parse_trim_node(item, x, childs)?];
114 if index == 0 {
115 for x in &childs {
116 main_node.push(x.clone());
117 }
118 return Ok(());
119 }
120 }
121 }
122 }
123 let node = Self::parse_trim_node(trim_x, x, childs)?;
124 main_node.push(node);
125 return Ok(());
126 } else {
127 let mut data;
129 if space <= 1 {
130 data = x.to_string();
131 } else {
132 data = x[(space - 1)..].to_string();
133 }
134 data = data.trim().to_string();
135 main_node.push(NodeType::NString(StringNode { value: data }));
136 for x in childs {
137 main_node.push(x);
138 }
139 return Ok(());
140 }
141 }
142
143 fn count_space(arg: &str) -> i32 {
144 let cs = arg.chars();
145 let mut index = 0;
146 for x in cs {
147 match x {
148 ' ' => {
149 index += 1;
150 }
151 _ => {
152 break;
153 }
154 }
155 }
156 return index;
157 }
158
159 fn find_child_str(
161 line_index: i32,
162 space_index: i32,
163 arg: &str,
164 m: &HashMap<i32, i32>,
165 ) -> (String, i32) {
166 let mut result = String::new();
167 let mut skip_line = -1;
168 let mut line = -1;
169 let lines = arg.lines();
170 for x in lines {
171 line += 1;
172 if line > line_index {
173 let cached_space = *m.get(&line).expect("line not exists");
174 if cached_space > space_index {
175 result = result + x + "\n";
176 skip_line = line;
177 } else {
178 break;
179 }
180 }
181 }
182 return (result, skip_line);
183 }
184
185 fn create_line_space_map(arg: &str) -> HashMap<i32, i32> {
187 let mut m = HashMap::with_capacity(100);
188 let lines = arg.lines();
189 let mut line = -1;
190 for x in lines {
191 line += 1;
192 let space = Self::count_space(x);
193 m.insert(line, space);
195 }
196 return m;
197 }
198
199 fn parse_trim_node(
200 trim_express: &str,
201 source_str: &str,
202 childs: Vec<NodeType>,
203 ) -> Result<NodeType, Error> {
204 if trim_express.starts_with(IfNode::name()) {
205 return Ok(NodeType::NIf(IfNode {
206 childs,
207 test: trim_express.trim_start_matches("if ").to_string(),
208 }));
209 } else if trim_express.starts_with(ForEachNode::name()) {
210 let for_tag = "for";
211 if !trim_express.starts_with(for_tag) {
212 return Err(Error::from(
213 "[rbatis-codegen] parser express fail:".to_string() + source_str,
214 ));
215 }
216 let in_tag = " in ";
217 if !trim_express.contains(in_tag) {
218 return Err(Error::from(
219 "[rbatis-codegen] parser express fail:".to_string() + source_str,
220 ));
221 }
222 let in_index = trim_express
223 .find(in_tag)
224 .ok_or_else(|| Error::from(format!("{} not have {}", trim_express, in_tag)))?;
225 let col = trim_express[in_index + in_tag.len()..].trim();
226 let mut item = trim_express[for_tag.len()..in_index].trim();
227 let mut index = "";
228 if item.contains(",") {
229 let splits: Vec<&str> = item.split(",").collect();
230 if splits.len() != 2 {
231 panic!("[rbatis-codegen_codegen] for node must be 'for key,item in col:'");
232 }
233 index = splits[0];
234 item = splits[1];
235 }
236 return Ok(NodeType::NForEach(ForEachNode {
237 childs,
238 collection: col.to_string(),
239 index: index.to_string(),
240 item: item.to_string(),
241 }));
242 } else if trim_express.starts_with(TrimNode::name()) {
243 let trim_express = trim_express.trim().trim_start_matches("trim ").trim();
244 if trim_express.starts_with("'") && trim_express.ends_with("'")
245 || trim_express.starts_with("`") && trim_express.ends_with("`")
246 {
247 let mut trim_express = trim_express;
248 if trim_express.starts_with("`") && trim_express.ends_with("`") {
249 trim_express = trim_express.trim_start_matches("`").trim_end_matches("`");
250 } else if trim_express.starts_with("'") && trim_express.ends_with("'") {
251 trim_express = trim_express.trim_start_matches("'").trim_end_matches("'");
252 }
253 return Ok(NodeType::NTrim(TrimNode {
254 childs,
255 start: trim_express.to_string(),
256 end: trim_express.to_string(),
257 }));
258 } else if trim_express.contains("=") || trim_express.contains(",") {
259 let express: Vec<&str> = trim_express.split(",").collect();
260 let mut prefix = "";
261 let mut suffix = "";
262 for mut expr in express {
263 expr = expr.trim();
264 if expr.starts_with("start") {
265 prefix = expr
266 .trim_start_matches("start")
267 .trim()
268 .trim_start_matches("=")
269 .trim()
270 .trim_start_matches("'")
271 .trim_end_matches("'")
272 .trim_start_matches("`")
273 .trim_end_matches("`");
274 } else if expr.starts_with("end") {
275 suffix = expr
276 .trim_start_matches("end")
277 .trim()
278 .trim_start_matches("=")
279 .trim()
280 .trim_start_matches("'")
281 .trim_end_matches("'")
282 .trim_start_matches("`")
283 .trim_end_matches("`");
284 } else {
285 return Err(Error::from(format!("[rbatis-codegen] express trim node error, for example trim 'value': trim start='value': trim start='value',end='value': express = {}", trim_express)));
286 }
287 }
288 return Ok(NodeType::NTrim(TrimNode {
289 childs,
290 start: prefix.to_string(),
291 end: suffix.to_string(),
292 }));
293 } else {
294 return Err(Error::from(format!("[rbatis-codegen] express trim node error, for example trim 'value': trim start='value': trim start='value',end='value': error express = {}", trim_express)));
295 }
296 } else if trim_express.starts_with(ChooseNode::name()) {
297 let mut node = ChooseNode {
298 when_nodes: vec![],
299 otherwise_node: None,
300 };
301 for x in childs {
302 match x {
303 NodeType::NWhen(_) => {
304 node.when_nodes.push(x);
305 }
306 NodeType::NOtherwise(_) => {
307 node.otherwise_node = Some(Box::new(x));
308 }
309 _ => {
310 return Err(Error::from("[rbatis-codegen] parser node fail,choose node' child must be when and otherwise nodes!".to_string()));
311 }
312 }
313 }
314 return Ok(NodeType::NChoose(node));
315 } else if trim_express.starts_with(OtherwiseNode::default_name())
316 || trim_express.starts_with(OtherwiseNode::name())
317 {
318 return Ok(NodeType::NOtherwise(OtherwiseNode { childs }));
319 } else if trim_express.starts_with(WhenNode::name()) {
320 let trim_express = trim_express[WhenNode::name().len()..].trim();
321 return Ok(NodeType::NWhen(WhenNode {
322 childs,
323 test: trim_express.to_string(),
324 }));
325 } else if trim_express.starts_with(BindNode::default_name())
326 || trim_express.starts_with(BindNode::name())
327 {
328 let express;
329 if trim_express.starts_with(BindNode::default_name()) {
330 express = trim_express[BindNode::default_name().len()..].trim();
331 } else {
332 express = trim_express[BindNode::name().len()..].trim();
333 }
334 let name_value: Vec<&str> = express.split("=").collect();
335 if name_value.len() != 2 {
336 return Err(Error::from(
337 "[rbatis-codegen] parser bind express fail:".to_string() + trim_express,
338 ));
339 }
340 return Ok(NodeType::NBind(BindNode {
341 name: name_value[0].to_owned().trim().to_string(),
342 value: name_value[1].to_owned().trim().to_string(),
343 }));
344 } else if trim_express.starts_with(SetNode::name()) {
345 return Ok(NodeType::NSet(SetNode { childs }));
346 } else if trim_express.starts_with(WhereNode::name()) {
347 return Ok(NodeType::NWhere(WhereNode { childs }));
348 } else if trim_express.starts_with(ContinueNode::name()) {
349 return Ok(NodeType::NContinue(ContinueNode {}));
350 } else if trim_express.starts_with(BreakNode::name()) {
351 return Ok(NodeType::NBreak(BreakNode {}));
352 } else {
353 return Err(Error::from(
355 "[rbatis-codegen] unknow tag: ".to_string() + source_str,
356 ));
357 }
358 }
359}