#include #include #include #include #include // pac_copy_empty_rules_from_ast_to_grammar: Creates a grammar corresponding to the AST, // not copying the variants and their items, but just the rules and their names. void pac_copy_empty_rules_from_ast_to_grammar(pac_grammar_s *grammar, pac_ast_s *ast) { for(usz_t rule_index = 0; rule_index < grammar->num_rules; ++rule_index) { pac_ast_rule_s ast_rule = ast->rules[rule_index]; pac_rule_s *rule = &grammar->rules[rule_index]; usz_t len_rule_name = strlen(ast_rule.name); rule->name = pac_arena_alloc(&grammar->result_arena, len_rule_name + 1); pac_memory_copy(rule->name, ast_rule.name, len_rule_name); rule->name[len_rule_name] = 0x00; } } pac_set_e pac_convert_ast_set_to_grammar_set(pac_ast_set_e set) { switch(set) { case PAC_AST_SET_RUNE: return PAC_SET_RUNE; case PAC_AST_SET_WORD: return PAC_SET_WORD; case PAC_AST_SET_INTEGER: return PAC_SET_INTEGER; case PAC_AST_SET_FLOAT: return PAC_SET_FLOAT; } return PAC_SET_INVALID; } pac_rule_s * pac_find_rule(pac_grammar_s *grammar, char *name) { for(usz_t index = 0; index < grammar->num_rules; ++index) { if(!strcmp(grammar->rules[index].name, name)) return &grammar->rules[index]; } printf("Couldn't find refernced rule: %s\n", name); return NULL; } void pac_copy_single_variant(pac_grammar_s *grammar, pac_variant_s *variant, pac_ast_variant_s *ast_variant) { variant->num_items = ast_variant->num_items; variant->items = pac_arena_alloc(&grammar->result_arena, sizeof(pac_item_s) * variant->num_items); for(usz_t item_index = 0; item_index < variant->num_items; ++item_index) { pac_ast_item_s ast_item = ast_variant->items[item_index]; pac_item_s *item = &variant->items[item_index]; switch(ast_item.type) { case PAC_AST_ITEM_INVALID: { item->type = PAC_ITEM_INVALID; } break; case PAC_AST_ITEM_LITERAL: { item->type = PAC_ITEM_LITERAL; item->data.literal.length = ast_item.data.string_literal.length; item->data.literal.string = ast_item.data.string_literal.string; // TODO: Copy this into a grammar-owned arena! } break; case PAC_AST_ITEM_REFERENCE: { item->type = PAC_ITEM_REFERENCE; item->data.reference = pac_find_rule(grammar, ast_item.data.reference.name); } break; case PAC_AST_ITEM_SET: { item->type = PAC_ITEM_SET; item->data.set = pac_convert_ast_set_to_grammar_set(ast_item.data.set); } break; } } } void pac_copy_variants_and_link_references(pac_grammar_s *grammar, pac_ast_s *ast) { grammar->num_rules = ast->num_rules; for(usz_t rule_index = 0; rule_index < ast->num_rules; ++rule_index) { pac_ast_rule_s ast_rule = ast->rules[rule_index]; pac_rule_s *rule = &grammar->rules[rule_index]; rule->num_variants = ast_rule.num_variants; rule->variants = pac_arena_alloc(&grammar->result_arena, sizeof(pac_variant_s) * rule->num_variants); for(usz_t variant_index = 0; variant_index < rule->num_variants; ++variant_index) { pac_copy_single_variant(grammar, &rule->variants[variant_index], &ast_rule.variants[variant_index]); } } } void pac_link_grammar(pac_grammar_s *grammar, pac_ast_s ast) { grammar->num_rules = ast.num_rules; grammar->rules = pac_arena_alloc(&grammar->result_arena, sizeof(pac_rule_s) * ast.num_rules); pac_copy_empty_rules_from_ast_to_grammar(grammar, &ast); pac_copy_variants_and_link_references(grammar, &ast); }