Skip to content

Commit 6bbe574

Browse files
committed
Simplify parsing method
1 parent 070d5b3 commit 6bbe574

File tree

1 file changed

+59
-68
lines changed

1 file changed

+59
-68
lines changed

src/tokenizer.rs

Lines changed: 59 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1046,12 +1046,13 @@ impl<'a> Tokenizer<'a> {
10461046
Some(&q @ 'q') | Some(&q @ 'Q') if dialect_of!(self is OracleDialect | GenericDialect) =>
10471047
{
10481048
chars.next(); // consume and check the next char
1049-
self.tokenize_word_or_quote_delimited_string(
1050-
chars,
1051-
&[n, q],
1052-
Token::NationalQuoteDelimitedStringLiteral,
1053-
)
1054-
.map(Some)
1049+
if let Some('\'') = chars.peek() {
1050+
self.tokenize_quote_delimited_string(chars, &[n, q])
1051+
.map(|s| Some(Token::NationalQuoteDelimitedStringLiteral(s)))
1052+
} else {
1053+
let s = self.tokenize_word(String::from_iter([n, q]), chars);
1054+
Ok(Some(Token::make_word(&s, None)))
1055+
}
10551056
}
10561057
_ => {
10571058
// regular identifier starting with an "N"
@@ -1062,12 +1063,13 @@ impl<'a> Tokenizer<'a> {
10621063
}
10631064
q @ 'Q' | q @ 'q' if dialect_of!(self is OracleDialect | GenericDialect) => {
10641065
chars.next(); // consume and check the next char
1065-
self.tokenize_word_or_quote_delimited_string(
1066-
chars,
1067-
&[q],
1068-
Token::QuoteDelimitedStringLiteral,
1069-
)
1070-
.map(Some)
1066+
if let Some('\'') = chars.peek() {
1067+
self.tokenize_quote_delimited_string(chars, &[q])
1068+
.map(|s| Some(Token::QuoteDelimitedStringLiteral(s)))
1069+
} else {
1070+
let s = self.tokenize_word(q, chars);
1071+
Ok(Some(Token::make_word(&s, None)))
1072+
}
10711073
}
10721074
// PostgreSQL accepts "escape" string constants, which are an extension to the SQL standard.
10731075
x @ 'e' | x @ 'E' if self.dialect.supports_string_escape_constant() => {
@@ -2024,72 +2026,61 @@ impl<'a> Tokenizer<'a> {
20242026
)
20252027
}
20262028

2027-
/// Reads a quote delimited string without "backslash escaping" or a word
2028-
/// depending on `chars.next()` delivering a `'`.
2029+
/// Reads a quote delimited string expecting `chars.next()` to deliver a quote.
20292030
///
20302031
/// See <https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/Literals.html#GUID-1824CBAA-6E16-4921-B2A6-112FB02248DA>
2031-
fn tokenize_word_or_quote_delimited_string(
2032+
fn tokenize_quote_delimited_string(
20322033
&self,
20332034
chars: &mut State,
20342035
// the prefix that introduced the possible literal or word,
20352036
// e.g. "Q" or "nq"
2036-
word_prefix: &[char],
2037-
// turns an identified quote string literal,
2038-
// ie. `(start-quote-char, string-literal, end-quote-char)`
2039-
// into a token
2040-
as_literal: fn(QuoteDelimitedString) -> Token,
2041-
) -> Result<Token, TokenizerError> {
2042-
match chars.peek() {
2043-
Some('\'') => {
2044-
chars.next();
2045-
// ~ determine the "quote character(s)"
2046-
let error_loc = chars.location();
2047-
let (start_quote, end_quote) = match chars.next() {
2048-
// ~ "newline" is not allowed by Oracle's SQL Reference,
2049-
// but works with sql*plus nevertheless
2050-
None | Some(' ') | Some('\t') | Some('\r') | Some('\n') => {
2051-
return self.tokenizer_error(
2052-
error_loc,
2053-
format!(
2054-
"Invalid space, tab, newline, or EOF after '{}''.",
2055-
String::from_iter(word_prefix)
2056-
),
2057-
);
2058-
}
2059-
Some(c) => (
2060-
c,
2061-
match c {
2062-
'[' => ']',
2063-
'{' => '}',
2064-
'<' => '>',
2065-
'(' => ')',
2066-
c => c,
2067-
},
2037+
literal_prefix: &[char],
2038+
) -> Result<QuoteDelimitedString, TokenizerError> {
2039+
let literal_start_loc = chars.location();
2040+
chars.next();
2041+
2042+
let start_quote_loc = chars.location();
2043+
let (start_quote, end_quote) = match chars.next() {
2044+
// ~ "newline" is not allowed by Oracle's SQL Reference,
2045+
// but works with sql*plus nevertheless
2046+
None | Some(' ') | Some('\t') | Some('\r') | Some('\n') => {
2047+
return self.tokenizer_error(
2048+
start_quote_loc,
2049+
format!(
2050+
"Invalid space, tab, newline, or EOF after '{}''.",
2051+
String::from_iter(literal_prefix)
20682052
),
2069-
};
2070-
// read the string literal until the "quote character" following a by literal quote
2071-
let mut value = String::new();
2072-
while let Some(ch) = chars.next() {
2073-
if ch == end_quote {
2074-
if let Some('\'') = chars.peek() {
2075-
chars.next(); // ~ consume the quote
2076-
return Ok(as_literal(QuoteDelimitedString {
2077-
start_quote,
2078-
value,
2079-
end_quote,
2080-
}));
2081-
}
2082-
}
2083-
value.push(ch);
2084-
}
2085-
self.tokenizer_error(error_loc, "Unterminated string literal")
2053+
);
20862054
}
2087-
// ~ not a literal introduced with _token_prefix_, assm
2088-
_ => {
2089-
let s = self.tokenize_word(String::from_iter(word_prefix), chars);
2090-
Ok(Token::make_word(&s, None))
2055+
Some(c) => (
2056+
c,
2057+
match c {
2058+
'[' => ']',
2059+
'{' => '}',
2060+
'<' => '>',
2061+
'(' => ')',
2062+
c => c,
2063+
},
2064+
),
2065+
};
2066+
2067+
// read the string literal until the "quote character" following a by literal quote
2068+
let mut value = String::new();
2069+
while let Some(ch) = chars.next() {
2070+
if ch == end_quote {
2071+
if let Some('\'') = chars.peek() {
2072+
chars.next(); // ~ consume the quote
2073+
return Ok(QuoteDelimitedString {
2074+
start_quote,
2075+
value,
2076+
end_quote,
2077+
});
2078+
}
20912079
}
2080+
value.push(ch);
20922081
}
2082+
2083+
self.tokenizer_error(literal_start_loc, "Unterminated string literal")
20932084
}
20942085

20952086
/// Read a quoted string.

0 commit comments

Comments
 (0)