| 216 | }; |
| 217 | |
| 218 | class Parser { |
| 219 | public: |
| 220 | explicit Parser(Lexer& lexer) : lexer_(lexer), token_(lexer.next()) {} |
| 221 | |
| 222 | File parse() { |
| 223 | File file; |
| 224 | while (token_.kind != Tok::End) { |
| 225 | const Token kind = expect(Tok::Ident, "declaration"); |
| 226 | if (kind.text == "enum") { |
| 227 | file.enums.push_back(parseEnum()); |
| 228 | } else if (kind.text == "struct") { |
| 229 | file.structs.push_back(parseStruct()); |
| 230 | } else if (kind.text == "protocol") { |
| 231 | file.protocols.push_back(parseProtocol()); |
| 232 | } else if (kind.text == "interface") { |
| 233 | file.interfaces.push_back(parseInterface()); |
| 234 | } else { |
| 235 | fail(kind.line, "unknown declaration '" + kind.text + "'"); |
| 236 | } |
| 237 | } |
| 238 | validate(file); |
| 239 | return file; |
| 240 | } |
| 241 | |
| 242 | private: |
| 243 | EnumDecl parseEnum() { |
| 244 | EnumDecl decl; |
| 245 | decl.line = token_.line; |
| 246 | decl.name = expect(Tok::Ident, "enum name").text; |
| 247 | expect(Tok::Colon); |
| 248 | decl.underlying = expect(Tok::Ident, "enum underlying type").text; |
| 249 | expect(Tok::LBrace); |
| 250 | std::unordered_set<std::string> names; |
| 251 | while (token_.kind != Tok::RBrace) { |
| 252 | EnumMember member; |
| 253 | member.line = token_.line; |
| 254 | member.name = expect(Tok::Ident, "enum member").text; |
| 255 | ensureUnique(names, member.name, "enum member", member.line); |
| 256 | expect(Tok::Equal); |
| 257 | member.value = expect(Tok::Int, "enum value").text; |
| 258 | expect(Tok::Semi); |
| 259 | decl.members.push_back(std::move(member)); |
| 260 | } |
| 261 | expect(Tok::RBrace); |
| 262 | optionalSemi(); |
| 263 | return decl; |
| 264 | } |
| 265 | |
| 266 | StructDecl parseStruct() { |
| 267 | StructDecl decl; |
| 268 | decl.line = token_.line; |
| 269 | decl.name = expect(Tok::Ident, "struct name").text; |
| 270 | expect(Tok::LBrace); |
| 271 | std::unordered_set<std::string> names; |
| 272 | while (token_.kind != Tok::RBrace) { |
| 273 | Field field = parseField(false); |
| 274 | ensureUnique(names, field.name, "struct field", field.line); |
| 275 | expect(Tok::Semi); |
nothing calls this directly
no outgoing calls
no test coverage detected