Skip to content

Commit e83a0d4

Browse files
author
Альберт Скальт
committed
add ability to map tokens during tokenization
This patch adds a method to map tokens with provided mapper during tokenization. This way tokens could be replaced without an additional pass.
1 parent e4c5500 commit e83a0d4

1 file changed

Lines changed: 44 additions & 1 deletion

File tree

src/tokenizer.rs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -934,6 +934,16 @@ impl<'a> Tokenizer<'a> {
934934
pub fn tokenize_with_location_into_buf(
935935
&mut self,
936936
buf: &mut Vec<TokenWithSpan>,
937+
) -> Result<(), TokenizerError> {
938+
self.tokenize_with_location_into_buf_with_mapper(buf, |token| token)
939+
}
940+
941+
/// Tokenize the statement and produce a vector of tokens, mapping each token
942+
/// with provided `mapper`
943+
pub fn tokenize_with_location_into_buf_with_mapper(
944+
&mut self,
945+
buf: &mut Vec<TokenWithSpan>,
946+
mut mapper: impl FnMut(TokenWithSpan) -> TokenWithSpan,
937947
) -> Result<(), TokenizerError> {
938948
let mut state = State {
939949
peekable: self.query.chars().peekable(),
@@ -945,7 +955,8 @@ impl<'a> Tokenizer<'a> {
945955
while let Some(token) = self.next_token(&mut state, buf.last().map(|t| &t.token))? {
946956
let span = location.span_to(state.location());
947957

948-
buf.push(TokenWithSpan { token, span });
958+
let token = TokenWithSpan { token, span };
959+
buf.push(mapper(token));
949960

950961
location = state.location();
951962
}
@@ -2590,6 +2601,38 @@ mod tests {
25902601
compare(expected, tokens);
25912602
}
25922603

2604+
#[test]
2605+
fn tokenize_with_mapper() {
2606+
let sql = String::from("SELECT ?");
2607+
let dialect = GenericDialect {};
2608+
let mut param_num = 1;
2609+
2610+
let mut tokens = vec![];
2611+
Tokenizer::new(&dialect, &sql)
2612+
.tokenize_with_location_into_buf_with_mapper(&mut tokens, |mut token_span| {
2613+
token_span.token = match token_span.token {
2614+
Token::Placeholder(n) => Token::Placeholder(if n == "?" {
2615+
let ret = format!("${}", param_num);
2616+
param_num += 1;
2617+
ret
2618+
} else {
2619+
n
2620+
}),
2621+
token => token,
2622+
};
2623+
token_span
2624+
})
2625+
.unwrap();
2626+
let actual = tokens.into_iter().map(|t| t.token).collect();
2627+
let expected = vec![
2628+
Token::make_keyword("SELECT"),
2629+
Token::Whitespace(Whitespace::Space),
2630+
Token::Placeholder("$1".to_string()),
2631+
];
2632+
2633+
compare(expected, actual);
2634+
}
2635+
25932636
#[test]
25942637
fn tokenize_clickhouse_double_equal() {
25952638
let sql = String::from("SELECT foo=='1'");

0 commit comments

Comments
 (0)