surql_parser/upstream/syn/parser/
prime.rs1use 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 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 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 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 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}