Skip to content

Commit 69bf16a

Browse files
authored
tokenizer: support Mustache token (#38)
2 parents 1e335e5 + 01b9513 commit 69bf16a

File tree

1 file changed

+42
-1
lines changed

1 file changed

+42
-1
lines changed

src/tokenizer.rs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ pub enum Token {
104104
UnicodeStringLiteral(String),
105105
/// Hexadecimal string literal: i.e.: X'deadbeef'
106106
HexStringLiteral(String),
107+
/// Interpolated text using Mustache-style syntax, e.g. {{FooBar}}.
108+
Mustache(String),
107109
/// Comma
108110
Comma,
109111
/// Whitespace (space, tab, etc)
@@ -303,6 +305,7 @@ impl fmt::Display for Token {
303305
Token::DoubleQuotedRawStringLiteral(ref s) => write!(f, "R\"{s}\""),
304306
Token::TripleSingleQuotedRawStringLiteral(ref s) => write!(f, "R'''{s}'''"),
305307
Token::TripleDoubleQuotedRawStringLiteral(ref s) => write!(f, "R\"\"\"{s}\"\"\""),
308+
Token::Mustache(ref s) => write!(f, "{{{s}}}"),
306309
Token::Comma => f.write_str(","),
307310
Token::Whitespace(ws) => write!(f, "{ws}"),
308311
Token::DoubleEq => f.write_str("=="),
@@ -1599,7 +1602,45 @@ impl<'a> Tokenizer<'a> {
15991602
_ => Ok(Some(Token::Caret)),
16001603
}
16011604
}
1602-
'{' => self.consume_and_return(chars, Token::LBrace),
1605+
'{' => {
1606+
chars.next(); // consume the '{'
1607+
if let Some('{') = chars.peek() {
1608+
chars.next(); // consume the second '{'
1609+
1610+
let mut s = String::new();
1611+
let mut is_terminated = false;
1612+
let mut prev: Option<char> = None;
1613+
1614+
while let Some(&ch) = chars.peek() {
1615+
if prev == Some('}') {
1616+
if ch == '}' {
1617+
chars.next();
1618+
is_terminated = true;
1619+
break;
1620+
} else {
1621+
s.push('}');
1622+
s.push(ch);
1623+
}
1624+
} else if ch != '}' {
1625+
s.push(ch);
1626+
}
1627+
1628+
prev = Some(ch);
1629+
chars.next();
1630+
}
1631+
1632+
if chars.peek().is_none() && !is_terminated {
1633+
self.tokenizer_error(
1634+
chars.location(),
1635+
"Unterminated mustache interpolation",
1636+
)
1637+
} else {
1638+
Ok(Some(Token::Mustache(s)))
1639+
}
1640+
} else {
1641+
Ok(Some(Token::LBrace))
1642+
}
1643+
}
16031644
'}' => self.consume_and_return(chars, Token::RBrace),
16041645
'#' if dialect_of!(self is SnowflakeDialect | BigQueryDialect | MySqlDialect | HiveDialect) =>
16051646
{

0 commit comments

Comments
 (0)