| 68 | // ── Module / module fields ──────────────────────────────────────────────────── |
| 69 | |
| 70 | void ParseContext::parse_module() { |
| 71 | if (tok_.at_eof()) return; |
| 72 | |
| 73 | // Either '(' 'module' Id? modulefield* ')' or plain modulefield* |
| 74 | if (tok_.peek().type == TokenType::LParen) { |
| 75 | // peek ahead to see if it's (module ...) or () empty module |
| 76 | const Token& peek2 = tok_.peek2(); |
| 77 | if (peek2.type == TokenType::Keyword && peek2.text == "module") { |
| 78 | tok_.consume(); // '(' |
| 79 | tok_.consume(); // 'module' |
| 80 | // optional Id |
| 81 | if (tok_.peek().type == TokenType::Id) tok_.consume(); |
| 82 | // modulefields until ')' |
| 83 | while (!tok_.at_eof() && tok_.peek().type != TokenType::RParen) |
| 84 | parse_modulefield(); |
| 85 | tok_.expect(TokenType::RParen, ")"); |
| 86 | return; |
| 87 | } |
| 88 | // '()' is treated as empty module |
| 89 | if (peek2.type == TokenType::RParen) { |
| 90 | tok_.consume(); // '(' |
| 91 | tok_.consume(); // ')' |
| 92 | return; |
| 93 | } |
| 94 | } |
| 95 | // plain modulefield* |
| 96 | while (!tok_.at_eof()) |
| 97 | parse_modulefield(); |
| 98 | } |
| 99 | |
| 100 | void ParseContext::parse_modulefield() { |
| 101 | // Each modulefield is '(' keyword ... ')'. |