Parses a counted repetition operation. A counted repetition operator corresponds to the {m,n} syntax, and does not include the ?, * or + operators. This assumes that the paser is currently positioned at the opening `{` and advances the parser to the first character after the operator. (Note that the operator may include a single additional `?`, which makes the operator ungreedy.) The caller shou
(
&self,
mut concat: ast::Concat,
)
| 1088 | /// concatenation returned includes the repetition operator applied to the |
| 1089 | /// last expression in the given concatenation. |
| 1090 | fn parse_counted_repetition( |
| 1091 | &self, |
| 1092 | mut concat: ast::Concat, |
| 1093 | ) -> Result<ast::Concat> { |
| 1094 | assert!(self.char() == '{'); |
| 1095 | let start = self.pos(); |
| 1096 | let ast = match concat.asts.pop() { |
| 1097 | Some(ast) => ast, |
| 1098 | None => return Err(self.error( |
| 1099 | self.span(), |
| 1100 | ast::ErrorKind::RepetitionMissing, |
| 1101 | )), |
| 1102 | }; |
| 1103 | match ast { |
| 1104 | Ast::Empty(_) | Ast::Flags(_) => return Err(self.error( |
| 1105 | self.span(), |
| 1106 | ast::ErrorKind::RepetitionMissing, |
| 1107 | )), |
| 1108 | _ => {} |
| 1109 | } |
| 1110 | if !self.bump_and_bump_space() { |
| 1111 | return Err(self.error( |
| 1112 | Span::new(start, self.pos()), |
| 1113 | ast::ErrorKind::RepetitionCountUnclosed, |
| 1114 | )); |
| 1115 | } |
| 1116 | let count_start = self.parse_decimal()?; |
| 1117 | let mut range = ast::RepetitionRange::Exactly(count_start); |
| 1118 | if self.is_eof() { |
| 1119 | return Err(self.error( |
| 1120 | Span::new(start, self.pos()), |
| 1121 | ast::ErrorKind::RepetitionCountUnclosed, |
| 1122 | )); |
| 1123 | } |
| 1124 | if self.char() == ',' { |
| 1125 | if !self.bump_and_bump_space() { |
| 1126 | return Err(self.error( |
| 1127 | Span::new(start, self.pos()), |
| 1128 | ast::ErrorKind::RepetitionCountUnclosed, |
| 1129 | )); |
| 1130 | } |
| 1131 | if self.char() != '}' { |
| 1132 | let count_end = self.parse_decimal()?; |
| 1133 | range = ast::RepetitionRange::Bounded(count_start, count_end); |
| 1134 | } else { |
| 1135 | range = ast::RepetitionRange::AtLeast(count_start); |
| 1136 | } |
| 1137 | } |
| 1138 | if self.is_eof() || self.char() != '}' { |
| 1139 | return Err(self.error( |
| 1140 | Span::new(start, self.pos()), |
| 1141 | ast::ErrorKind::RepetitionCountUnclosed, |
| 1142 | )); |
| 1143 | } |
| 1144 | |
| 1145 | let mut greedy = true; |
| 1146 | if self.bump_and_bump_space() && self.char() == '?' { |
| 1147 | greedy = false; |
no test coverage detected