Skip to main content

surql_parser/upstream/syn/parser/basic/
mod.rs

1use crate::upstream::sql::Param;
2use crate::upstream::sql::language::Language;
3use crate::upstream::syn::error::bail;
4use crate::upstream::syn::lexer::Lexer;
5use crate::upstream::syn::lexer::compound::{self, ParsedInt};
6use crate::upstream::syn::parser::mac::unexpected;
7use crate::upstream::syn::parser::{ParseResult, Parser};
8use crate::upstream::syn::token::{Span, TokenKind, t};
9use rust_decimal::Decimal;
10mod number;
11/// A trait for parsing single tokens with a specific value.
12pub trait TokenValue: Sized {
13	fn from_token(parser: &mut Parser<'_>) -> ParseResult<Self>;
14}
15impl TokenValue for Language {
16	fn from_token(parser: &mut Parser<'_>) -> ParseResult<Self> {
17		let peek = parser.peek();
18		match peek.kind {
19			TokenKind::Language(x) => {
20				parser.pop_peek();
21				Ok(x)
22			}
23			t!("NO") => {
24				parser.pop_peek();
25				Ok(Language::Norwegian)
26			}
27			_ => unexpected!(parser, peek, "a language"),
28		}
29	}
30}
31impl TokenValue for Param {
32	fn from_token(parser: &mut Parser<'_>) -> ParseResult<Self> {
33		let peek = parser.peek();
34		match peek.kind {
35			TokenKind::Parameter => {
36				parser.pop_peek();
37				let mut span = peek.span;
38				span.offset += 1;
39				span.len -= 1;
40				let ident = parser.unescape_ident_span(span)?;
41				Ok(Param::new(ident.to_owned()))
42			}
43			_ => unexpected!(parser, peek, "a parameter"),
44		}
45	}
46}
47impl TokenValue for surrealdb_types::Duration {
48	fn from_token(parser: &mut Parser<'_>) -> ParseResult<Self> {
49		let token = parser.peek();
50		match token.kind {
51			TokenKind::Digits => {
52				parser.pop_peek();
53				let v = parser.lexer.lex_compound(token, compound::duration)?.value;
54				Ok(surrealdb_types::Duration::from(v))
55			}
56			_ => unexpected!(parser, token, "a duration"),
57		}
58	}
59}
60impl TokenValue for surrealdb_types::Datetime {
61	fn from_token(parser: &mut Parser<'_>) -> ParseResult<Self> {
62		let token = parser.peek();
63		match token.kind {
64			t!("d\"") | t!("d'") => {
65				parser.pop_peek();
66				let str = parser.unescape_string_span(token.span)?;
67				let file = Lexer::lex_datetime(str).map_err(|e| {
68					e.update_spans(|span| {
69						let range = span.to_range();
70						let start =
71							Lexer::escaped_string_offset(parser.span_str(token.span), range.start);
72						let end =
73							Lexer::escaped_string_offset(parser.span_str(token.span), range.end);
74						*span = Span::from_range(
75							(token.span.offset + start)..(token.span.offset + end),
76						);
77					})
78				})?;
79				Ok(file)
80			}
81			_ => unexpected!(parser, token, "a datetime"),
82		}
83	}
84}
85impl TokenValue for surrealdb_types::Uuid {
86	fn from_token(parser: &mut Parser<'_>) -> ParseResult<Self> {
87		let token = parser.peek();
88		match token.kind {
89			t!("u\"") | t!("u'") => {
90				parser.pop_peek();
91				let str = parser.unescape_string_span(token.span)?;
92				let file = Lexer::lex_uuid(str).map_err(|e| {
93					e.update_spans(|span| {
94						let range = span.to_range();
95						let start =
96							Lexer::escaped_string_offset(parser.span_str(token.span), range.start);
97						let end =
98							Lexer::escaped_string_offset(parser.span_str(token.span), range.end);
99						*span = Span::from_range(
100							(token.span.offset + start)..(token.span.offset + end),
101						);
102					})
103				})?;
104				Ok(file)
105			}
106			_ => unexpected!(parser, token, "a uuid"),
107		}
108	}
109}
110impl TokenValue for surrealdb_types::File {
111	fn from_token(parser: &mut Parser<'_>) -> ParseResult<Self> {
112		let token = parser.peek();
113		if !parser.settings.files_enabled {
114			unexpected!(
115				parser,
116				token,
117				"the experimental files feature to be enabled"
118			);
119		}
120		match token.kind {
121			t!("f\"") | t!("f'") => {
122				parser.pop_peek();
123				let str = parser.unescape_string_span(token.span)?;
124				let file = Lexer::lex_file(str).map_err(|e| {
125					e.update_spans(|span| {
126						let range = span.to_range();
127						let start =
128							Lexer::escaped_string_offset(parser.span_str(token.span), range.start);
129						let end =
130							Lexer::escaped_string_offset(parser.span_str(token.span), range.end);
131						*span = Span::from_range(
132							(token.span.offset + start)..(token.span.offset + end),
133						);
134					})
135				})?;
136				Ok(file)
137			}
138			_ => unexpected!(parser, token, "a file"),
139		}
140	}
141}
142impl TokenValue for surrealdb_types::Bytes {
143	fn from_token(parser: &mut Parser<'_>) -> ParseResult<Self> {
144		let token = parser.peek();
145		match token.kind {
146			t!("b\"") | t!("b'") => {
147				parser.pop_peek();
148				let str = parser.unescape_string_span(token.span)?;
149				let bytes = Lexer::lex_bytes(str).map_err(|e| {
150					e.update_spans(|span| {
151						let range = span.to_range();
152						let start =
153							Lexer::escaped_string_offset(parser.span_str(token.span), range.start);
154						let end =
155							Lexer::escaped_string_offset(parser.span_str(token.span), range.end);
156						*span = Span::from_range(
157							(token.span.offset + start)..(token.span.offset + end),
158						);
159					})
160				})?;
161				Ok(bytes)
162			}
163			_ => unexpected!(parser, token, "a bytestring"),
164		}
165	}
166}
167impl TokenValue for surrealdb_types::Regex {
168	fn from_token(parser: &mut Parser<'_>) -> ParseResult<Self> {
169		let peek = parser.peek();
170		match peek.kind {
171			t!("/") => {
172				parser.pop_peek();
173				if parser.has_peek() {
174					parser.backup_after(peek.span);
175				}
176				let token = parser.lex_compound(peek, compound::regex)?;
177				let s = parser.unescape_regex_span(token.span)?;
178				match regex::Regex::new(s) {
179					Ok(x) => Ok(surrealdb_types::Regex::from(x)),
180					Err(e) => {
181						bail!("Invalid regex syntax {e}", @ token.span);
182					}
183				}
184			}
185			_ => unexpected!(parser, peek, "a regex"),
186		}
187	}
188}
189pub enum NumberToken {
190	Float(f64),
191	Integer(ParsedInt),
192	Decimal(Decimal),
193}
194impl TokenValue for NumberToken {
195	fn from_token(parser: &mut Parser<'_>) -> ParseResult<Self> {
196		let token = parser.peek();
197		match token.kind {
198			t!("+") | t!("-") | TokenKind::Digits => {
199				parser.pop_peek();
200				let token = parser.lex_compound(token, compound::number)?;
201				match token.value {
202					compound::Numeric::Float(f) => Ok(NumberToken::Float(f)),
203					compound::Numeric::Integer(x) => Ok(NumberToken::Integer(x)),
204					compound::Numeric::Decimal(d) => Ok(NumberToken::Decimal(d)),
205					compound::Numeric::Duration(_) => {
206						bail!(
207							"Unexpected token `duration`, expected a number", @ token
208							.span
209						)
210					}
211				}
212			}
213			TokenKind::NaN => {
214				parser.pop_peek();
215				Ok(NumberToken::Float(f64::NAN))
216			}
217			TokenKind::Infinity => {
218				parser.pop_peek();
219				Ok(NumberToken::Float(f64::INFINITY))
220			}
221			_ => unexpected!(parser, token, "a number"),
222		}
223	}
224}
225impl TokenValue for surrealdb_types::Number {
226	fn from_token(parser: &mut Parser<'_>) -> ParseResult<Self> {
227		let token = parser.next_token_value::<NumberToken>()?;
228		match token {
229			NumberToken::Float(x) => Ok(Self::Float(x)),
230			NumberToken::Integer(i) => Ok(Self::Int(i.into_int(parser.recent_span())?)),
231			NumberToken::Decimal(x) => Ok(Self::Decimal(x)),
232		}
233	}
234}
235impl Parser<'_> {
236	/// Parse a token value from the next token in the parser.
237	pub fn next_token_value<V: TokenValue>(&mut self) -> ParseResult<V> {
238		V::from_token(self)
239	}
240	pub fn parse_string_lit(&mut self) -> ParseResult<String> {
241		let token = self.peek();
242		match token.kind {
243			t!("\"") | t!("'") => {
244				self.pop_peek();
245				let str = self.unescape_string_span(token.span)?;
246				Ok(str.to_owned())
247			}
248			_ => unexpected!(self, token, "a strand"),
249		}
250	}
251	pub fn parse_ident(&mut self) -> ParseResult<String> {
252		self.parse_ident_str().map(|x| x.to_owned())
253	}
254	pub fn parse_ident_str(&mut self) -> ParseResult<&str> {
255		let token = self.next();
256		match token.kind {
257			TokenKind::Identifier => self.unescape_ident_span(token.span),
258			x if Self::kind_is_keyword_like(x) => Ok(self.span_str(token.span)),
259			_ => {
260				unexpected!(self, token, "an identifier");
261			}
262		}
263	}
264	pub fn parse_flexible_ident(&mut self) -> ParseResult<String> {
265		let token = self.next();
266		match token.kind {
267			TokenKind::Digits => {
268				let span = if let Some(peek) = self.peek_whitespace() {
269					match peek.kind {
270						x if Self::kind_is_keyword_like(x) => {
271							self.pop_peek();
272							token.span.covers(peek.span)
273						}
274						TokenKind::Identifier | TokenKind::NaN | TokenKind::Infinity => {
275							self.pop_peek();
276							token.span.covers(peek.span)
277						}
278						_ => token.span,
279					}
280				} else {
281					token.span
282				};
283				Ok(self.span_str(span).to_owned())
284			}
285			TokenKind::Identifier | TokenKind::NaN | TokenKind::Infinity => {
286				let str = self.unescape_ident_span(token.span)?;
287				Ok(str.to_owned())
288			}
289			x if Self::kind_is_keyword_like(x) => Ok(self.span_str(token.span).to_owned()),
290			_ => {
291				unexpected!(self, token, "an identifier");
292			}
293		}
294	}
295}