Parse MATCH and OPTIONAL MATCH clauses from the pattern section.
(section: &str)
| 120 | |
| 121 | /// Parse MATCH and OPTIONAL MATCH clauses from the pattern section. |
| 122 | pub(super) fn parse_match_clauses(section: &str) -> crate::Result<Vec<MatchClause>> { |
| 123 | let mut clauses = Vec::new(); |
| 124 | let upper = section.to_uppercase(); |
| 125 | |
| 126 | let mut pos = 0; |
| 127 | while pos < section.len() { |
| 128 | let remaining_upper = &upper[pos..]; |
| 129 | let remaining = §ion[pos..]; |
| 130 | |
| 131 | let (optional, match_start) = if remaining_upper.trim_start().starts_with("OPTIONAL MATCH") |
| 132 | { |
| 133 | let ws = remaining.len() - remaining.trim_start().len(); |
| 134 | (true, pos + ws + 14) |
| 135 | } else if remaining_upper.trim_start().starts_with("MATCH") { |
| 136 | let ws = remaining.len() - remaining.trim_start().len(); |
| 137 | (false, pos + ws + 5) |
| 138 | } else { |
| 139 | break; |
| 140 | }; |
| 141 | |
| 142 | let rest_upper = &upper[match_start..]; |
| 143 | let next_match = find_next_match_keyword(rest_upper) |
| 144 | .map(|offset| match_start + offset) |
| 145 | .unwrap_or(section.len()); |
| 146 | |
| 147 | let pattern_text = section[match_start..next_match].trim(); |
| 148 | let patterns = parse_pattern_chains(pattern_text)?; |
| 149 | |
| 150 | clauses.push(MatchClause { patterns, optional }); |
| 151 | pos = next_match; |
| 152 | } |
| 153 | |
| 154 | if clauses.is_empty() { |
| 155 | return Err(crate::Error::BadRequest { |
| 156 | detail: "no MATCH clause found".to_string(), |
| 157 | }); |
| 158 | } |
| 159 | |
| 160 | Ok(clauses) |
| 161 | } |
| 162 | |
| 163 | /// Parse comma-separated pattern chains. |
| 164 | fn parse_pattern_chains(text: &str) -> crate::Result<Vec<PatternChain>> { |
no test coverage detected