(&mut self)
| 92 | type_names: std::collections::HashSet::new(), |
| 93 | enum_names: prelude_enum_names(), |
| 94 | synthesized_declarations: Vec::new(), |
| 95 | next_lambda_id: 0, |
| 96 | } |
| 97 | } |
| 98 | |
| 99 | pub fn parse_program(&mut self) -> Result<Program, ParserError> { |
| 100 | let mut declarations = Vec::new(); |
| 101 | let mut statements = Vec::new(); |
| 102 | |
| 103 | self.consume_terminators(); |
| 104 | while !self.is_eof() { |
| 105 | if matches!(self.peek(), Some(Token::Impl)) { |
| 106 | // `impl Type { ... }` desugars in place to flat `Type_method` |
| 107 | // functions, so no later stage needs to know about methods. |
| 108 | declarations.extend(self.parse_impl_block(false)?); |
| 109 | } else if matches!(self.peek(), Some(Token::Export)) |
| 110 | && matches!(self.peek_n(1), Some(Token::Impl)) |
| 111 | { |
| 112 | self.advance(); |
| 113 | declarations.extend(self.parse_impl_block(true)?); |
| 114 | } else if self.is_declaration_start() { |
| 115 | declarations.push(self.parse_declaration()?); |
| 116 | } else { |
| 117 | statements.push(self.parse_statement()?); |
| 118 | } |
| 119 | self.consume_terminators(); |
| 120 | } |
| 121 | |
| 122 | declarations.append(&mut self.synthesized_declarations); |
| 123 | Ok(Program { |
| 124 | declarations, |
| 125 | statements, |
| 126 | }) |
| 127 | } |
| 128 | |
| 129 | fn parse_declaration(&mut self) -> Result<Declaration, ParserError> { |
| 130 | self.consume_terminators(); |
| 131 | |
| 132 | // `export` marks the following declaration visible to importers. Record the |
| 133 | // flag and parse the underlying declaration; it is otherwise unchanged. |
| 134 | let exported = if matches!(self.peek(), Some(Token::Export)) { |
| 135 | self.advance(); |
| 136 | self.consume_terminators(); |
| 137 | true |
| 138 | } else { |
| 139 | false |
| 140 | }; |
| 141 | |
| 142 | let decl = match self.peek() { |
| 143 | Some(Token::Const) => { |
| 144 | self.advance(); |
| 145 | let name = self.expect_ident()?; |
| 146 | self.expect_assign()?; |
| 147 | if matches!(self.peek(), Some(Token::Import)) { |
| 148 | let path = self.parse_import_call()?; |
| 149 | DeclNode::ModuleImport { alias: name, path } |
| 150 | } else { |
| 151 | let init = self.parse_expression()?; |
no test coverage detected