| 662 | } |
| 663 | |
| 664 | bool llama_grammar_parser::parse(const char * src) { |
| 665 | try { |
| 666 | const char * pos = parse_space(src, true); |
| 667 | while (*pos) { |
| 668 | pos = parse_rule(pos); |
| 669 | } |
| 670 | // Validate the state to ensure that all rules are defined |
| 671 | for (const auto & rule : rules) { |
| 672 | if (rule.empty()) { |
| 673 | throw std::runtime_error("Undefined rule"); |
| 674 | } |
| 675 | for (const auto & elem : rule) { |
| 676 | if (elem.type == LLAMA_GRETYPE_RULE_REF) { |
| 677 | // Ensure that the rule at that location exists |
| 678 | if (elem.value >= rules.size() || rules[elem.value].empty()) { |
| 679 | // Get the name of the rule that is missing |
| 680 | for (const auto & kv : symbol_ids) { |
| 681 | if (kv.second == elem.value) { |
| 682 | throw std::runtime_error("Undefined rule identifier '" + kv.first + "'"); |
| 683 | } |
| 684 | } |
| 685 | } |
| 686 | } |
| 687 | } |
| 688 | } |
| 689 | } catch (const std::exception & err) { |
| 690 | fprintf(stderr, "%s: error parsing grammar: %s\n\n%s\n", __func__, err.what(), src); |
| 691 | rules.clear(); |
| 692 | return false; |
| 693 | } |
| 694 | |
| 695 | return true; |
| 696 | } |
| 697 | |
| 698 | void llama_grammar_parser::print(FILE * file) { |
| 699 | try { |
nothing calls this directly
no test coverage detected