surrealdb_core/syn/parser/
mod.rs1use self::token_buffer::TokenBuffer;
57use crate::{
58 sql::{self, Datetime, Duration, Strand, Uuid},
59 syn::{
60 error::{bail, SyntaxError},
61 lexer::{compound::NumberKind, Lexer},
62 token::{t, Span, Token, TokenKind},
63 },
64};
65use bytes::BytesMut;
66use reblessive::{Stack, Stk};
67
68mod basic;
69mod builtin;
70mod expression;
71mod function;
72mod glue;
73mod idiom;
74mod json;
75mod kind;
76pub(crate) mod mac;
77mod object;
78mod prime;
79mod stmt;
80mod thing;
81mod token;
82mod token_buffer;
83
84pub(crate) use mac::{enter_object_recursion, enter_query_recursion, unexpected};
85
86use super::error::{syntax_error, RenderedError};
87
88#[cfg(test)]
89pub mod test;
90
91pub type ParseResult<T> = Result<T, SyntaxError>;
93
94#[derive(Debug)]
96#[non_exhaustive]
97pub enum PartialResult<T> {
98 MoreData,
99 Empty {
101 used: usize,
102 },
103 Ok {
104 value: T,
105 used: usize,
106 },
107 Err {
108 err: SyntaxError,
109 used: usize,
110 },
111}
112
113#[derive(Default)]
114pub enum GluedValue {
115 Duration(Duration),
116 Datetime(Datetime),
117 Uuid(Uuid),
118 Number(NumberKind),
119 Strand(Strand),
120 #[default]
121 None,
122}
123
124#[derive(Clone, Debug)]
125pub struct ParserSettings {
126 pub legacy_strands: bool,
129 pub flexible_record_id: bool,
133 pub object_recursion_limit: usize,
136 pub query_recursion_limit: usize,
140 pub references_enabled: bool,
142 pub bearer_access_enabled: bool,
144 pub define_api_enabled: bool,
146}
147
148impl Default for ParserSettings {
149 fn default() -> Self {
150 ParserSettings {
151 legacy_strands: false,
152 flexible_record_id: true,
153 object_recursion_limit: 100,
154 query_recursion_limit: 20,
155 references_enabled: false,
156 bearer_access_enabled: false,
157 define_api_enabled: false,
158 }
159 }
160}
161
162pub struct Parser<'a> {
164 lexer: Lexer<'a>,
165 last_span: Span,
166 token_buffer: TokenBuffer<4>,
167 glued_value: GluedValue,
168 pub(crate) table_as_field: bool,
169 settings: ParserSettings,
170}
171
172impl<'a> Parser<'a> {
173 pub fn new(source: &'a [u8]) -> Self {
175 Parser::new_with_settings(source, ParserSettings::default())
176 }
177
178 pub fn new_with_settings(source: &'a [u8], settings: ParserSettings) -> Self {
180 Parser {
181 lexer: Lexer::new(source),
182 last_span: Span::empty(),
183 token_buffer: TokenBuffer::new(),
184 glued_value: GluedValue::None,
185 table_as_field: true,
186 settings,
187 }
188 }
189
190 pub fn with_settings(mut self, settings: ParserSettings) -> Self {
191 self.settings = settings;
192 self
193 }
194
195 #[allow(clippy::should_implement_trait)]
197 pub fn next(&mut self) -> Token {
198 let res = loop {
199 let res = self.token_buffer.pop().unwrap_or_else(|| self.lexer.next_token());
200 if res.kind != TokenKind::WhiteSpace {
201 break res;
202 }
203 };
204 self.last_span = res.span;
205 res
206 }
207
208 #[allow(clippy::should_implement_trait)]
212 pub fn next_whitespace(&mut self) -> Token {
213 let res = self.token_buffer.pop().unwrap_or_else(|| self.lexer.next_token());
214 self.last_span = res.span;
215 res
216 }
217
218 pub fn has_peek(&self) -> bool {
220 self.token_buffer.is_empty()
221 }
222
223 pub fn pop_peek(&mut self) -> Token {
227 let res = self.token_buffer.pop().unwrap();
228 self.last_span = res.span;
229 res
230 }
231
232 pub fn peek(&mut self) -> Token {
234 loop {
235 let Some(x) = self.token_buffer.first() else {
236 let res = loop {
237 let res = self.lexer.next_token();
238 if res.kind != TokenKind::WhiteSpace {
239 break res;
240 }
241 };
242 self.token_buffer.push(res);
243 return res;
244 };
245 if x.kind == TokenKind::WhiteSpace {
246 self.token_buffer.pop();
247 continue;
248 }
249 break x;
250 }
251 }
252
253 pub fn peek_whitespace(&mut self) -> Token {
258 let Some(x) = self.token_buffer.first() else {
259 let res = self.lexer.next_token();
260 self.token_buffer.push(res);
261 return res;
262 };
263 x
264 }
265
266 pub fn peek_kind(&mut self) -> TokenKind {
268 self.peek().kind
269 }
270
271 pub(crate) fn peek_token_at(&mut self, at: u8) -> Token {
274 for _ in self.token_buffer.len()..=at {
275 let r = loop {
276 let r = self.lexer.next_token();
277 if r.kind != TokenKind::WhiteSpace {
278 break r;
279 }
280 };
281 self.token_buffer.push(r);
282 }
283 self.token_buffer.at(at).unwrap()
284 }
285
286 pub fn peek1(&mut self) -> Token {
287 self.peek_token_at(1)
288 }
289
290 pub fn peek_whitespace_token_at(&mut self, at: u8) -> Token {
293 for _ in self.token_buffer.len()..=at {
294 let r = self.lexer.next_token();
295 self.token_buffer.push(r);
296 }
297 self.token_buffer.at(at).unwrap()
298 }
299
300 pub fn peek_whitespace1(&mut self) -> Token {
301 self.peek_whitespace_token_at(1)
302 }
303
304 pub fn recent_span(&mut self) -> Span {
307 self.token_buffer.first().map(|x| x.span).unwrap_or(self.last_span)
308 }
309
310 pub fn last_span(&mut self) -> Span {
312 self.last_span
313 }
314
315 pub fn assert_finished(&mut self) -> ParseResult<()> {
316 let p = self.peek();
317 if self.peek().kind != TokenKind::Eof {
318 bail!("Unexpected token `{}`, expected no more tokens",p.kind, @p.span);
319 }
320 Ok(())
321 }
322
323 pub fn eat(&mut self, token: TokenKind) -> bool {
326 let peek = self.peek();
327 if token == peek.kind {
328 self.token_buffer.pop();
329 self.last_span = peek.span;
330 true
331 } else {
332 false
333 }
334 }
335
336 pub fn eat_whitespace(&mut self, token: TokenKind) -> bool {
341 let peek = self.peek_whitespace();
342 if token == peek.kind {
343 self.token_buffer.pop();
344 self.last_span = peek.span;
345 true
346 } else {
347 false
348 }
349 }
350
351 fn prepend_token(&mut self, token: Token) {
354 self.token_buffer.push_front(token);
355 }
356
357 fn expect_closing_delimiter(&mut self, kind: TokenKind, should_close: Span) -> ParseResult<()> {
360 let peek = self.peek();
361 if peek.kind != kind {
362 bail!("Unexpected token `{}` expected delimiter `{kind}`",
363 peek.kind,
364 @self.recent_span(),
365 @should_close => "expected this delimiter to close"
366 );
367 }
368 self.pop_peek();
369 Ok(())
370 }
371
372 pub fn backup_after(&mut self, span: Span) {
374 self.token_buffer.clear();
375 self.lexer.backup_after(span);
376 }
377
378 pub async fn parse_query(&mut self, ctx: &mut Stk) -> ParseResult<sql::Query> {
382 let statements = self.parse_stmt_list(ctx).await?;
383 Ok(sql::Query(statements))
384 }
385
386 pub async fn parse_statement(&mut self, ctx: &mut Stk) -> ParseResult<sql::Statement> {
388 self.parse_stmt(ctx).await
389 }
390}
391
392pub struct StatementStream {
394 stack: Stack,
395 settings: ParserSettings,
396 col_offset: usize,
397 line_offset: usize,
398}
399
400impl StatementStream {
401 #[allow(clippy::new_without_default)]
402 pub fn new() -> Self {
403 Self::new_with_settings(ParserSettings::default())
404 }
405
406 pub fn new_with_settings(settings: ParserSettings) -> Self {
407 StatementStream {
408 stack: Stack::new(),
409 settings,
410 col_offset: 0,
411 line_offset: 0,
412 }
413 }
414
415 fn accumulate_line_col(&mut self, bytes: &[u8]) {
417 let (line_num, remaining) =
421 std::str::from_utf8(bytes).unwrap().lines().enumerate().last().unwrap_or((0, ""));
422
423 self.line_offset += line_num;
424 if line_num > 0 {
425 self.col_offset = 0;
426 }
427 self.col_offset += remaining.chars().count();
428 }
429
430 pub fn parse_partial(
439 &mut self,
440 buffer: &mut BytesMut,
441 ) -> Result<Option<sql::Statement>, RenderedError> {
442 let mut slice = &**buffer;
443 if slice.len() > u32::MAX as usize {
444 slice = &slice[..u32::MAX as usize];
446 }
447
448 let mut parser = Parser::new_with_settings(slice, self.settings.clone());
449
450 while parser.eat(t!(";")) {}
452
453 if parser.peek().span.offset != 0 && buffer.len() > u32::MAX as usize {
454 let eaten = buffer.split_to(parser.peek().span.offset as usize);
457 self.accumulate_line_col(&eaten);
458 slice = &**buffer;
459 if slice.len() > u32::MAX as usize {
460 slice = &slice[..u32::MAX as usize];
462 }
463 parser = Parser::new_with_settings(slice, self.settings.clone())
464 }
465
466 if parser.peek().is_eof() {
468 return Ok(None);
469 }
470
471 let res = self.stack.enter(|ctx| parser.parse_statement(ctx)).finish();
472 if parser.peek().is_eof() {
473 if buffer.len() > u32::MAX as usize {
474 let error = syntax_error!("Cannot parse query, statement exceeded maximum size of 4GB", @parser.last_span());
475 return Err(error
476 .render_on_bytes(buffer)
477 .offset_location(self.line_offset, self.col_offset));
478 }
479
480 return Ok(None);
484 }
485
486 if !parser.eat(t!(";")) {
488 let peek = parser.next();
489
490 if parser.peek1().is_eof() {
491 return Ok(None);
492 }
493
494 if let Err(e) = res {
495 return Err(e
496 .render_on_bytes(slice)
497 .offset_location(self.line_offset, self.col_offset));
498 }
499
500 let error = syntax_error!("Unexpected token `{}` expected the query to end.",peek.kind.as_str(),
501 @peek.span => "maybe forgot a semicolon after the previous statement?");
502 return Err(error
503 .render_on_bytes(slice)
504 .offset_location(self.line_offset, self.col_offset));
505 }
506
507 while parser.eat(t!(";")) {}
509
510 let eaten = buffer.split_to(parser.last_span().after_offset() as usize);
511 let res = res.map(Some).map_err(|e| {
512 e.render_on_bytes(&eaten).offset_location(self.line_offset, self.col_offset)
513 });
514 self.accumulate_line_col(&eaten);
515 res
516 }
517
518 pub fn parse_complete(
520 &mut self,
521 buffer: &mut BytesMut,
522 ) -> Result<Option<sql::Statement>, RenderedError> {
523 let mut slice = &**buffer;
524 if slice.len() > u32::MAX as usize {
525 slice = &slice[..u32::MAX as usize];
527 }
528
529 let mut parser = Parser::new_with_settings(slice, self.settings.clone());
530 while parser.eat(t!(";")) {}
532
533 if parser.peek().is_eof() {
534 buffer.clear();
536 return Ok(None);
537 }
538
539 match self.stack.enter(|ctx| parser.parse_statement(ctx)).finish() {
540 Ok(x) => {
541 if !parser.peek().is_eof() && !parser.eat(t!(";")) {
542 let peek = parser.peek();
543 let error = syntax_error!("Unexpected token `{}` expected the query to end.",peek.kind.as_str(),
544 @peek.span => "maybe forgot a semicolon after the previous statement?");
545 return Err(error
546 .render_on_bytes(slice)
547 .offset_location(self.line_offset, self.col_offset));
548 }
549
550 let eaten = buffer.split_to(parser.last_span().after_offset() as usize);
551 self.accumulate_line_col(&eaten);
552 Ok(Some(x))
553 }
554 Err(e) => {
555 Err(e.render_on_bytes(slice).offset_location(self.line_offset, self.col_offset))
556 }
557 }
558 }
559}