| ... | @@ -583,6 +583,40 @@ static AstNode *ast_parse_asm_expr(ParseContext *pc, size_t *token_index, bool m | ... | @@ -583,6 +583,40 @@ static AstNode *ast_parse_asm_expr(ParseContext *pc, size_t *token_index, bool m |
| 583 | return node; | 583 | return node; |
| 584 | } | 584 | } |
| 585 | | 585 | |
| | 586 | /* |
| | 587 | GotoExpression = option("inline") "goto" Symbol |
| | 588 | */ |
| | 589 | static AstNode *ast_parse_goto_expr(ParseContext *pc, size_t *token_index, bool mandatory) { |
| | 590 | Token *first_token = &pc->tokens->at(*token_index); |
| | 591 | Token *goto_token; |
| | 592 | bool is_inline; |
| | 593 | if (first_token->id == TokenIdKeywordInline) { |
| | 594 | is_inline = true; |
| | 595 | goto_token = &pc->tokens->at(*token_index + 1); |
| | 596 | if (goto_token->id == TokenIdKeywordGoto) { |
| | 597 | *token_index += 2; |
| | 598 | } else if (mandatory) { |
| | 599 | ast_expect_token(pc, first_token, TokenIdKeywordGoto); |
| | 600 | } else { |
| | 601 | return nullptr; |
| | 602 | } |
| | 603 | } else if (first_token->id == TokenIdKeywordGoto) { |
| | 604 | goto_token = first_token; |
| | 605 | is_inline = false; |
| | 606 | *token_index += 1; |
| | 607 | } else if (mandatory) { |
| | 608 | ast_expect_token(pc, first_token, TokenIdKeywordGoto); |
| | 609 | } else { |
| | 610 | return nullptr; |
| | 611 | } |
| | 612 | |
| | 613 | AstNode *node = ast_create_node(pc, NodeTypeGoto, goto_token); |
| | 614 | |
| | 615 | Token *dest_symbol = ast_eat_token(pc, token_index, TokenIdSymbol); |
| | 616 | node->data.goto_expr.name = token_buf(dest_symbol); |
| | 617 | node->data.goto_expr.is_inline = is_inline; |
| | 618 | return node; |
| | 619 | } |
| 586 | /* | 620 | /* |
| 587 | PrimaryExpression = "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | FnProto | AsmExpression | ("error" "." "Symbol") | 621 | PrimaryExpression = "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | FnProto | AsmExpression | ("error" "." "Symbol") |
| 588 | KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "zeroes" | "error" | "type" | "this" | 622 | KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "zeroes" | "error" | "type" | "this" |
| ... | @@ -672,18 +706,12 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo | ... | @@ -672,18 +706,12 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo |
| 672 | AstNode *node = ast_create_node(pc, NodeTypeSymbol, token); | 706 | AstNode *node = ast_create_node(pc, NodeTypeSymbol, token); |
| 673 | node->data.symbol_expr.symbol = token_buf(token); | 707 | node->data.symbol_expr.symbol = token_buf(token); |
| 674 | return node; | 708 | return node; |
| 675 | } else if (token->id == TokenIdKeywordGoto) { | | |
| 676 | AstNode *node = ast_create_node(pc, NodeTypeGoto, token); | | |
| 677 | *token_index += 1; | | |
| 678 | | | |
| 679 | Token *dest_symbol = &pc->tokens->at(*token_index); | | |
| 680 | *token_index += 1; | | |
| 681 | ast_expect_token(pc, dest_symbol, TokenIdSymbol); | | |
| 682 | | | |
| 683 | node->data.goto_expr.name = token_buf(dest_symbol); | | |
| 684 | return node; | | |
| 685 | } | 709 | } |
| 686 | | 710 | |
| | 711 | AstNode *goto_node = ast_parse_goto_expr(pc, token_index, false); |
| | 712 | if (goto_node) |
| | 713 | return goto_node; |
| | 714 | |
| 687 | AstNode *grouped_expr_node = ast_parse_grouped_expr(pc, token_index, false); | 715 | AstNode *grouped_expr_node = ast_parse_grouped_expr(pc, token_index, false); |
| 688 | if (grouped_expr_node) { | 716 | if (grouped_expr_node) { |
| 689 | return grouped_expr_node; | 717 | return grouped_expr_node; |