Skip to main content

surql_parser/upstream/syn/parser/
prime.rs

1use super::{ParseResult, Parser};
2use crate::compat::types::{PublicDuration, PublicGeometry};
3use crate::compat::val::range::TypedRange;
4use crate::upstream::sql::lookup::LookupKind;
5use crate::upstream::sql::{
6	Closure, Dir, Expr, Function, FunctionCall, Idiom, Kind, Literal, Mock, Param, Part, Script,
7};
8use crate::upstream::syn::error::{SyntaxError, bail};
9use crate::upstream::syn::lexer::Lexer;
10use crate::upstream::syn::lexer::compound::{self};
11use crate::upstream::syn::parser::enter_object_recursion;
12use crate::upstream::syn::parser::mac::{expected, unexpected};
13use crate::upstream::syn::token::{Span, TokenKind, t};
14use reblessive::Stk;
15use std::ops::Bound;
16impl Parser<'_> {
17	pub(super) fn parse_number_like_prime(&mut self) -> ParseResult<Expr> {
18		let token = self.peek();
19		match token.kind {
20			TokenKind::Infinity => Ok(Expr::Literal(Literal::Float(f64::INFINITY))),
21			t!("+") | t!("-") | TokenKind::Digits => {
22				self.pop_peek();
23				let value = self.lex_compound(token, compound::numeric)?;
24				self.last_span = value.span;
25				let v = match value.value {
26					compound::Numeric::Float(x) => Expr::Literal(Literal::Float(x)),
27					compound::Numeric::Integer(x) => {
28						Expr::Literal(Literal::Integer(x.into_int(value.span)?))
29					}
30					compound::Numeric::Decimal(x) => Expr::Literal(Literal::Decimal(x)),
31					compound::Numeric::Duration(x) => {
32						Expr::Literal(Literal::Duration(PublicDuration::from(x)))
33					}
34				};
35				Ok(v)
36			}
37			_ => unexpected!(self, token, "a number"),
38		}
39	}
40	/// Parse an expressions
41	pub(super) async fn parse_prime_expr(&mut self, stk: &mut Stk) -> ParseResult<Expr> {
42		let token = self.peek();
43		let value = match token.kind {
44			t!("@") => {
45				self.pop_peek();
46				let mut res = vec![Part::Doc];
47				if !self.peek_continues_idiom() {
48					res.push(self.parse_dot_part(stk).await?);
49				}
50				Expr::Idiom(Idiom(res))
51			}
52			t!("NONE") => {
53				self.pop_peek();
54				Expr::Literal(Literal::None)
55			}
56			t!("NULL") => {
57				self.pop_peek();
58				Expr::Literal(Literal::Null)
59			}
60			t!("true") => {
61				self.pop_peek();
62				Expr::Literal(Literal::Bool(true))
63			}
64			t!("false") => {
65				self.pop_peek();
66				Expr::Literal(Literal::Bool(false))
67			}
68			t!("<") => {
69				self.pop_peek();
70				if let Some(peek) = self.peek_whitespace() {
71					if peek.kind == t!("~") {
72						self.pop_peek();
73						let lookup = stk
74							.run(|ctx| self.parse_lookup(ctx, LookupKind::Reference))
75							.await?;
76						Expr::Idiom(Idiom(vec![Part::Graph(lookup)]))
77					} else if peek.kind == t!("-") {
78						self.pop_peek();
79						let lookup = stk
80							.run(|ctx| self.parse_lookup(ctx, LookupKind::Graph(Dir::In)))
81							.await?;
82						Expr::Idiom(Idiom(vec![Part::Graph(lookup)]))
83					} else if peek.kind == t!("->") {
84						self.pop_peek();
85						let lookup = stk
86							.run(|ctx| self.parse_lookup(ctx, LookupKind::Graph(Dir::Both)))
87							.await?;
88						Expr::Idiom(Idiom(vec![Part::Graph(lookup)]))
89					} else {
90						unexpected!(self, token, "`<-`, `<->` or `<~`")
91					}
92				} else {
93					unexpected!(self, token, "`<-`, `<->` or `<~`")
94				}
95			}
96			t!("r\"") | t!("r'") => {
97				self.pop_peek();
98				let str = self.unescape_string_span(token.span)?;
99				let mut inner_parser = Parser::new(str.as_bytes());
100				let record_id = match stk.run(|stk| inner_parser.parse_record_id(stk)).await {
101					Ok(x) => x,
102					Err(e) => {
103						let e = e.update_spans(|span| {
104							let range = span.to_range();
105							let start = Lexer::escaped_string_offset(
106								self.span_str(token.span),
107								range.start,
108							);
109							let end =
110								Lexer::escaped_string_offset(self.span_str(token.span), range.end);
111							*span = Span::from_range(
112								(token.span.offset + start)..(token.span.offset + end),
113							);
114						});
115						return Err(e);
116					}
117				};
118				Expr::Literal(Literal::RecordId(record_id))
119			}
120			t!("d\"") | t!("d'") => Expr::Literal(Literal::Datetime(self.next_token_value()?)),
121			t!("u\"") | t!("u'") => Expr::Literal(Literal::Uuid(self.next_token_value()?)),
122			t!("b\"") | t!("b'") => Expr::Literal(Literal::Bytes(self.next_token_value()?)),
123			t!("f\"") | t!("f'") => {
124				if !self.settings.files_enabled {
125					unexpected!(self, token, "the experimental files feature to be enabled");
126				}
127				let file = self.next_token_value()?;
128				Expr::Literal(Literal::File(file))
129			}
130			t!("'") | t!("\"") => {
131				if self.settings.legacy_strands {
132					Expr::Literal(self.reparse_legacy_strand(stk).await?)
133				} else {
134					let s = self.parse_string_lit()?;
135					Expr::Literal(Literal::String(s))
136				}
137			}
138			t!("+") | t!("-") | TokenKind::Digits => self.parse_number_like_prime()?,
139			TokenKind::Infinity => {
140				self.pop_peek();
141				Expr::Literal(Literal::Float(f64::INFINITY))
142			}
143			TokenKind::NaN => {
144				self.pop_peek();
145				Expr::Literal(Literal::Float(f64::NAN))
146			}
147			t!("$param") => Expr::Param(self.next_token_value()?),
148			t!("FUNCTION") => {
149				self.pop_peek();
150				let script = self.parse_script(stk).await?;
151				Expr::FunctionCall(Box::new(script))
152			}
153			t!("->") => {
154				self.pop_peek();
155				let lookup = stk
156					.run(|ctx| self.parse_lookup(ctx, LookupKind::Graph(Dir::Out)))
157					.await?;
158				Expr::Idiom(Idiom(vec![Part::Graph(lookup)]))
159			}
160			t!("[") => {
161				self.pop_peek();
162				self.parse_array(stk, token.span)
163					.await
164					.map(|a| Expr::Literal(Literal::Array(a)))?
165			}
166			t!("{") => {
167				self.pop_peek();
168				self.parse_object_like(stk, token.span).await?
169			}
170			t!("|") => {
171				self.pop_peek();
172				self.parse_closure_or_mock(stk, token.span).await?
173			}
174			t!("||") => {
175				self.pop_peek();
176				stk.run(|ctx| self.parse_closure_after_args(ctx, Vec::new()))
177					.await?
178			}
179			t!("(") => {
180				self.pop_peek();
181				self.parse_covered_expr_or_coordinate(stk, token.span)
182					.await?
183			}
184			t!("/") => {
185				let regex = self.next_token_value()?;
186				Expr::Literal(Literal::Regex(regex))
187			}
188			t!("fn") if self.peek1().kind == t!("::") => {
189				self.pop_peek();
190				self.parse_custom_function(stk)
191					.await
192					.map(|x| Expr::FunctionCall(Box::new(x)))?
193			}
194			t!("mod") if self.peek1().kind == t!("::") => {
195				self.pop_peek();
196				self.parse_module_function(stk)
197					.await
198					.map(|x| Expr::FunctionCall(Box::new(x)))?
199			}
200			t!("silo") if self.peek1().kind == t!("::") => {
201				self.pop_peek();
202				self.parse_silo_function(stk)
203					.await
204					.map(|x| Expr::FunctionCall(Box::new(x)))?
205			}
206			t!("ml") if self.peek1().kind == t!("::") => {
207				self.pop_peek();
208				self.parse_model(stk)
209					.await
210					.map(|x| Expr::FunctionCall(Box::new(x)))?
211			}
212			t!("IF") => {
213				self.pop_peek();
214				let stmt = stk.run(|ctx| self.parse_if_stmt(ctx)).await?;
215				Expr::IfElse(Box::new(stmt))
216			}
217			t!("SELECT") => {
218				self.pop_peek();
219				let stmt = self.parse_select_stmt(stk).await?;
220				Expr::Select(Box::new(stmt))
221			}
222			t!("CREATE") => {
223				self.pop_peek();
224				let stmt = self.parse_create_stmt(stk).await?;
225				Expr::Create(Box::new(stmt))
226			}
227			t!("EXPLAIN") => {
228				self.pop_peek();
229				self.parse_explain_expr(stk).await?
230			}
231			t!("UPDATE") => {
232				self.pop_peek();
233				let stmt = self.parse_update_stmt(stk).await?;
234				Expr::Update(Box::new(stmt))
235			}
236			t!("UPSERT") => {
237				self.pop_peek();
238				let stmt = self.parse_upsert_stmt(stk).await?;
239				Expr::Upsert(Box::new(stmt))
240			}
241			t!("DELETE") => {
242				self.pop_peek();
243				let stmt = self.parse_delete_stmt(stk).await?;
244				Expr::Delete(Box::new(stmt))
245			}
246			t!("RELATE") => {
247				self.pop_peek();
248				let stmt = self.parse_relate_stmt(stk).await?;
249				Expr::Relate(Box::new(stmt))
250			}
251			t!("INSERT") => {
252				self.pop_peek();
253				let stmt = self.parse_insert_stmt(stk).await?;
254				Expr::Insert(Box::new(stmt))
255			}
256			t!("DEFINE") => {
257				self.pop_peek();
258				let stmt = self.parse_define_stmt(stk).await?;
259				Expr::Define(Box::new(stmt))
260			}
261			t!("REMOVE") => {
262				self.pop_peek();
263				let stmt = self.parse_remove_stmt(stk).await?;
264				Expr::Remove(Box::new(stmt))
265			}
266			t!("REBUILD") => {
267				self.pop_peek();
268				let stmt = self.parse_rebuild_stmt()?;
269				Expr::Rebuild(Box::new(stmt))
270			}
271			t!("ALTER") => {
272				self.pop_peek();
273				let stmt = self.parse_alter_stmt(stk).await?;
274				Expr::Alter(Box::new(stmt))
275			}
276			t!("INFO") => {
277				self.pop_peek();
278				let stmt = self.parse_info_stmt(stk).await?;
279				Expr::Info(Box::new(stmt))
280			}
281			t!("FOR") => {
282				self.pop_peek();
283				let stmt = self.parse_for_stmt(stk).await?;
284				Expr::Foreach(Box::new(stmt))
285			}
286			t!("LET") => {
287				self.pop_peek();
288				let stmt = self.parse_let_stmt(stk).await?;
289				Expr::Let(Box::new(stmt))
290			}
291			t!("SLEEP") if self.peek1().kind != t!("(") => {
292				self.pop_peek();
293				let stmt = self.parse_sleep_stmt()?;
294				Expr::Sleep(Box::new(stmt))
295			}
296			t!("RETURN") => {
297				self.pop_peek();
298				let stmt = self.parse_return_stmt(stk).await?;
299				Expr::Return(Box::new(stmt))
300			}
301			t!("THROW") => {
302				self.pop_peek();
303				let expr = stk.run(|stk| self.parse_expr_inherit(stk)).await?;
304				Expr::Throw(Box::new(expr))
305			}
306			t!("CONTINUE") => {
307				self.pop_peek();
308				Expr::Continue
309			}
310			t!("BREAK") => {
311				self.pop_peek();
312				Expr::Break
313			}
314			x if Self::kind_is_identifier(x) => {
315				let peek = self.peek1();
316				match peek.kind {
317					t!("::") | t!("(") => {
318						self.pop_peek();
319						self.parse_builtin(stk, token.span).await?
320					}
321					t!(":") => {
322						let str = self.parse_ident()?;
323						self.parse_record_id_or_range(stk, str)
324							.await
325							.map(|x| Expr::Literal(Literal::RecordId(x)))?
326					}
327					_ => {
328						if self.table_as_field {
329							Expr::Idiom(Idiom(vec![Part::Field(self.parse_ident()?)]))
330						} else {
331							Expr::Table(self.parse_ident()?)
332						}
333					}
334				}
335			}
336			_ => unexpected!(self, token, "an expression"),
337		};
338		if self.peek_continues_idiom() {
339			match value {
340				Expr::Idiom(Idiom(x)) => self.parse_remaining_value_idiom(stk, x).await,
341				Expr::Table(x) => {
342					self.parse_remaining_value_idiom(stk, vec![Part::Field(x)])
343						.await
344				}
345				x => {
346					self.parse_remaining_value_idiom(stk, vec![Part::Start(x)])
347						.await
348				}
349			}
350		} else {
351			Ok(value)
352		}
353	}
354	/// Parses an array production
355	///
356	/// # Parser state
357	/// Expects the starting `[` to already be eaten and its span passed as an
358	/// argument.
359	pub async fn parse_array(&mut self, stk: &mut Stk, start: Span) -> ParseResult<Vec<Expr>> {
360		let mut exprs = Vec::new();
361		enter_object_recursion!(
362			this = self => { loop { if this.eat(t!("]")) { break; } let value = stk.run(|
363			ctx | this.parse_expr_inherit(ctx)). await ?; exprs.push(value); if ! this
364			.eat(t!(",")) { this.expect_closing_delimiter(t!("]"), start) ?; break; } } }
365		);
366		Ok(exprs)
367	}
368	/// Parse a mock `|foo:1..3|`
369	///
370	/// # Parser State
371	/// Expects the starting `|` already be eaten and its span passed as an
372	/// argument.
373	pub(super) fn parse_mock(&mut self, start_span: Span) -> ParseResult<Mock> {
374		let name = self.parse_ident()?;
375		expected!(self, t!(":"));
376		let start = match self.peek_kind() {
377			t!("..") => {
378				self.pop_peek();
379				Bound::Unbounded
380			}
381			_ => {
382				let from = self.next_token_value::<i64>()?;
383				match self.peek_kind() {
384					t!("..") => {
385						self.pop_peek();
386						Bound::Included(from)
387					}
388					t!(">") => {
389						self.pop_peek();
390						expected!(self, t!(".."));
391						Bound::Excluded(from)
392					}
393					_ => {
394						self.expect_closing_delimiter(t!("|"), start_span)?;
395						return Ok(Mock::Count(name, from));
396					}
397				}
398			}
399		};
400		let end = match self.peek_kind() {
401			t!("|") => {
402				self.pop_peek();
403				Bound::Unbounded
404			}
405			t!("=") => {
406				self.pop_peek();
407				let to = self.next_token_value()?;
408				self.expect_closing_delimiter(t!("|"), start_span)?;
409				Bound::Included(to)
410			}
411			_ => {
412				let to = self.next_token_value()?;
413				self.expect_closing_delimiter(t!("|"), start_span)?;
414				Bound::Excluded(to)
415			}
416		};
417		Ok(Mock::Range(name, TypedRange { start, end }))
418	}
419	pub(super) async fn parse_closure_or_mock(
420		&mut self,
421		stk: &mut Stk,
422		start: Span,
423	) -> ParseResult<Expr> {
424		match self.peek_kind() {
425			t!("$param") => stk.run(|ctx| self.parse_closure(ctx, start)).await,
426			_ => self.parse_mock(start).map(Expr::Mock),
427		}
428	}
429	pub(super) async fn parse_closure(&mut self, stk: &mut Stk, start: Span) -> ParseResult<Expr> {
430		let mut args = Vec::new();
431		loop {
432			if self.eat(t!("|")) {
433				break;
434			}
435			let param = self.next_token_value::<Param>()?;
436			let kind = if self.eat(t!(":")) {
437				if self.eat(t!("<")) {
438					let delim = self.last_span();
439					stk.run(|stk| self.parse_kind(stk, delim)).await?
440				} else {
441					stk.run(|stk| self.parse_inner_single_kind(stk)).await?
442				}
443			} else {
444				Kind::Any
445			};
446			args.push((param, kind));
447			if !self.eat(t!(",")) {
448				self.expect_closing_delimiter(t!("|"), start)?;
449				break;
450			}
451		}
452		self.parse_closure_after_args(stk, args).await
453	}
454	pub(super) async fn parse_closure_after_args(
455		&mut self,
456		stk: &mut Stk,
457		args: Vec<(Param, Kind)>,
458	) -> ParseResult<Expr> {
459		let (returns, body) = if self.eat(t!("->")) {
460			let returns = Some(stk.run(|ctx| self.parse_inner_kind(ctx)).await?);
461			let start = expected!(self, t!("{")).span;
462			let body = Expr::Block(Box::new(stk.run(|ctx| self.parse_block(ctx, start)).await?));
463			(returns, body)
464		} else {
465			let body = stk.run(|stk| self.parse_expr_inherit(stk)).await?;
466			(None, body)
467		};
468		Ok(Expr::Closure(Box::new(Closure {
469			args,
470			returns,
471			body,
472		})))
473	}
474	async fn parse_covered_expr_or_coordinate(
475		&mut self,
476		stk: &mut Stk,
477		start: Span,
478	) -> ParseResult<Expr> {
479		let peek = self.peek();
480		match peek.kind {
481			t!("+") | t!("-") | TokenKind::NaN | TokenKind::Infinity | TokenKind::Digits => {
482				if let Some(x) = self
483					.speculate(stk, async |_, this| {
484						let Ok(x) = this.next_token_value::<f64>() else {
485							return Ok(None);
486						};
487						if !this.eat(t!(",")) {
488							return Ok(None);
489						}
490						let y = this.next_token_value::<f64>()?;
491						this.expect_closing_delimiter(t!(")"), start)?;
492						Ok(Some(Expr::Literal(Literal::Geometry(
493							PublicGeometry::Point(geo::Point::new(x, y)),
494						))))
495					})
496					.await?
497				{
498					return Ok(x);
499				}
500			}
501			_ => {}
502		};
503		let res = stk.run(|ctx| self.parse_expr_inherit(ctx)).await?;
504		let token = self.peek();
505		if token.kind != t!(")")
506			&& Self::starts_disallowed_subquery_statement(peek.kind)
507			&& let Expr::Idiom(Idiom(ref idiom)) = res
508			&& idiom.len() == 1
509		{
510			bail!(
511				"Unexpected token `{}` expected `)`", peek.kind, @ token.span, @ peek
512				.span => "This is a reserved keyword here and can't be an identifier"
513			);
514		}
515		self.expect_closing_delimiter(t!(")"), start)?;
516		if self.peek_continues_idiom() {
517			self.parse_remaining_value_idiom(stk, vec![Part::Start(res)])
518				.await
519		} else {
520			Ok(res)
521		}
522	}
523	/// Parses a strand with legacy rules, parsing to a record id, datetime or
524	/// uuid if the string matches.
525	pub(super) async fn reparse_legacy_strand(
526		&mut self,
527		stk: &mut Stk,
528	) -> Result<Literal, SyntaxError> {
529		let token = self.next();
530		assert!(matches!(token.kind, t!("'") | t!("\"")));
531		let str = self.unescape_string_span(token.span)?;
532		if let Ok(x) = Lexer::lex_uuid(str) {
533			return Ok(Literal::Uuid(x));
534		}
535		if let Ok(x) = Lexer::lex_datetime(str) {
536			return Ok(Literal::Datetime(x));
537		}
538		let mut record_id_parser = Parser::new(str.as_bytes());
539		if let Ok(x) = record_id_parser.parse_record_id(stk).await
540			&& record_id_parser.peek().is_eof()
541		{
542			return Ok(Literal::RecordId(x));
543		}
544		Ok(Literal::String(str.to_owned()))
545	}
546	async fn parse_script(&mut self, stk: &mut Stk) -> ParseResult<FunctionCall> {
547		let start = expected!(self, t!("(")).span;
548		let mut args = Vec::new();
549		loop {
550			if self.eat(t!(")")) {
551				break;
552			}
553			let arg = stk.run(|ctx| self.parse_expr_inherit(ctx)).await?;
554			args.push(arg);
555			if !self.eat(t!(",")) {
556				self.expect_closing_delimiter(t!(")"), start)?;
557				break;
558			}
559		}
560		let token = expected!(self, t!("{"));
561		let mut span = self.lex_compound(token, compound::javascript)?.span;
562		span.offset += 1;
563		span.len -= 2;
564		let body = self.span_str(span);
565		let receiver = Function::Script(Script(body.to_string()));
566		Ok(FunctionCall {
567			receiver,
568			arguments: args,
569		})
570	}
571}