| 398 | } |
| 399 | |
| 400 | auto parse_program(const std::span<const std::string> lines) -> std::expected<as::parser::Program, std::vector<sim::Error>> { |
| 401 | auto program = as::parser::Program{}; |
| 402 | auto errors = std::vector<sim::Error>{}; |
| 403 | |
| 404 | std::optional<std::uint32_t> block_count{}; |
| 405 | std::optional<std::uint32_t> warp_count{}; |
| 406 | |
| 407 | auto line_nr = 0u; |
| 408 | auto instr_count = 0u; |
| 409 | |
| 410 | auto add_label = [&](const std::string_view label_name) { |
| 411 | if (program.label_mappings.contains(label_name)) { |
| 412 | auto previous_declaration_line = program.label_mappings[label_name]; |
| 413 | errors.emplace_back(std::format("Duplicate label declaration on line {}", line_nr), 0, line_nr); |
| 414 | } else { |
| 415 | program.label_mappings[label_name] = instr_count; |
| 416 | } |
| 417 | }; |
| 418 | |
| 419 | |
| 420 | for(const auto& line : lines) { |
| 421 | line_nr++; |
| 422 | |
| 423 | // Tokenize |
| 424 | auto [tokens, lexer_errors] = as::collect_tokens(line); |
| 425 | if (!lexer_errors.empty()) { |
| 426 | for (auto error : lexer_errors) { |
| 427 | errors.push_back(error.with_line(line_nr)); |
| 428 | } |
| 429 | } |
| 430 | |
| 431 | // Skip empty lines |
| 432 | if (tokens.empty()) { |
| 433 | continue; |
| 434 | } |
| 435 | |
| 436 | const auto output = as::parse_line(tokens); |
| 437 | if(!output.has_value()) { |
| 438 | for (auto err : output.error()) { |
| 439 | errors.push_back(err.with_line(line_nr)); |
| 440 | } |
| 441 | continue; |
| 442 | } |
| 443 | |
| 444 | const auto& val = output.value(); |
| 445 | std::visit(as::overloaded{ |
| 446 | [&](const as::parser::JustLabel& label) { |
| 447 | add_label(label.label.name); |
| 448 | }, |
| 449 | [&](const as::parser::Instruction& instr) { |
| 450 | program.instructions.push_back(instr); |
| 451 | if (instr.label.has_value()) { |
| 452 | add_label(instr.label->name); |
| 453 | } |
| 454 | instr_count++; |
| 455 | }, |
| 456 | [&](const as::parser::BlocksDirective& block) { |
| 457 | if(block_count.has_value()) { |
no test coverage detected