Skip to main content

reddb_server/storage/query/parser/
graph_commands.rs

1//! Graph Command Parser: GRAPH NEIGHBORHOOD | SHORTEST_PATH | TRAVERSE | CENTRALITY | ...
2
3use super::super::ast::{GraphCommand, QueryExpr};
4use super::super::lexer::Token;
5use super::error::ParseError;
6use super::Parser;
7
8impl<'a> Parser<'a> {
9    /// Parse: GRAPH subcommand ...
10    pub fn parse_graph_command(&mut self) -> Result<QueryExpr, ParseError> {
11        self.expect(Token::Graph)?;
12        match self.peek().clone() {
13            Token::Neighborhood => self.parse_graph_neighborhood(),
14            Token::ShortestPath => self.parse_graph_shortest_path(),
15            Token::Traverse => self.parse_graph_traverse(),
16            Token::Centrality => self.parse_graph_centrality(),
17            Token::Community => self.parse_graph_community(),
18            Token::Components => self.parse_graph_components(),
19            Token::Cycles => self.parse_graph_cycles(),
20            Token::Clustering => self.parse_graph_clustering(),
21            Token::TopologicalSort => self.parse_graph_topological_sort(),
22            Token::Properties => self.parse_graph_properties(),
23            _ => Err(ParseError::expected(
24                vec![
25                    "NEIGHBORHOOD",
26                    "SHORTEST_PATH",
27                    "TRAVERSE",
28                    "CENTRALITY",
29                    "COMMUNITY",
30                    "COMPONENTS",
31                    "CYCLES",
32                    "CLUSTERING",
33                    "TOPOLOGICAL_SORT",
34                    "PROPERTIES",
35                ],
36                self.peek(),
37                self.position(),
38            )),
39        }
40    }
41
42    /// Parse: GRAPH NEIGHBORHOOD 'source' [DEPTH n] [DIRECTION outgoing|incoming|both]
43    fn parse_graph_neighborhood(&mut self) -> Result<QueryExpr, ParseError> {
44        self.advance()?; // consume NEIGHBORHOOD
45        let source = self.parse_string()?;
46        let mut depth = 3;
47        let mut direction = "outgoing".to_string();
48
49        loop {
50            if self.consume(&Token::Depth)? {
51                depth = self.parse_integer()? as u32;
52            } else if self.consume(&Token::Direction)? {
53                direction = self.expect_ident_or_keyword()?;
54            } else {
55                break;
56            }
57        }
58
59        Ok(QueryExpr::GraphCommand(GraphCommand::Neighborhood {
60            source,
61            depth,
62            direction,
63        }))
64    }
65
66    /// Parse: GRAPH SHORTEST_PATH 'source' TO 'target' [ALGORITHM bfs|dijkstra] [DIRECTION dir]
67    fn parse_graph_shortest_path(&mut self) -> Result<QueryExpr, ParseError> {
68        self.advance()?; // consume SHORTEST_PATH
69        let source = self.parse_string()?;
70        self.expect(Token::To)?;
71        let target = self.parse_string()?;
72        let algorithm = if self.consume(&Token::Algorithm)? {
73            self.expect_ident_or_keyword()?
74        } else {
75            "bfs".to_string()
76        };
77        let direction = if self.consume(&Token::Direction)? {
78            self.expect_ident_or_keyword()?
79        } else {
80            "outgoing".to_string()
81        };
82        Ok(QueryExpr::GraphCommand(GraphCommand::ShortestPath {
83            source,
84            target,
85            algorithm,
86            direction,
87        }))
88    }
89
90    /// Parse: GRAPH TRAVERSE 'source' [STRATEGY bfs|dfs] [DEPTH n] [DIRECTION dir]
91    fn parse_graph_traverse(&mut self) -> Result<QueryExpr, ParseError> {
92        self.advance()?; // consume TRAVERSE
93        let source = self.parse_string()?;
94        let strategy = if self.consume(&Token::Strategy)? {
95            self.expect_ident_or_keyword()?
96        } else {
97            "bfs".to_string()
98        };
99        let depth = if self.consume(&Token::Depth)? {
100            self.parse_integer()? as u32
101        } else {
102            5
103        };
104        let direction = if self.consume(&Token::Direction)? {
105            self.expect_ident_or_keyword()?
106        } else {
107            "outgoing".to_string()
108        };
109        Ok(QueryExpr::GraphCommand(GraphCommand::Traverse {
110            source,
111            strategy,
112            depth,
113            direction,
114        }))
115    }
116
117    /// Parse: GRAPH CENTRALITY [ALGORITHM degree|closeness|betweenness|eigenvector|pagerank]
118    fn parse_graph_centrality(&mut self) -> Result<QueryExpr, ParseError> {
119        self.advance()?; // consume CENTRALITY
120        let algorithm = if self.consume(&Token::Algorithm)? {
121            self.expect_ident_or_keyword()?
122        } else {
123            "degree".to_string()
124        };
125        Ok(QueryExpr::GraphCommand(GraphCommand::Centrality {
126            algorithm,
127        }))
128    }
129
130    /// Parse: GRAPH COMMUNITY [ALGORITHM label_propagation|louvain] [MAX_ITERATIONS n]
131    fn parse_graph_community(&mut self) -> Result<QueryExpr, ParseError> {
132        self.advance()?; // consume COMMUNITY
133        let algorithm = if self.consume(&Token::Algorithm)? {
134            self.expect_ident_or_keyword()?
135        } else {
136            "label_propagation".to_string()
137        };
138        let max_iterations = if self.consume(&Token::MaxIterations)? {
139            self.parse_integer()? as u32
140        } else {
141            100
142        };
143        Ok(QueryExpr::GraphCommand(GraphCommand::Community {
144            algorithm,
145            max_iterations,
146        }))
147    }
148
149    /// Parse: GRAPH COMPONENTS [MODE connected|weak|strong]
150    fn parse_graph_components(&mut self) -> Result<QueryExpr, ParseError> {
151        self.advance()?; // consume COMPONENTS
152        let mode = if self.consume(&Token::Mode)? {
153            self.expect_ident_or_keyword()?
154        } else {
155            "connected".to_string()
156        };
157        Ok(QueryExpr::GraphCommand(GraphCommand::Components { mode }))
158    }
159
160    /// Parse: GRAPH CYCLES [MAX_LENGTH n]
161    fn parse_graph_cycles(&mut self) -> Result<QueryExpr, ParseError> {
162        self.advance()?; // consume CYCLES
163        let max_length = if self.consume(&Token::MaxLength)? {
164            self.parse_integer()? as u32
165        } else {
166            10
167        };
168        Ok(QueryExpr::GraphCommand(GraphCommand::Cycles { max_length }))
169    }
170
171    /// Parse: GRAPH CLUSTERING
172    fn parse_graph_clustering(&mut self) -> Result<QueryExpr, ParseError> {
173        self.advance()?; // consume CLUSTERING
174        Ok(QueryExpr::GraphCommand(GraphCommand::Clustering))
175    }
176
177    /// Parse: GRAPH TOPOLOGICAL_SORT
178    fn parse_graph_topological_sort(&mut self) -> Result<QueryExpr, ParseError> {
179        self.advance()?; // consume TOPOLOGICAL_SORT
180        Ok(QueryExpr::GraphCommand(GraphCommand::TopologicalSort))
181    }
182
183    /// Parse: GRAPH PROPERTIES
184    fn parse_graph_properties(&mut self) -> Result<QueryExpr, ParseError> {
185        self.advance()?; // consume PROPERTIES
186        Ok(QueryExpr::GraphCommand(GraphCommand::Properties))
187    }
188}