(&mut self)
| 598 | } |
| 599 | |
| 600 | fn parse_model(&mut self) -> Result<Model> { |
| 601 | let pos = self.pos(); |
| 602 | let name = self.parse_ident()?; |
| 603 | self.expect_lparen()?; // body |
| 604 | let val = if self.eat_sym_str("type")? { |
| 605 | let ty = self.parse_model_type(); |
| 606 | ModelValue::TypeValue(ty?) |
| 607 | } else if self.eat_sym_str("enum")? { |
| 608 | let mut variants = vec![]; |
| 609 | let mut has_explicit_value = false; |
| 610 | let mut implicit_idx = None; |
| 611 | |
| 612 | while !self.is_rparen() { |
| 613 | self.expect_lparen()?; // enum value |
| 614 | let name = self.parse_ident()?; |
| 615 | let val = if self.is_rparen() { |
| 616 | // has implicit enum value |
| 617 | if has_explicit_value { |
| 618 | return Err(self.error( |
| 619 | pos, |
| 620 | format!( |
| 621 | "Spec enum has unexpected implicit value after implicit value." |
| 622 | ), |
| 623 | )); |
| 624 | } |
| 625 | implicit_idx = Some(if let Some(idx) = implicit_idx { |
| 626 | idx + 1 |
| 627 | } else { |
| 628 | 0 |
| 629 | }); |
| 630 | SpecExpr::ConstInt { |
| 631 | val: implicit_idx.unwrap(), |
| 632 | pos, |
| 633 | } |
| 634 | } else { |
| 635 | if implicit_idx.is_some() { |
| 636 | return Err(self.error( |
| 637 | pos, |
| 638 | format!( |
| 639 | "Spec enum has unexpected explicit value after implicit value." |
| 640 | ), |
| 641 | )); |
| 642 | } |
| 643 | has_explicit_value = true; |
| 644 | self.parse_spec_expr()? |
| 645 | }; |
| 646 | self.expect_rparen()?; |
| 647 | variants.push((name, val)); |
| 648 | } |
| 649 | ModelValue::EnumValues(variants) |
| 650 | } else { |
| 651 | return Err(self.error(pos, "Model must be a type or enum".to_string())); |
| 652 | }; |
| 653 | |
| 654 | self.expect_rparen()?; // end body |
| 655 | Ok(Model { name, val }) |
| 656 | } |
| 657 |
no test coverage detected