linkrs_query/parser/parsing/traversal_parser/
find_path.rs1use crate::parser::ast::stmt::*;
2use crate::parser::core::error::ParseError;
3use crate::parser::parsing::clause_parser::ClauseParser;
4use crate::parser::parsing::parse_context::ParseContext;
5use crate::parser::TokenKind;
6use linkrs_core::types::graph_schema::EdgeDirection;
7
8use super::TraversalParser;
9
10impl TraversalParser {
11 pub fn parse_find_path_statement(
13 &mut self,
14 ctx: &mut ParseContext,
15 ) -> Result<Stmt, ParseError> {
16 let start_span = ctx.current_span();
17 ctx.expect_token(TokenKind::Find)?;
18
19 let shortest = if ctx.match_token(TokenKind::Shortest) {
20 true
21 } else {
22 !ctx.match_token(TokenKind::All)
23 };
24
25 ctx.expect_token(TokenKind::Path)?;
26
27 let mut with_loop = false;
28 let mut with_trail = false;
29 let mut with_walk = false;
30 while ctx.match_token(TokenKind::With) {
31 if ctx.match_token(TokenKind::Loop) {
32 with_loop = true;
33 } else if ctx.match_token(TokenKind::Trail) {
34 with_trail = true;
35 } else if ctx.match_token(TokenKind::Walk) {
36 with_walk = true;
37 }
38 }
39
40 ctx.expect_token(TokenKind::From)?;
41 let from_span = ctx.current_span();
42 let from_clause = ctx.recover_clause(
43 |c| {
44 Ok(FromClause {
45 span: c.current_span(),
46 vertices: Vec::new(),
47 })
48 },
49 |c| {
50 let vertices = self.parse_expression_list(c)?;
51 Ok(FromClause {
52 span: from_span,
53 vertices,
54 })
55 },
56 )?;
57
58 ctx.expect_token(TokenKind::To)?;
59 let to_vertex =
60 ctx.recover_clause(Self::create_true_expression, |c| self.parse_expression(c))?;
61
62 let over_present = ctx.check_token(TokenKind::Over);
66 let over = if over_present {
67 ctx.expect_token(TokenKind::Over)?;
68 ctx.recover_clause(
69 |c| {
70 Ok(OverClause {
71 span: c.current_span(),
72 edge_types: Vec::new(),
73 direction: EdgeDirection::Out,
74 })
75 },
76 |c| ClauseParser::new().parse_over_clause(c),
77 )?
78 } else {
79 OverClause {
80 span: ctx.current_span(),
81 edge_types: Vec::new(),
82 direction: EdgeDirection::Out,
83 }
84 };
85
86 let mut max_steps = None;
87 if ctx.match_token(TokenKind::Upto) {
88 let steps = ctx.recover_clause(
89 |_| Ok(None),
90 |c| c.expect_integer_literal().map(|n| n as usize).map(Some),
91 )?;
92 if let Some(n) = steps {
93 max_steps = Some(n);
94 ctx.expect_token(TokenKind::Step)?;
95 }
96 }
97
98 let weight_expression = if ctx.match_token(TokenKind::Weight) {
99 ctx.recover_clause(|_| Ok(None), |c| c.expect_identifier().map(Some))?
100 } else {
101 None
102 };
103
104 let where_clause = if ctx.match_token(TokenKind::Where) {
105 Some(ctx.recover_clause(Self::create_true_expression, |c| self.parse_expression(c))?)
106 } else {
107 Some(Self::create_true_expression(ctx)?)
108 };
109
110 let yield_clause = if ctx.match_token(TokenKind::Yield) {
111 ctx.recover_clause(
112 |_| Ok(None),
113 |c| ClauseParser::new().parse_yield_clause(c).map(Some),
114 )?
115 } else {
116 None
117 };
118
119 let span = ctx.span_since(start_span.start);
120
121 Ok(Stmt::FindPath(FindPathStmt {
122 span,
123 from: from_clause,
124 to: to_vertex,
125 over: Some(over),
126 where_clause,
127 shortest,
128 max_steps,
129 limit: None,
130 skip: None,
131 yield_clause,
132 weight_expression,
133 heuristic_expression: None,
134 with_loop,
135 with_trail,
136 with_walk,
137 }))
138 }
139}