Parses a `DIM` statement.
(&mut self)
| 553 | |
| 554 | /// Parses a `DIM` statement. |
| 555 | fn parse_dim(&mut self) -> Result<Statement> { |
| 556 | let peeked = self.lexer.peek()?; |
| 557 | let mut shared = false; |
| 558 | if peeked.token == Token::Shared { |
| 559 | self.lexer.consume_peeked(); |
| 560 | shared = true; |
| 561 | } |
| 562 | |
| 563 | let token_span = self.lexer.read()?; |
| 564 | let vref = match token_span.token { |
| 565 | Token::Symbol(vref) => vref, |
| 566 | _ => { |
| 567 | return Err(Error::Bad( |
| 568 | token_span.pos, |
| 569 | "Expected variable name after DIM".to_owned(), |
| 570 | )); |
| 571 | } |
| 572 | }; |
| 573 | // TODO(jmmv): Why do we require unannotated strings? We could also take one and then |
| 574 | // skip the `AS <type>` portion. |
| 575 | let name = vref_to_unannotated_string(vref, token_span.pos)?; |
| 576 | let name_pos = token_span.pos; |
| 577 | |
| 578 | match self.lexer.peek()?.token { |
| 579 | Token::LeftParen => { |
| 580 | let peeked = self.lexer.consume_peeked(); |
| 581 | let dimensions = self.parse_comma_separated_exprs()?; |
| 582 | if dimensions.is_empty() { |
| 583 | return Err(Error::Bad( |
| 584 | peeked.pos, |
| 585 | "Arrays require at least one dimension".to_owned(), |
| 586 | )); |
| 587 | } |
| 588 | let (subtype, subtype_pos) = self.parse_dim_as()?; |
| 589 | Ok(Statement::DimArray(DimArraySpan { |
| 590 | name, |
| 591 | name_pos, |
| 592 | shared, |
| 593 | dimensions: argspans_to_exprs(dimensions), |
| 594 | subtype, |
| 595 | subtype_pos, |
| 596 | })) |
| 597 | } |
| 598 | _ => { |
| 599 | let (vtype, vtype_pos) = self.parse_dim_as()?; |
| 600 | Ok(Statement::Dim(DimSpan { name, name_pos, shared, vtype, vtype_pos })) |
| 601 | } |
| 602 | } |
| 603 | } |
| 604 | |
| 605 | /// Parses the `UNTIL` or `WHILE` clause of a `DO` loop. |
| 606 | /// |
no test coverage detected