surql_parser/upstream/syn/parser/
value.rs1use super::{ParseResult, Parser};
2use crate::compat::types::{
3 PublicArray, PublicDuration, PublicFile, PublicGeometry, PublicNumber, PublicObject,
4 PublicRange, PublicRecordId, PublicRecordIdKey, PublicSet, PublicTable, PublicUuid,
5 PublicValue,
6};
7use crate::upstream::syn::error::bail;
8use crate::upstream::syn::lexer::Lexer;
9use crate::upstream::syn::lexer::compound::{self, Numeric};
10use crate::upstream::syn::parser::mac::{expected, expected_whitespace};
11use crate::upstream::syn::parser::unexpected;
12use crate::upstream::syn::token::{Span, TokenKind, t};
13use reblessive::Stk;
14use std::cmp::Ordering;
15use std::collections::BTreeMap;
16use std::ops::Bound;
17trait ValueParseFunc {
18 async fn parse(parser: &mut Parser<'_>, stk: &mut Stk) -> ParseResult<PublicValue>;
19}
20struct SurrealQL;
21struct Json;
22impl ValueParseFunc for SurrealQL {
23 async fn parse(parser: &mut Parser<'_>, stk: &mut Stk) -> ParseResult<PublicValue> {
24 parser.parse_value(stk).await
25 }
26}
27impl ValueParseFunc for Json {
28 async fn parse(parser: &mut Parser<'_>, stk: &mut Stk) -> ParseResult<PublicValue> {
29 parser.parse_json(stk).await
30 }
31}
32impl Parser<'_> {
33 pub async fn parse_value(&mut self, stk: &mut Stk) -> ParseResult<PublicValue> {
35 let token = self.peek();
36 let res = match token.kind {
37 t!("NONE") => {
38 self.pop_peek();
39 PublicValue::None
40 }
41 t!("NULL") => {
42 self.pop_peek();
43 PublicValue::Null
44 }
45 TokenKind::NaN => {
46 self.pop_peek();
47 PublicValue::Number(PublicNumber::Float(f64::NAN))
48 }
49 TokenKind::Infinity => {
50 self.pop_peek();
51 PublicValue::Number(PublicNumber::Float(f64::INFINITY))
52 }
53 t!("true") => {
54 self.pop_peek();
55 PublicValue::Bool(true)
56 }
57 t!("false") => {
58 self.pop_peek();
59 PublicValue::Bool(false)
60 }
61 t!("{") => {
62 let open = self.pop_peek().span;
63 if self.eat(t!("}")) {
64 return Ok(PublicValue::Object(PublicObject::new()));
65 }
66 if self.eat(t!(",")) {
67 self.expect_closing_delimiter(t!("}"), open)?;
68 return Ok(PublicValue::Set(PublicSet::new()));
69 }
70 if let t!("\"")
71 | t!("'")
72 | TokenKind::Identifier
73 | TokenKind::Digits
74 | TokenKind::Keyword(_)
75 | TokenKind::Language(_)
76 | TokenKind::Algorithm(_)
77 | TokenKind::Distance(_)
78 | TokenKind::VectorType(_) = self.peek().kind
79 && let Some(x) = self
80 .speculate(stk, async |stk, this| {
81 let key = this.parse_object_key()?;
82 if !this.eat(t!(":")) {
83 return Ok(None);
84 }
85 let value = stk.run(|stk| this.parse_value(stk)).await?;
86 let mut res = BTreeMap::new();
87 res.insert(key, value);
88 if this.eat(t!(",")) {
89 this.parse_value_object::<SurrealQL>(stk, open, res)
90 .await
91 .map(Some)
92 } else {
93 this.expect_closing_delimiter(t!("}"), open)?;
94 Ok(Some(PublicObject::from(res)))
95 }
96 })
97 .await?
98 {
99 if let Some(x) = PublicGeometry::try_from_object(&x) {
100 return Ok(PublicValue::Geometry(x));
101 } else {
102 return Ok(PublicValue::Object(x));
103 }
104 }
105 let set = self.parse_value_set::<SurrealQL>(stk, token.span).await?;
106 PublicValue::Set(set)
107 }
108 t!("[") => {
109 self.pop_peek();
110 self.parse_value_array::<SurrealQL>(stk, token.span)
111 .await
112 .map(PublicValue::Array)?
113 }
114 t!("\"") | t!("'") => {
115 let strand = self.parse_string_lit()?;
116 if self.settings.legacy_strands {
117 self.reparse_json_legacy_strand(stk, strand).await
118 } else {
119 PublicValue::String(strand)
120 }
121 }
122 t!("d\"") | t!("d'") => PublicValue::Datetime(self.next_token_value()?),
123 t!("u\"") | t!("u'") => PublicValue::Uuid(self.next_token_value()?),
124 t!("b\"") | t!("b'") => PublicValue::Bytes(self.next_token_value()?),
125 t!("f\"") | t!("f'") => {
126 if !self.settings.files_enabled {
127 unexpected!(self, token, "the experimental files feature to be enabled");
128 }
129 let file = self.next_token_value::<PublicFile>()?;
130 PublicValue::File(file)
131 }
132 t!("/") => {
133 let regex = self.next_token_value()?;
134 PublicValue::Regex(regex)
135 }
136 t!("(") => {
137 let open = self.pop_peek().span;
138 let peek = self.peek();
139 match peek.kind {
140 t!("+") | t!("-") | TokenKind::Digits => {
141 let before = peek.span;
142 let number = self.next_token_value::<Numeric>()?;
143 let number_span = before.covers(self.last_span());
144 if self.peek().kind == t!(",") {
145 let x = match number {
146 Numeric::Duration(_) | Numeric::Decimal(_) => {
147 bail!(
148 "Unexpected token, expected a non-decimal, non-NaN, number",
149 @ number_span =>
150 "Coordinate numbers can't be NaN or a decimal"
151 );
152 }
153 Numeric::Float(x) if x.is_nan() => {
154 bail!(
155 "Unexpected token, expected a non-decimal, non-NaN, number",
156 @ number_span =>
157 "Coordinate numbers can't be NaN or a decimal"
158 );
159 }
160 Numeric::Float(x) => x,
161 Numeric::Integer(x) => x.into_int(number_span)? as f64,
162 };
163 self.pop_peek();
164 let y = self.next_token_value::<f64>()?;
165 self.expect_closing_delimiter(t!(")"), open)?;
166 PublicValue::Geometry(PublicGeometry::Point(geo::Point::new(x, y)))
167 } else {
168 self.expect_closing_delimiter(t!(")"), open)?;
169 match number {
170 Numeric::Float(x) => PublicValue::Number(PublicNumber::Float(x)),
171 Numeric::Integer(x) => {
172 PublicValue::Number(PublicNumber::Int(x.into_int(number_span)?))
173 }
174 Numeric::Decimal(x) => {
175 PublicValue::Number(PublicNumber::Decimal(x))
176 }
177 Numeric::Duration(duration) => {
178 PublicValue::Duration(PublicDuration::from(duration))
179 }
180 }
181 }
182 }
183 _ => {
184 let res = stk.run(|stk| self.parse_value(stk)).await?;
185 self.expect_closing_delimiter(t!(")"), open)?;
186 res
187 }
188 }
189 }
190 t!("..") => {
191 self.pop_peek();
192 match self.peek_whitespace().map(|x| x.kind) {
193 Some(t!("=")) => {
194 self.pop_peek();
195 let v = stk.run(|stk| self.parse_value(stk)).await?;
196 PublicValue::Range(Box::new(PublicRange {
197 start: Bound::Unbounded,
198 end: Bound::Included(v),
199 }))
200 }
201 Some(x) if Self::kind_starts_expression(x) => {
202 let v = stk.run(|stk| self.parse_value(stk)).await?;
203 PublicValue::Range(Box::new(PublicRange {
204 start: Bound::Unbounded,
205 end: Bound::Excluded(v),
206 }))
207 }
208 _ => PublicValue::Range(Box::new(PublicRange {
209 start: Bound::Unbounded,
210 end: Bound::Unbounded,
211 })),
212 }
213 }
214 t!("-") | t!("+") | TokenKind::Digits => {
215 self.pop_peek();
216 let compound = self.lex_compound(token, compound::numeric)?;
217 match compound.value {
218 Numeric::Duration(x) => PublicValue::Duration(PublicDuration::from(x)),
219 Numeric::Integer(x) => {
220 PublicValue::Number(PublicNumber::Int(x.into_int(compound.span)?))
221 }
222 Numeric::Float(x) => PublicValue::Number(PublicNumber::Float(x)),
223 Numeric::Decimal(x) => PublicValue::Number(PublicNumber::Decimal(x)),
224 }
225 }
226 _ => self
227 .parse_value_record_id_inner::<SurrealQL>(stk)
228 .await
229 .map(PublicValue::RecordId)?,
230 };
231 match self.peek_whitespace().map(|x| x.kind) {
232 Some(t!(">")) => {
233 self.pop_peek();
234 expected_whitespace!(self, t!(".."));
235 match self.peek_whitespace().map(|x| x.kind) {
236 Some(t!("=")) => {
237 self.pop_peek();
238 let v = stk.run(|stk| self.parse_value(stk)).await?;
239 Ok(PublicValue::Range(Box::new(PublicRange {
240 start: Bound::Excluded(res),
241 end: Bound::Included(v),
242 })))
243 }
244 Some(x) if Self::kind_starts_expression(x) => {
245 let v = stk.run(|stk| self.parse_value(stk)).await?;
246 Ok(PublicValue::Range(Box::new(PublicRange {
247 start: Bound::Excluded(res),
248 end: Bound::Excluded(v),
249 })))
250 }
251 _ => Ok(PublicValue::Range(Box::new(PublicRange {
252 start: Bound::Excluded(res),
253 end: Bound::Unbounded,
254 }))),
255 }
256 }
257 Some(t!("..")) => {
258 self.pop_peek();
259 match self.peek_whitespace().map(|x| x.kind) {
260 Some(t!("=")) => {
261 self.pop_peek();
262 let v = stk.run(|stk| self.parse_value(stk)).await?;
263 Ok(PublicValue::Range(Box::new(PublicRange {
264 start: Bound::Included(res),
265 end: Bound::Included(v),
266 })))
267 }
268 Some(x) if Self::kind_starts_expression(x) => {
269 let v = stk.run(|stk| self.parse_value(stk)).await?;
270 Ok(PublicValue::Range(Box::new(PublicRange {
271 start: Bound::Included(res),
272 end: Bound::Excluded(v),
273 })))
274 }
275 _ => Ok(PublicValue::Range(Box::new(PublicRange {
276 start: Bound::Included(res),
277 end: Bound::Unbounded,
278 }))),
279 }
280 }
281 _ => Ok(res),
282 }
283 }
284 pub async fn parse_json(&mut self, stk: &mut Stk) -> ParseResult<PublicValue> {
285 let token = self.peek();
286 match token.kind {
287 t!("NULL") => {
288 self.pop_peek();
289 Ok(PublicValue::Null)
290 }
291 t!("true") => {
292 self.pop_peek();
293 Ok(PublicValue::Bool(true))
294 }
295 t!("false") => {
296 self.pop_peek();
297 Ok(PublicValue::Bool(false))
298 }
299 t!("{") => {
300 self.pop_peek();
301 self.parse_value_object::<Json>(stk, token.span, BTreeMap::new())
302 .await
303 .map(PublicValue::Object)
304 }
305 t!("[") => {
306 self.pop_peek();
307 self.parse_value_array::<Json>(stk, token.span)
308 .await
309 .map(PublicValue::Array)
310 }
311 t!("\"") | t!("'") => {
312 let strand = self.parse_string_lit()?;
313 if self.settings.legacy_strands {
314 Ok(self.reparse_json_legacy_strand(stk, strand).await)
315 } else {
316 Ok(PublicValue::String(strand))
317 }
318 }
319 t!("-") | t!("+") | TokenKind::Digits => {
320 self.pop_peek();
321 let compound = self.lex_compound(token, compound::numeric)?;
322 match compound.value {
323 Numeric::Duration(x) => Ok(PublicValue::Duration(PublicDuration::from(x))),
324 Numeric::Integer(x) => Ok(PublicValue::Number(PublicNumber::Int(
325 x.into_int(compound.span)?,
326 ))),
327 Numeric::Float(x) => Ok(PublicValue::Number(PublicNumber::Float(x))),
328 Numeric::Decimal(x) => Ok(PublicValue::Number(PublicNumber::Decimal(x))),
329 }
330 }
331 _ => {
332 match self
333 .parse_value_record_id_inner::<Json>(stk)
334 .await
335 .map(PublicValue::RecordId)
336 {
337 Ok(x) => Ok(x),
338 Err(err) => {
339 tracing::debug!("Error parsing record id: {err:?}");
340 self.parse_value_table().await.map(PublicValue::Table)
341 }
342 }
343 }
344 }
345 }
346 async fn reparse_json_legacy_strand(&mut self, stk: &mut Stk, strand: String) -> PublicValue {
347 if let Ok(x) = Parser::new(strand.as_bytes())
348 .parse_value_record_id(stk)
349 .await
350 {
351 return PublicValue::RecordId(x);
352 }
353 if let Ok(x) = Lexer::lex_datetime(&strand) {
354 return PublicValue::Datetime(x);
355 }
356 if let Ok(x) = Lexer::lex_uuid(&strand) {
357 return PublicValue::Uuid(x);
358 }
359 PublicValue::String(strand)
360 }
361 async fn parse_value_object<VP>(
362 &mut self,
363 stk: &mut Stk,
364 start: Span,
365 mut obj: BTreeMap<String, PublicValue>,
366 ) -> ParseResult<PublicObject>
367 where
368 VP: ValueParseFunc,
369 {
370 loop {
371 if self.eat(t!("}")) {
372 return Ok(PublicObject::from(obj));
373 }
374 let key = self.parse_object_key()?;
375 expected!(self, t!(":"));
376 let value = stk.run(|ctx| VP::parse(self, ctx)).await?;
377 obj.insert(key, value);
378 if !self.eat(t!(",")) {
379 self.expect_closing_delimiter(t!("}"), start)?;
380 return Ok(PublicObject::from(obj));
381 }
382 }
383 }
384 async fn parse_value_set<VP>(&mut self, stk: &mut Stk, start: Span) -> ParseResult<PublicSet>
385 where
386 VP: ValueParseFunc,
387 {
388 let mut set = PublicSet::new();
389 loop {
390 if self.eat(t!("}")) {
391 return Ok(set);
392 }
393 let value = stk.run(|stk| VP::parse(self, stk)).await?;
394 set.insert(value);
395 if !self.eat(t!(",")) {
396 if set.len() <= 1 {
397 unexpected!(
398 self, self.peek(), "`,`", =>
399 "Sets with a single value must have at least a single comma"
400 );
401 }
402 self.expect_closing_delimiter(t!("}"), start)?;
403 return Ok(set);
404 }
405 }
406 }
407 async fn parse_value_array<VP>(
408 &mut self,
409 stk: &mut Stk,
410 start: Span,
411 ) -> ParseResult<PublicArray>
412 where
413 VP: ValueParseFunc,
414 {
415 let mut array = Vec::new();
416 loop {
417 if self.eat(t!("]")) {
418 return Ok(PublicArray::from(array));
419 }
420 let value = stk.run(|stk| VP::parse(self, stk)).await?;
421 array.push(value);
422 if !self.eat(t!(",")) {
423 self.expect_closing_delimiter(t!("]"), start)?;
424 return Ok(PublicArray::from(array));
425 }
426 }
427 }
428 async fn parse_value_table(&mut self) -> ParseResult<PublicTable> {
429 let table = self.parse_ident()?;
430 Ok(PublicTable::new(table))
431 }
432 pub async fn parse_value_record_id(&mut self, stk: &mut Stk) -> ParseResult<PublicRecordId> {
433 self.parse_value_record_id_inner::<SurrealQL>(stk).await
434 }
435 async fn parse_value_record_id_inner<VP>(
436 &mut self,
437 stk: &mut Stk,
438 ) -> ParseResult<PublicRecordId>
439 where
440 VP: ValueParseFunc,
441 {
442 let table = self.parse_ident()?;
443 expected!(self, t!(":"));
444 let peek = self.peek();
445 let key = match peek.kind {
446 t!("u'") | t!("u\"") => PublicRecordIdKey::Uuid(self.next_token_value::<PublicUuid>()?),
447 t!("{") => {
448 let peek = self.pop_peek();
449 PublicRecordIdKey::Object(
450 self.parse_value_object::<VP>(stk, peek.span, BTreeMap::new())
451 .await?,
452 )
453 }
454 t!("[") => {
455 let peek = self.pop_peek();
456 PublicRecordIdKey::Array(self.parse_value_array::<VP>(stk, peek.span).await?)
457 }
458 t!("+") => {
459 self.pop_peek();
460 let digits_token = if let Some(digits_token) = self.peek_whitespace() {
461 match digits_token.kind {
462 TokenKind::Digits => digits_token,
463 _ => unexpected!(self, digits_token, "an integer"),
464 }
465 } else {
466 bail!(
467 "Unexpected whitespace",@ self.last_span() =>
468 "No whitespace allowed after this token"
469 )
470 };
471 match self.peek_whitespace().map(|x| x.kind) {
472 Some(t!(".")) => {
473 unexpected!(
474 self, self.peek(), "an integer", =>
475 "Numeric Record-id keys can only be integers"
476 );
477 }
478 Some(x) if Self::kind_is_identifier(x) => {
479 let span = peek.span.covers(self.peek().span);
480 bail!("Unexpected token `{x}` expected an integer", @ span);
481 }
482 _ => {}
483 }
484 let digits_str = self.span_str(digits_token.span);
485 if let Ok(number) = digits_str.parse() {
486 PublicRecordIdKey::Number(number)
487 } else {
488 PublicRecordIdKey::String(digits_str.to_owned())
489 }
490 }
491 t!("-") => {
492 self.pop_peek();
493 let token = expected!(self, TokenKind::Digits);
494 if let Ok(number) = self.lex_compound(token, compound::integer::<u64>) {
495 match number.value.cmp(&((i64::MAX as u64) + 1)) {
496 Ordering::Less => PublicRecordIdKey::Number(-(number.value as i64)),
497 Ordering::Equal => PublicRecordIdKey::Number(i64::MIN),
498 Ordering::Greater => PublicRecordIdKey::String(format!(
499 "-{}",
500 self.lexer.span_str(number.span)
501 )),
502 }
503 } else {
504 PublicRecordIdKey::String(format!("-{}", self.lexer.span_str(token.span)))
505 }
506 }
507 TokenKind::Digits => {
508 if self.settings.flexible_record_id
509 && let Some(peek) = self.peek_whitespace1()
510 && Self::kind_is_identifier(peek.kind)
511 {
512 let ident = self.parse_flexible_ident()?;
513 PublicRecordIdKey::String(ident)
514 } else {
515 self.pop_peek();
516 let digits_str = self.span_str(peek.span);
517 if let Ok(number) = digits_str.parse::<i64>() {
518 PublicRecordIdKey::Number(number)
519 } else {
520 PublicRecordIdKey::String(digits_str.to_owned())
521 }
522 }
523 }
524 _ => {
525 let ident = if self.settings.flexible_record_id {
526 self.parse_flexible_ident()?
527 } else {
528 self.parse_ident()?
529 };
530 PublicRecordIdKey::String(ident)
531 }
532 };
533 Ok(PublicRecordId::new(table, key))
534 }
535}