Parses a `FOR` statement.
(&mut self, for_pos: LineCol)
| 1249 | |
| 1250 | /// Parses a `FOR` statement. |
| 1251 | fn parse_for(&mut self, for_pos: LineCol) -> Result<Statement> { |
| 1252 | let token_span = self.lexer.read()?; |
| 1253 | let iterator = match token_span.token { |
| 1254 | Token::Symbol(iterator) => match iterator.ref_type { |
| 1255 | None | Some(ExprType::Double) | Some(ExprType::Integer) => iterator, |
| 1256 | _ => { |
| 1257 | return Err(Error::Bad( |
| 1258 | token_span.pos, |
| 1259 | "Iterator name in FOR statement must be a numeric reference".to_owned(), |
| 1260 | )); |
| 1261 | } |
| 1262 | }, |
| 1263 | _ => { |
| 1264 | return Err(Error::Bad( |
| 1265 | token_span.pos, |
| 1266 | "No iterator name in FOR statement".to_owned(), |
| 1267 | )); |
| 1268 | } |
| 1269 | }; |
| 1270 | let iterator_pos = token_span.pos; |
| 1271 | |
| 1272 | self.expect_and_consume(Token::Equal, "No equal sign in FOR statement")?; |
| 1273 | let start = self.parse_required_expr("No start expression in FOR statement")?; |
| 1274 | |
| 1275 | let to_span = self.expect_and_consume(Token::To, "No TO in FOR statement")?; |
| 1276 | let end = self.parse_required_expr("No end expression in FOR statement")?; |
| 1277 | |
| 1278 | let (step, step_sign, iter_double) = self.parse_step(for_pos)?; |
| 1279 | let end_condition = match step_sign { |
| 1280 | Ordering::Greater => Expr::LessEqual(Box::from(BinaryOpSpan { |
| 1281 | lhs: Expr::Symbol(SymbolSpan { vref: iterator.clone(), pos: iterator_pos }), |
| 1282 | rhs: end, |
| 1283 | pos: to_span.pos, |
| 1284 | })), |
| 1285 | Ordering::Less => Expr::GreaterEqual(Box::from(BinaryOpSpan { |
| 1286 | lhs: Expr::Symbol(SymbolSpan { vref: iterator.clone(), pos: iterator_pos }), |
| 1287 | rhs: end, |
| 1288 | pos: to_span.pos, |
| 1289 | })), |
| 1290 | Ordering::Equal => { |
| 1291 | return Err(Error::Bad( |
| 1292 | step.start_pos(), |
| 1293 | "Infinite FOR loop; STEP cannot be 0".to_owned(), |
| 1294 | )); |
| 1295 | } |
| 1296 | }; |
| 1297 | |
| 1298 | let next_value = Expr::Add(Box::from(BinaryOpSpan { |
| 1299 | lhs: Expr::Symbol(SymbolSpan { vref: iterator.clone(), pos: iterator_pos }), |
| 1300 | rhs: step, |
| 1301 | pos: to_span.pos, |
| 1302 | })); |
| 1303 | |
| 1304 | self.expect_and_consume(Token::Eol, "Expecting newline after FOR")?; |
| 1305 | |
| 1306 | let stmts = self.parse_until(Token::Next)?; |
| 1307 | self.expect_and_consume_with_pos(Token::Next, for_pos, "FOR without NEXT")?; |
| 1308 |
no test coverage detected