Skip to content

Commit 819c095

Browse files
Tentatively added support for path identifiers
1 parent 93ea5d2 commit 819c095

File tree

3 files changed

+49
-2
lines changed

3 files changed

+49
-2
lines changed

src/dialect/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,11 @@ pub trait Dialect: Debug + Any {
183183
false
184184
}
185185

186+
/// Returns whether the dialect supports path-like identifiers
187+
fn supports_path_like_identifiers(&self) -> bool {
188+
false
189+
}
190+
186191
/// Most dialects do not have custom operators. Override this method to provide custom operators.
187192
fn is_custom_operator_part(&self, _ch: char) -> bool {
188193
false

src/dialect/snowflake.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,10 @@ impl Dialect for SnowflakeDialect {
158158
|| ch == '_'
159159
}
160160

161+
fn supports_path_like_identifiers(&self) -> bool {
162+
true
163+
}
164+
161165
// See https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#escape_sequences
162166
fn supports_string_literal_backslash_escape(&self) -> bool {
163167
true
@@ -1067,8 +1071,22 @@ pub fn parse_stage_name_identifier(parser: &mut Parser) -> Result<Ident, ParserE
10671071
Token::Plus => ident.push('+'),
10681072
Token::Minus => ident.push('-'),
10691073
Token::Number(n, _) => ident.push_str(n),
1070-
Token::Word(w) => ident.push_str(&w.to_string()),
1071-
_ => return parser.expected("stage name identifier", parser.peek_token()),
1074+
Token::Word(w) => {
1075+
if matches!(w.keyword, Keyword::NoKeyword) {
1076+
ident.push_str(w.to_string().as_str());
1077+
} else {
1078+
parser.prev_token();
1079+
break;
1080+
}
1081+
}
1082+
token => {
1083+
return {
1084+
println!(
1085+
"Unexpected token {token:?} while parsing stage name identifier {ident:?}"
1086+
);
1087+
parser.expected("stage name identifier", parser.peek_token())
1088+
}
1089+
}
10721090
}
10731091
}
10741092
Ok(Ident::new(ident))

src/tokenizer.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1669,6 +1669,11 @@ impl<'a> Tokenizer<'a> {
16691669
_ => self.start_binop(chars, "~~", Token::DoubleTilde),
16701670
}
16711671
}
1672+
Some('/') if self.dialect.supports_path_like_identifiers() => {
1673+
// regular identifier starting with an "E" or "e"
1674+
let s = self.tokenize_word("~", chars, prev_keyword)?;
1675+
Ok(Some(Token::make_word(s, None)))
1676+
}
16721677
_ => self.start_binop(chars, "~", Token::Tilde),
16731678
}
16741679
}
@@ -1969,6 +1974,25 @@ impl<'a> Tokenizer<'a> {
19691974
s.push_str(&peeking_take_while(chars, |ch| {
19701975
self.dialect.is_identifier_part(ch)
19711976
}));
1977+
1978+
while !matches!(prev_keyword, Some(Keyword::SELECT))
1979+
&& self.dialect.supports_path_like_identifiers()
1980+
&& chars.peek().map(|&ch| ch == '/').unwrap_or(false)
1981+
&& chars
1982+
.peekable
1983+
.clone()
1984+
.nth(1)
1985+
.map(|ch| ch.is_alphabetic())
1986+
.unwrap_or(false)
1987+
{
1988+
s.push('/');
1989+
chars.next(); // consume the '/'
1990+
1991+
s.push_str(&peeking_take_while(chars, |ch| {
1992+
self.dialect.is_identifier_part(ch)
1993+
}));
1994+
}
1995+
19721996
if !matches!(prev_keyword, Some(Keyword::SELECT))
19731997
&& self.dialect.supports_hyphenated_identifiers()
19741998
{

0 commit comments

Comments
 (0)