| ... | ... | @@ -187,29 +187,39 @@ struct RuleNode { |
| 187 | 187 | }; |
| 188 | 188 | |
| 189 | 189 | |
| 190 | | enum ParserStateType { |
| 191 | | ParserStateTypeError, |
| 192 | | ParserStateTypeOk, |
| 193 | | ParserStateTypeCapture, |
| 190 | enum CodeGenType { |
| 191 | CodeGenTypeTransition, |
| 192 | CodeGenTypeError, |
| 193 | CodeGenTypeSave, |
| 194 | CodeGenTypePushNode, |
| 195 | CodeGenTypeCapture, |
| 196 | CodeGenTypePopNode, |
| 197 | CodeGenTypeEatToken, |
| 194 | 198 | }; |
| 195 | 199 | |
| 196 | | struct ParserStateError { |
| 200 | struct CodeGenError { |
| 197 | 201 | Buf *msg; |
| 198 | 202 | }; |
| 199 | 203 | |
| 200 | | struct ParserStateCapture { |
| 204 | struct CodeGenCapture { |
| 201 | 205 | Buf *body; |
| 206 | bool is_root; |
| 207 | Buf *field_names; |
| 208 | }; |
| 209 | |
| 210 | struct CodeGen { |
| 211 | CodeGenType type; |
| 212 | union { |
| 213 | CodeGenError error; |
| 214 | CodeGenCapture capture; |
| 215 | }; |
| 202 | 216 | }; |
| 203 | 217 | |
| 204 | 218 | struct ParserState { |
| 205 | | ParserStateType type; |
| 219 | ZigList<CodeGen *> code_gen_list; |
| 206 | 220 | // One for each token ID. |
| 207 | 221 | ParserState **transition; |
| 208 | 222 | int index; |
| 209 | | union { |
| 210 | | ParserStateError error; |
| 211 | | ParserStateCapture capture; |
| 212 | | }; |
| 213 | 223 | }; |
| 214 | 224 | |
| 215 | 225 | enum LexState { |
| ... | ... | @@ -234,6 +244,7 @@ struct Gen { |
| 234 | 244 | ZigList<ParserState *> transition_table; |
| 235 | 245 | ZigList<Token *> tokens; |
| 236 | 246 | RuleNode *root; |
| 247 | int biggest_tuple_len; |
| 237 | 248 | |
| 238 | 249 | Buf *in_buf; |
| 239 | 250 | LexState lex_state; |
| ... | ... | @@ -249,9 +260,8 @@ struct Gen { |
| 249 | 260 | int lex_body_end; |
| 250 | 261 | }; |
| 251 | 262 | |
| 252 | | static ParserState *create_state(Gen *g, ParserStateType type) { |
| 263 | static ParserState *create_state(Gen *g) { |
| 253 | 264 | ParserState *state = allocate<ParserState>(1); |
| 254 | | state->type = type; |
| 255 | 265 | state->index = g->transition_table.length; |
| 256 | 266 | state->transition = allocate<ParserState*>(g->tokens.length); |
| 257 | 267 | g->transition_table.append(state); |
| ... | ... | @@ -264,28 +274,93 @@ static void fill_state_with_transition(Gen *g, ParserState *source, ParserState |
| 264 | 274 | } |
| 265 | 275 | } |
| 266 | 276 | |
| 267 | | static void gen(Gen *g, RuleNode *node) { |
| 277 | static void state_add_code(ParserState *state, CodeGen *code) { |
| 278 | state->code_gen_list.append(code); |
| 279 | } |
| 280 | |
| 281 | static void state_add_save_token(ParserState *state) { |
| 282 | CodeGen *code = allocate<CodeGen>(1); |
| 283 | code->type = CodeGenTypeSave; |
| 284 | state_add_code(state, code); |
| 285 | } |
| 286 | |
| 287 | static void state_add_error(ParserState *state, Buf *msg) { |
| 288 | CodeGen *code = allocate<CodeGen>(1); |
| 289 | code->type = CodeGenTypeError; |
| 290 | code->error.msg = msg; |
| 291 | state_add_code(state, code); |
| 292 | } |
| 293 | |
| 294 | static void state_add_transition(ParserState *state) { |
| 295 | CodeGen *code = allocate<CodeGen>(1); |
| 296 | code->type = CodeGenTypeTransition; |
| 297 | state_add_code(state, code); |
| 298 | } |
| 299 | |
| 300 | static void state_add_push_node(ParserState *state) { |
| 301 | CodeGen *code = allocate<CodeGen>(1); |
| 302 | code->type = CodeGenTypePushNode; |
| 303 | state_add_code(state, code); |
| 304 | } |
| 305 | |
| 306 | static CodeGen *codegen_create_capture(Buf *body, bool is_root, int field_name_count) { |
| 307 | CodeGen *code = allocate<CodeGen>(1); |
| 308 | code->type = CodeGenTypeCapture; |
| 309 | code->capture.body = body; |
| 310 | code->capture.is_root = is_root; |
| 311 | code->capture.field_names = allocate<Buf>(field_name_count); |
| 312 | return code; |
| 313 | } |
| 314 | |
| 315 | static void state_add_pop_node(ParserState *state) { |
| 316 | CodeGen *code = allocate<CodeGen>(1); |
| 317 | code->type = CodeGenTypePopNode; |
| 318 | state_add_code(state, code); |
| 319 | } |
| 320 | |
| 321 | static void state_add_eat_token(ParserState *state) { |
| 322 | CodeGen *code = allocate<CodeGen>(1); |
| 323 | code->type = CodeGenTypeEatToken; |
| 324 | state_add_code(state, code); |
| 325 | } |
| 326 | |
| 327 | static void gen(Gen *g, RuleNode *node, Buf *out_field_name) { |
| 268 | 328 | switch (node->type) { |
| 269 | 329 | case RuleNodeTypeToken: |
| 270 | 330 | { |
| 271 | | ParserState *ok_state = create_state(g, ParserStateTypeOk); |
| 272 | | ParserState *err_state = create_state(g, ParserStateTypeError); |
| 331 | buf_init_from_str(out_field_name, "token"); |
| 332 | |
| 333 | state_add_save_token(g->cur_state); |
| 273 | 334 | |
| 274 | | err_state->error.msg = buf_sprintf("expected token '%s'", buf_ptr(&node->token.token->name)); |
| 335 | ParserState *ok_state = create_state(g); |
| 336 | ParserState *err_state = create_state(g); |
| 337 | state_add_error(err_state, buf_sprintf("expected token '%s'", buf_ptr(&node->token.token->name))); |
| 275 | 338 | |
| 276 | 339 | fill_state_with_transition(g, g->cur_state, err_state); |
| 277 | 340 | g->cur_state->transition[node->token.token->id] = ok_state; |
| 341 | state_add_transition(g->cur_state); |
| 342 | state_add_eat_token(g->cur_state); |
| 343 | |
| 278 | 344 | g->cur_state = ok_state; |
| 279 | 345 | } |
| 280 | 346 | break; |
| 281 | 347 | case RuleNodeTypeTuple: |
| 282 | 348 | { |
| 349 | buf_init_from_str(out_field_name, "node"); |
| 350 | |
| 351 | state_add_push_node(g->cur_state); |
| 352 | |
| 353 | bool is_root = (node == g->root); |
| 354 | int field_name_count = node->tuple.children.length; |
| 355 | CodeGen *code = codegen_create_capture(&node->tuple.body, is_root, field_name_count); |
| 356 | |
| 283 | 357 | for (int i = 0; i < node->tuple.children.length; i += 1) { |
| 284 | 358 | RuleNode *child = node->tuple.children.at(i); |
| 285 | | gen(g, child); |
| 359 | gen(g, child, &code->capture.field_names[i]); |
| 286 | 360 | } |
| 287 | | g->cur_state->type = ParserStateTypeCapture; |
| 288 | | g->cur_state->capture.body = &node->tuple.body; |
| 361 | state_add_code(g->cur_state, code); |
| 362 | |
| 363 | state_add_pop_node(g->cur_state); |
| 289 | 364 | } |
| 290 | 365 | break; |
| 291 | 366 | case RuleNodeTypeMany: |
| ... | ... | @@ -301,7 +376,10 @@ static void gen(Gen *g, RuleNode *node) { |
| 301 | 376 | zig_panic("TODO"); |
| 302 | 377 | break; |
| 303 | 378 | case RuleNodeTypeSubRule: |
| 304 | | zig_panic("TODO"); |
| 379 | { |
| 380 | RuleNode *child = node->sub_rule.child; |
| 381 | gen(g, child, out_field_name); |
| 382 | } |
| 305 | 383 | break; |
| 306 | 384 | } |
| 307 | 385 | } |
| ... | ... | @@ -407,6 +485,9 @@ static void end_token_name(Gen *g) { |
| 407 | 485 | assert(g->lex_cur_rule->type == RuleNodeTypeTuple); |
| 408 | 486 | g->lex_cur_rule->tuple.children.append(node); |
| 409 | 487 | |
| 488 | g->biggest_tuple_len = max(g->biggest_tuple_len, g->lex_cur_rule->tuple.children.length); |
| 489 | |
| 490 | |
| 410 | 491 | lex_pop_stack(g); |
| 411 | 492 | } |
| 412 | 493 | |
| ... | ... | @@ -571,6 +652,76 @@ static void initialize_rules(Gen *g) { |
| 571 | 652 | } |
| 572 | 653 | } |
| 573 | 654 | |
| 655 | enum TemplateState { |
| 656 | TemplateStateStart, |
| 657 | TemplateStateDollar, |
| 658 | TemplateStateNumber, |
| 659 | }; |
| 660 | |
| 661 | static Buf *fill_template(Buf *body, const char *result_name, Buf *field_names) { |
| 662 | //fprintf(stderr, "fill template input:\n%s\n", buf_ptr(body)); |
| 663 | Buf *result = buf_alloc(); |
| 664 | TemplateState state = TemplateStateStart; |
| 665 | int digit_start; |
| 666 | for (int i = 0; i < buf_len(body); i += 1) { |
| 667 | uint8_t c = buf_ptr(body)[i]; |
| 668 | switch (state) { |
| 669 | case TemplateStateStart: |
| 670 | switch (c) { |
| 671 | case '$': |
| 672 | state = TemplateStateDollar; |
| 673 | break; |
| 674 | default: |
| 675 | buf_append_char(result, c); |
| 676 | break; |
| 677 | } |
| 678 | break; |
| 679 | case TemplateStateDollar: |
| 680 | switch (c) { |
| 681 | case '$': |
| 682 | buf_append_str(result, result_name); |
| 683 | state = TemplateStateStart; |
| 684 | break; |
| 685 | case DIGIT: |
| 686 | digit_start = i; |
| 687 | state = TemplateStateNumber; |
| 688 | break; |
| 689 | default: |
| 690 | buf_append_char(result, '$'); |
| 691 | buf_append_char(result, c); |
| 692 | state = TemplateStateStart; |
| 693 | break; |
| 694 | } |
| 695 | break; |
| 696 | case TemplateStateNumber: |
| 697 | switch (c) { |
| 698 | case DIGIT: |
| 699 | // nothing |
| 700 | break; |
| 701 | default: |
| 702 | { |
| 703 | Buf *num_buf = buf_create_from_mem(&buf_ptr(body)[digit_start], i - digit_start); |
| 704 | int index = atoi(buf_ptr(num_buf)) - 1; |
| 705 | buf_appendf(result, "(top_node->data[%d].%s)%c", |
| 706 | index, buf_ptr(&field_names[index]), c); |
| 707 | |
| 708 | state = TemplateStateStart; |
| 709 | } |
| 710 | break; |
| 711 | } |
| 712 | break; |
| 713 | } |
| 714 | } |
| 715 | switch (state) { |
| 716 | case TemplateStateStart: |
| 717 | // OK |
| 718 | break; |
| 719 | default: |
| 720 | zig_panic("unable to fill grammar template"); |
| 721 | } |
| 722 | //fprintf(stderr, "fill template output:\n%s\n", buf_ptr(result)); |
| 723 | return result; |
| 724 | } |
| 574 | 725 | |
| 575 | 726 | int main(int argc, char **argv) { |
| 576 | 727 | const char *in_filename = argv[1]; |
| ... | ... | @@ -603,8 +754,9 @@ int main(int argc, char **argv) { |
| 603 | 754 | |
| 604 | 755 | g.root = g.rules.at(0); |
| 605 | 756 | |
| 606 | | g.cur_state = create_state(&g, ParserStateTypeOk); |
| 607 | | gen(&g, g.root); |
| 757 | g.cur_state = create_state(&g); |
| 758 | Buf root_field_name = {0}; |
| 759 | gen(&g, g.root, &root_field_name); |
| 608 | 760 | |
| 609 | 761 | fprintf(out_f, "/* This file is generated by parsergen.cpp */\n"); |
| 610 | 762 | fprintf(out_f, "\n"); |
| ... | ... | @@ -627,15 +779,14 @@ int main(int argc, char **argv) { |
| 627 | 779 | } |
| 628 | 780 | fprintf(out_f, "\n"); |
| 629 | 781 | |
| 630 | | /* TODO |
| 631 | | fprintf(out_f, "struct ParserGenNode{\n"); |
| 782 | fprintf(out_f, "struct ParserGenNode {\n"); |
| 783 | fprintf(out_f, " int next_index;\n"); |
| 632 | 784 | fprintf(out_f, " union {\n"); |
| 633 | | fprintf(out_f, " [%d];\n", biggest_tuple_len); |
| 634 | 785 | fprintf(out_f, " Token *token;\n"); |
| 635 | | fprintf(out_f, " };\n"); |
| 786 | fprintf(out_f, " AstNode *node;\n"); |
| 787 | fprintf(out_f, " } data[%d];\n", g.biggest_tuple_len); |
| 636 | 788 | fprintf(out_f, "};\n"); |
| 637 | 789 | fprintf(out_f, "\n"); |
| 638 | | */ |
| 639 | 790 | |
| 640 | 791 | fprintf(out_f, "AstNode * ast_parse(Buf *buf, ZigList<Token> *tokens) {\n"); |
| 641 | 792 | |
| ... | ... | @@ -655,39 +806,66 @@ int main(int argc, char **argv) { |
| 655 | 806 | |
| 656 | 807 | |
| 657 | 808 | fprintf(out_f, " int state = 0;\n"); |
| 809 | fprintf(out_f, " int token_index = 0;\n"); |
| 810 | fprintf(out_f, " Token *token = &tokens->at(token_index);\n"); |
| 658 | 811 | fprintf(out_f, " AstNode *root = nullptr;\n"); |
| 812 | fprintf(out_f, " ZigList<ParserGenNode *> stack = {0};\n"); |
| 813 | fprintf(out_f, " ParserGenNode *top_node = nullptr;\n"); |
| 659 | 814 | |
| 660 | | fprintf(out_f, " for (int i = 0; i < tokens->length; i += 1) {\n"); |
| 661 | | fprintf(out_f, " Token *token = &tokens->at(i);\n"); |
| 815 | fprintf(out_f, " for (;;) {\n"); |
| 662 | 816 | fprintf(out_f, " switch (state) {\n"); |
| 663 | 817 | |
| 664 | | for (int i = 0; i < g.transition_table.length; i += 1) { |
| 665 | | ParserState *state = g.transition_table.at(i); |
| 666 | | fprintf(out_f, " case %d:\n", i); |
| 667 | | switch (state->type) { |
| 668 | | case ParserStateTypeError: |
| 669 | | fprintf(out_f, " ast_error(token, \"%s\");\n", buf_ptr(state->error.msg)); |
| 670 | | break; |
| 671 | | case ParserStateTypeOk: |
| 672 | | fprintf(out_f, " assert(transition[%d][token->id] >= 0);\n", state->index); |
| 673 | | fprintf(out_f, " assert(transition[%d][token->id] < %d);\n", |
| 674 | | state->index, g.transition_table.length); |
| 675 | | fprintf(out_f, " state = transition[%d][token->id];\n", state->index); |
| 676 | | break; |
| 677 | | case ParserStateTypeCapture: |
| 678 | | // TODO fprintf(out_f, " %s\n", buf_ptr(state->capture.body)); |
| 679 | | fprintf(out_f, " state = transition[%d][token->id];\n", state->index); |
| 680 | | break; |
| 818 | for (int state_i = 0; state_i < g.transition_table.length; state_i += 1) { |
| 819 | ParserState *state = g.transition_table.at(state_i); |
| 820 | fprintf(out_f, " case %d: {\n", state_i); |
| 821 | for (int code_i = 0; code_i < state->code_gen_list.length; code_i += 1) { |
| 822 | CodeGen *code = state->code_gen_list.at(code_i); |
| 823 | switch (code->type) { |
| 824 | case CodeGenTypeTransition: |
| 825 | fprintf(out_f, " assert(transition[%d][token->id] >= 0);\n", state->index); |
| 826 | fprintf(out_f, " assert(transition[%d][token->id] < %d);\n", |
| 827 | state->index, g.transition_table.length); |
| 828 | fprintf(out_f, " state = transition[%d][token->id];\n", state->index); |
| 829 | break; |
| 830 | case CodeGenTypeError: |
| 831 | fprintf(out_f, " ast_error(token, \"%s\");\n", buf_ptr(code->error.msg)); |
| 832 | break; |
| 833 | case CodeGenTypeSave: |
| 834 | fprintf(out_f, " top_node->data[top_node->next_index++].token = token;\n"); |
| 835 | break; |
| 836 | case CodeGenTypePushNode: |
| 837 | fprintf(out_f, " top_node = allocate<ParserGenNode>(1);\n"); |
| 838 | fprintf(out_f, " stack.append(top_node);\n"); |
| 839 | break; |
| 840 | case CodeGenTypeCapture: |
| 841 | if (code->capture.is_root) { |
| 842 | Buf *code_text = fill_template(code->capture.body, "root", code->capture.field_names); |
| 843 | fprintf(out_f, "%s\n", buf_ptr(code_text)); |
| 844 | fprintf(out_f, " return root;\n"); |
| 845 | } else { |
| 846 | zig_panic("TODO capture non-root"); |
| 847 | } |
| 848 | break; |
| 849 | case CodeGenTypePopNode: |
| 850 | fprintf(out_f, " stack.pop();\n"); |
| 851 | fprintf(out_f, " top_node = stack.length ? stack.last() : nullptr;\n"); |
| 852 | break; |
| 853 | case CodeGenTypeEatToken: |
| 854 | fprintf(out_f, " token_index += 1;\n"); |
| 855 | fprintf(out_f, " token = (token_index < tokens->length) ? &tokens->at(token_index) : nullptr;\n"); |
| 856 | break; |
| 857 | } |
| 681 | 858 | } |
| 682 | 859 | fprintf(out_f, " break;\n"); |
| 860 | fprintf(out_f, " }\n"); |
| 683 | 861 | } |
| 684 | 862 | fprintf(out_f, " default:\n"); |
| 685 | 863 | fprintf(out_f, " zig_panic(\"unreachable\");\n"); |
| 686 | 864 | |
| 687 | 865 | fprintf(out_f, " }\n"); |
| 688 | 866 | fprintf(out_f, " }\n"); |
| 689 | | fprintf(out_f, " return root;\n"); |
| 867 | fprintf(out_f, " zig_panic(\"unreachable\");\n"); |
| 690 | 868 | fprintf(out_f, "}\n"); |
| 691 | 869 | |
| 692 | | |
| 870 | return 0; |
| 693 | 871 | } |