1pub mod tokens;
2pub mod others;
3pub mod reindent;
4pub mod aligned_indent;
5
6use super::{Token, TokenList, TokenType};
7pub use tokens::{IdentifierCaseFilter, KeywordCaseFilter};
8pub use others::{StripWhitespaceFilter, StripCommentsFilter, StripBeforeNewline, SpacesAroundOperatorsFilter};
9pub use reindent::ReindentFilter;
10pub use aligned_indent::AlignedIndentFilter;
11
12pub trait Filter: Send+Sync {
13 fn process(&self, token: &mut Token);
14}
15
16pub trait StmtFilter: Send+Sync {
18 fn process(&self, tokens: &mut Vec<Token>);
19}
20
21
22pub trait TokenListFilter: Send+Sync {
23 fn process(&mut self, token_list: &mut TokenList);
24}
25
26const SPLIT_WORDS: [&str; 12] = ["FROM", "AND", "OR", "GROUP BY",
27 "ORDER BY", "UNION", "VALUES", "SET", "BETWEEN", "EXCEPT", "HAVING", "LIMIT"];
28
29const SPLIT_WORDS_ALIGN: [&str; 14] = ["FROM", "ON", "WHERE", "AND", "OR",
30"GROUP BY", "ORDER BY","UNION", "VALUES",
31"SET", "BETWEEN", "EXCEPT", "HAVING", "LIMIT"];
32
33fn next_token(token_list: &TokenList, idx: usize) -> Option<usize> {
34 next_token_internal(token_list, idx, &SPLIT_WORDS)
35}
36
37fn next_token_align(token_list: &TokenList, idx: usize) -> Option<usize> {
38 next_token_internal(token_list, idx, &SPLIT_WORDS_ALIGN)
39}
40
41fn next_token_internal(token_list: &TokenList, idx: usize, split_words: &[&str]) -> Option<usize> {
42 let mut tidx = token_list.token_next_by_fn(|t| match t.typ {
43 TokenType::Keyword => split_words.iter().find(|w| **w == t.normalized).is_some() || t.normalized.ends_with("STRAIGHT_JOIN") || t.normalized.ends_with("JOIN"),
44 _ => false
45 } , idx);
46 let token = token_list.token_idx(tidx);
47 if token.map(|t| t.normalized == "BETWEEN").unwrap_or(false) {
48 tidx = next_token_internal(token_list, tidx.unwrap()+1, split_words);
49 let token = token_list.token_idx(tidx);
50 if token.map(|t| t.normalized == "AND").unwrap_or(false) {
51 tidx = next_token_internal(token_list, tidx.unwrap()+1, split_words);
52 }
53 }
54 tidx
55}