1use std::sync::Arc;
2
3use crate::parser::core::error::{ParseError, ParseErrorKind};
4use crate::parser::lexing::LexError;
5use crate::parser::lexing::Lexer;
6use crate::parser::ParseErrors;
7use crate::parser::Token;
8use crate::parser::TokenKind;
9use linkrs_core::types::expr::expression_context::ExpressionAnalysisContext;
10use linkrs_core::types::{Position, Span};
11
12const RECOVERY_LIMIT: usize = 5;
13
14const STATEMENT_SYNC_TOKENS: &[TokenKind] = &[
15 TokenKind::Semicolon,
16 TokenKind::Match,
17 TokenKind::Go,
18 TokenKind::Fetch,
19 TokenKind::Insert,
20 TokenKind::Copy,
21 TokenKind::Delete,
22 TokenKind::Update,
23 TokenKind::Upsert,
24 TokenKind::Create,
25 TokenKind::Drop,
26 TokenKind::Show,
27 TokenKind::Explain,
28 TokenKind::Profile,
29 TokenKind::Group,
30 TokenKind::Lookup,
31 TokenKind::Find,
32 TokenKind::Return,
33 TokenKind::With,
34 TokenKind::Unwind,
35 TokenKind::Set,
36 TokenKind::Use,
37 TokenKind::Begin,
38 TokenKind::Commit,
39 TokenKind::Rollback,
40 TokenKind::Savepoint,
41 TokenKind::Release,
42 TokenKind::Search,
43 TokenKind::Dollar,
44 TokenKind::Eof,
45];
46
47const CLAUSE_SYNC_TOKENS: &[TokenKind] = &[
48 TokenKind::Semicolon,
49 TokenKind::Where,
50 TokenKind::Return,
51 TokenKind::With,
52 TokenKind::Yield,
53 TokenKind::Order,
54 TokenKind::Limit,
55 TokenKind::Skip,
56 TokenKind::Having,
57 TokenKind::Group,
58 TokenKind::Union,
59 TokenKind::Intersect,
60 TokenKind::SetMinus,
61 TokenKind::Pipe,
62 TokenKind::Match,
63 TokenKind::Go,
64 TokenKind::Find,
65 TokenKind::Lookup,
66 TokenKind::Insert,
67 TokenKind::Update,
68 TokenKind::Delete,
69 TokenKind::And,
70 TokenKind::Or,
71 TokenKind::Eof,
72];
73
74const EXPR_SYNC_TOKENS: &[TokenKind] = &[
75 TokenKind::Comma,
76 TokenKind::RParen,
77 TokenKind::RBracket,
78 TokenKind::RBrace,
79 TokenKind::Then,
80 TokenKind::Else,
81 TokenKind::End,
82];
83
84#[derive(Debug, Clone, Copy, PartialEq, Eq)]
85pub enum RecoveryScope {
86 Statement,
87 Clause,
88 Expression,
89}
90
91pub struct ParseContext<'a> {
92 lexer: Lexer<'a>,
93 current_token: Token,
94 next_token: Option<Token>,
95 errors: ParseErrors,
96 compat_mode: bool,
97 upsert_mode: bool,
98 edge_syntax_mode: bool,
99 suppress_pipe_or: bool,
104 recursion_depth: usize,
105 max_recursion_depth: usize,
106 expr_context: Arc<ExpressionAnalysisContext>,
107 recovery_count: usize,
108 type_alias_manager: Option<Arc<linkrs_core::metadata::TypeAliasManager>>,
111 recursive_comprehension: Option<crate::parser::ast::pattern::RecursiveComprehension>,
113}
114
115pub struct ParseContextCheckpoint {
116 lexer_ckpt: crate::parser::lexing::LexerCheckpoint,
117 current_token: Token,
118 next_token: Option<Token>,
119}
120
121mod literals;
122
123impl<'a> ParseContext<'a> {
124 pub fn new(input: &'a str) -> Self {
125 let lexer = Lexer::new(input);
126 let current_token = lexer.current_token().clone();
127 let expr_context = Arc::new(ExpressionAnalysisContext::new());
128
129 Self {
130 lexer,
131 current_token,
132 next_token: None,
133 errors: ParseErrors::new(),
134 compat_mode: false,
135 upsert_mode: false,
136 edge_syntax_mode: false,
137 suppress_pipe_or: false,
138 recursion_depth: 0,
139 max_recursion_depth: 100,
140 expr_context,
141 recovery_count: 0,
142 type_alias_manager: None,
143 recursive_comprehension: None,
144 }
145 }
146
147 pub fn from_string(input: String) -> Self {
148 let lexer = Lexer::from_string(input);
149 let current_token = lexer.current_token().clone();
150 let expr_context = Arc::new(ExpressionAnalysisContext::new());
151
152 Self {
153 lexer,
154 current_token,
155 next_token: None,
156 errors: ParseErrors::new(),
157 compat_mode: false,
158 upsert_mode: false,
159 edge_syntax_mode: false,
160 suppress_pipe_or: false,
161 recursion_depth: 0,
162 max_recursion_depth: 100,
163 expr_context,
164 recovery_count: 0,
165 type_alias_manager: None,
166 recursive_comprehension: None,
167 }
168 }
169
170 pub fn checkpoint(&self) -> ParseContextCheckpoint {
171 ParseContextCheckpoint {
172 lexer_ckpt: self.lexer.checkpoint(),
173 current_token: self.current_token.clone(),
174 next_token: self.next_token.clone(),
175 }
176 }
177
178 pub fn restore(&mut self, ckpt: ParseContextCheckpoint) {
179 self.lexer.restore(ckpt.lexer_ckpt);
180 self.current_token = ckpt.current_token;
181 self.next_token = ckpt.next_token;
182 }
183
184 pub fn set_expression_context(&mut self, expr_context: Arc<ExpressionAnalysisContext>) {
185 self.expr_context = expr_context;
186 }
187
188 pub fn expression_context(&self) -> &Arc<ExpressionAnalysisContext> {
189 &self.expr_context
190 }
191
192 pub fn set_type_alias_manager(
194 &mut self,
195 manager: Arc<linkrs_core::metadata::TypeAliasManager>,
196 ) {
197 self.type_alias_manager = Some(manager);
198 }
199
200 pub fn resolve_named_type(&self, name: &str) -> Option<linkrs_core::DataType> {
203 if let Ok(builtin) = name.parse::<linkrs_core::DataType>() {
204 return Some(builtin);
205 }
206 let manager = self.type_alias_manager.as_ref()?;
207 manager
208 .resolve(name, &|text| text.parse::<linkrs_core::DataType>().ok())
209 .ok()
210 }
211
212 pub fn expression_context_clone(&self) -> Arc<ExpressionAnalysisContext> {
213 self.expr_context.clone()
214 }
215
216 pub fn take_recursive_comprehension(
217 &mut self,
218 ) -> Option<crate::parser::ast::pattern::RecursiveComprehension> {
219 self.recursive_comprehension.take()
220 }
221
222 pub fn set_recursive_comprehension(
223 &mut self,
224 rc: crate::parser::ast::pattern::RecursiveComprehension,
225 ) {
226 self.recursive_comprehension = Some(rc);
227 }
228
229 pub fn lexer(&self) -> &Lexer<'a> {
230 &self.lexer
231 }
232
233 pub fn lexer_mut(&mut self) -> &mut Lexer<'a> {
234 &mut self.lexer
235 }
236
237 pub fn set_compat_mode(&mut self, enabled: bool) {
238 self.compat_mode = enabled;
239 }
240
241 pub fn set_upsert_mode(&mut self, enabled: bool) {
242 self.upsert_mode = enabled;
243 }
244
245 pub fn is_upsert_mode(&self) -> bool {
246 self.upsert_mode
247 }
248
249 pub fn is_edge_syntax_mode(&self) -> bool {
252 self.edge_syntax_mode
253 }
254
255 pub fn with_edge_syntax_mode<T>(
258 &mut self,
259 f: impl FnOnce(&mut Self) -> Result<T, ParseError>,
260 ) -> Result<T, ParseError> {
261 let saved = self.edge_syntax_mode;
262 self.edge_syntax_mode = true;
263 let result = f(self);
264 self.edge_syntax_mode = saved;
265 result
266 }
267
268 pub fn is_pipe_or_suppressed(&self) -> bool {
271 self.suppress_pipe_or
272 }
273
274 pub fn with_pipe_or_suppression<T>(
277 &mut self,
278 value: bool,
279 f: impl FnOnce(&mut Self) -> Result<T, ParseError>,
280 ) -> Result<T, ParseError> {
281 let saved = self.suppress_pipe_or;
282 self.suppress_pipe_or = value;
283 let result = f(self);
284 self.suppress_pipe_or = saved;
285 result
286 }
287
288 pub fn enter_recursion(&mut self) -> Result<(), ParseError> {
289 self.recursion_depth += 1;
290 if self.recursion_depth > self.max_recursion_depth {
291 let pos = self.current_position();
292 Err(ParseError::new(
293 ParseErrorKind::SyntaxError,
294 "Recursion limit exceeded".to_string(),
295 pos,
296 ))
297 } else {
298 Ok(())
299 }
300 }
301
302 pub fn exit_recursion(&mut self) {
303 if self.recursion_depth > 0 {
304 self.recursion_depth -= 1;
305 }
306 }
307
308 pub fn add_error(&mut self, error: ParseError) {
309 self.errors.add(error);
310 }
311
312 pub fn add_lex_error(&mut self, error: LexError) {
313 self.errors.add(error.into());
314 }
315
316 pub fn errors(&self) -> &ParseErrors {
317 &self.errors
318 }
319
320 pub fn has_errors(&self) -> bool {
321 !self.errors.is_empty() || self.lexer.has_errors()
322 }
323
324 pub fn take_errors(&mut self) -> ParseErrors {
325 for lex_error in self.lexer.take_errors() {
326 self.errors.add(lex_error.into());
327 }
328 std::mem::take(&mut self.errors)
329 }
330
331 pub fn current_position(&self) -> Position {
332 self.lexer.current_position()
333 }
334
335 pub fn current_span(&self) -> Span {
336 let pos = self.current_position();
337 Span::new(pos, pos)
338 }
339
340 pub fn merge_span(&self, start: Position, end: Position) -> Span {
341 Span::new(start, end)
342 }
343
344 pub fn span_since(&self, start: Position) -> Span {
348 let end = self.current_span();
349 Span::new(start, end.end)
350 }
351
352 pub fn current_token(&self) -> &Token {
353 &self.current_token
354 }
355
356 pub fn next_token(&mut self) {
357 if let Some(tok) = self.next_token.take() {
358 self.current_token = tok;
359 } else {
360 self.current_token = self.lexer.next_token();
361 }
362 }
363
364 pub fn peek_token(&mut self) -> &Token {
370 if self.next_token.is_none() {
371 self.next_token = Some(self.lexer.next_token());
372 }
373 self.next_token
374 .as_ref()
375 .expect("lookahead buffer should be filled")
376 }
377
378 pub fn match_token(&mut self, expected: TokenKind) -> bool {
379 if self.current_token.kind == expected {
380 self.next_token();
381 true
382 } else {
383 false
384 }
385 }
386
387 pub fn check_token(&self, expected: TokenKind) -> bool {
388 self.current_token.kind == expected
389 }
390
391 pub fn expect_token(&mut self, expected: TokenKind) -> Result<(), ParseError> {
392 if self.current_token.kind == expected {
393 self.next_token();
394 Ok(())
395 } else {
396 let pos = self.current_position();
397 Err(ParseError::new(
398 ParseErrorKind::UnexpectedToken,
399 format!(
400 "Expected {:?}, found {:?}",
401 expected, self.current_token.kind
402 ),
403 pos,
404 )
405 .with_expected_tokens(vec![format!("{:?}", expected)]))
406 }
407 }
408
409 pub fn is_recovery_exhausted(&self) -> bool {
410 self.recovery_count >= RECOVERY_LIMIT
411 }
412
413 pub fn record_recovery(&mut self) {
414 self.recovery_count += 1;
415 }
416
417 pub fn reset_recovery_count(&mut self) {
418 self.recovery_count = 0;
419 }
420
421 pub fn synchronize(&mut self, scope: RecoveryScope) {
422 if self.is_recovery_exhausted() {
423 return;
424 }
425
426 let sync_tokens: &[TokenKind] = match scope {
427 RecoveryScope::Statement => STATEMENT_SYNC_TOKENS,
428 RecoveryScope::Clause => CLAUSE_SYNC_TOKENS,
429 RecoveryScope::Expression => EXPR_SYNC_TOKENS,
430 };
431
432 while self.current_token.kind != TokenKind::Eof {
433 if sync_tokens.contains(&self.current_token.kind) {
434 return;
435 }
436 self.next_token();
437 }
438 }
439
440 pub fn try_recover(
441 &mut self,
442 error: ParseError,
443 scope: RecoveryScope,
444 ) -> Result<(), ParseError> {
445 if self.is_recovery_exhausted() {
446 return Err(error);
447 }
448
449 self.add_error(error.mark_recovered());
450 self.record_recovery();
451 self.synchronize(scope);
452 Ok(())
453 }
454
455 pub fn recover_clause<T>(
465 &mut self,
466 fallback: impl FnOnce(&mut ParseContext) -> Result<T, ParseError>,
467 parse: impl FnOnce(&mut ParseContext) -> Result<T, ParseError>,
468 ) -> Result<T, ParseError> {
469 match parse(self) {
470 Ok(value) => Ok(value),
471 Err(error) => match self.try_recover(error, RecoveryScope::Clause) {
472 Ok(()) => fallback(self),
473 Err(error) => Err(error),
474 },
475 }
476 }
477
478 pub fn consume_value(&mut self) -> Result<linkrs_core::Value, ParseError> {
479 match &self.current_token.kind {
480 TokenKind::StringLiteral(s) => {
481 let s = s.clone();
482 self.next_token();
483 Ok(linkrs_core::Value::string(s))
484 }
485 TokenKind::IntegerLiteral(n) => {
486 let n = *n;
487 self.next_token();
488 Ok(linkrs_core::Value::BigInt(n))
489 }
490 TokenKind::FloatLiteral(f) => {
491 let f = *f;
492 self.next_token();
493 Ok(linkrs_core::Value::Double(f))
494 }
495 TokenKind::BooleanLiteral(b) => {
496 let b = *b;
497 self.next_token();
498 Ok(linkrs_core::Value::Bool(b))
499 }
500 TokenKind::Null => {
501 self.next_token();
502 Ok(linkrs_core::Value::Null(linkrs_core::null::NullType::Null))
503 }
504 _ => {
505 let pos = self.current_position();
506 Err(ParseError::new(
507 ParseErrorKind::UnexpectedToken,
508 format!("Expected value, found {:?}", self.current_token.kind),
509 pos,
510 ))
511 }
512 }
513 }
514}