diff options
Diffstat (limited to 'src/parser.cpp')
| -rw-r--r-- | src/parser.cpp | 173 |
1 files changed, 102 insertions, 71 deletions
diff --git a/src/parser.cpp b/src/parser.cpp index 478e1377a..8ba398020 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -77,6 +77,10 @@ enum CallExprKind { AST_NODE_KIND(Invalid, "invalid node", struct{}) \ AST_NODE_KIND(BasicLit, "basic literal", Token) \ AST_NODE_KIND(Ident, "identifier", Token) \ + AST_NODE_KIND(Ellipsis, "ellipsis", struct { \ + Token token; \ + AstNode *expr; \ + }) \ AST_NODE_KIND(ProcLit, "procedure literal", struct { \ AstNode *type; \ AstNode *body; \ @@ -110,7 +114,6 @@ AST_NODE_KIND(_ExprBegin, "", struct{}) \ b32 triple_indexed; \ }) \ AST_NODE_KIND(FieldValue, "field value", struct { Token eq; AstNode *field, *value; }) \ - AST_NODE_KIND(Ellipsis, "ellipsis", struct { Token token; }) \ AST_NODE_KIND(_ExprEnd, "", struct{}) \ AST_NODE_KIND(_StmtBegin, "", struct{}) \ AST_NODE_KIND(BadStmt, "bad statement", struct { Token begin, end; }) \ @@ -542,11 +545,6 @@ gb_inline AstNode *make_deref_expr(AstFile *f, AstNode *expr, Token op) { } -gb_inline AstNode *make_ellipsis(AstFile *f, Token token) { - AstNode *result = make_node(f, AstNode_Ellipsis); - result->Ellipsis.token = token; - return result; -} gb_inline AstNode *make_basic_lit(AstFile *f, Token basic_lit) { AstNode *result = make_node(f, AstNode_BasicLit); result->BasicLit = basic_lit; @@ -559,6 +557,14 @@ gb_inline AstNode *make_ident(AstFile *f, Token token) { return result; } +gb_inline AstNode *make_ellipsis(AstFile *f, Token token, AstNode *expr) { + AstNode *result = make_node(f, AstNode_Ellipsis); + result->Ellipsis.token = token; + result->Ellipsis.expr = expr; + return result; +} + + gb_inline AstNode *make_proc_lit(AstFile *f, AstNode *type, AstNode *body, u64 tags) { AstNode *result = make_node(f, AstNode_ProcLit); result->ProcLit.type = type; @@ -1253,6 +1259,37 @@ b32 is_literal_type(AstNode *node) { return false; } +AstNode *parse_call_expr(AstFile *f, AstNode *operand) { + AstNode *arg_list = NULL; + AstNode *arg_list_curr = NULL; + isize arg_list_count = 0; + Token open_paren, close_paren; + + f->expr_level++; + open_paren = expect_token(f, Token_OpenParen); + + while (f->cursor[0].kind != Token_CloseParen && + f->cursor[0].kind != Token_EOF) { + if (f->cursor[0].kind == Token_Comma) + ast_file_err(f, f->cursor[0], "Expected an expression not a ,"); + + DLIST_APPEND(arg_list, arg_list_curr, parse_expr(f, false)); + arg_list_count++; + + if (f->cursor[0].kind != Token_Comma) { + if (f->cursor[0].kind == Token_CloseParen) + break; + } + + next_token(f); + } + + f->expr_level--; + close_paren = expect_token(f, Token_CloseParen); + + return make_call_expr(f, operand, arg_list, arg_list_count, open_paren, close_paren); +} + AstNode *parse_atom_expr(AstFile *f, b32 lhs) { AstNode *operand = parse_operand(f, lhs); @@ -1273,34 +1310,7 @@ AstNode *parse_atom_expr(AstFile *f, b32 lhs) { if (lhs) { // TODO(bill): Handle this shit! Is this even allowed in this language?! } - AstNode *arg_list = NULL; - AstNode *arg_list_curr = NULL; - isize arg_list_count = 0; - Token open_paren, close_paren; - - f->expr_level++; - open_paren = expect_token(f, Token_OpenParen); - - while (f->cursor[0].kind != Token_CloseParen && - f->cursor[0].kind != Token_EOF) { - if (f->cursor[0].kind == Token_Comma) - ast_file_err(f, f->cursor[0], "Expected an expression not a ,"); - - DLIST_APPEND(arg_list, arg_list_curr, parse_expr(f, false)); - arg_list_count++; - - if (f->cursor[0].kind != Token_Comma) { - if (f->cursor[0].kind == Token_CloseParen) - break; - } - - next_token(f); - } - - f->expr_level--; - close_paren = expect_token(f, Token_CloseParen); - - operand = make_call_expr(f, operand, arg_list, arg_list_count, open_paren, close_paren); + operand = parse_call_expr(f, operand); } break; case Token_Period: { @@ -1617,64 +1627,81 @@ AstNode *parse_type(AstFile *f) { return type; } -AstNode *parse_field_decl(AstFile *f, b32 allow_using) { - b32 is_using = false; + +Token parse_procedure_signature(AstFile *f, + AstNode **param_list, isize *param_count, + AstNode **result_list, isize *result_count); + +AstNode *parse_proc_type(AstFile *f) { + AstNode *params = NULL; + AstNode *results = NULL; + isize param_count = 0; + isize result_count = 0; + + Token proc_token = parse_procedure_signature(f, ¶ms, ¶m_count, &results, &result_count); + + return make_proc_type(f, proc_token, params, param_count, results, result_count); +} + +AstNode *parse_field_decl(AstFile *f) { AstNode *name_list = NULL; isize name_count = 0; - if (allow_using) { - if (allow_token(f, Token_using)) { - is_using = true; - } + b32 is_using = false; + if (allow_token(f, Token_using)) { + is_using = true; } name_list = parse_lhs_expr_list(f, &name_count); - if (name_count == 0) + if (name_count == 0) { ast_file_err(f, f->cursor[0], "Empty field declaration"); + } if (name_count > 1 && is_using) { ast_file_err(f, f->cursor[0], "Cannot apply `using` to more than one of the same type"); + is_using = false; } expect_token(f, Token_Colon); - AstNode *type = parse_type_attempt(f); - if (type == NULL) + AstNode *type = NULL; + if (f->cursor[0].kind == Token_Ellipsis) { + Token ellipsis = f->cursor[0]; + next_token(f); + type = parse_type_attempt(f); + if (type == NULL) { + ast_file_err(f, f->cursor[0], "variadic parameter is missing a type after `..`"); + type = make_bad_expr(f, ellipsis, f->cursor[0]); + } else { + if (name_count > 1) { + ast_file_err(f, f->cursor[0], "mutliple variadic parameters, only 1 is allowed"); + type = make_bad_expr(f, ellipsis, f->cursor[0]); + } else { + type = make_ellipsis(f, ellipsis, type); + } + } + } else { + type = parse_type_attempt(f); + } + + if (type == NULL) { ast_file_err(f, f->cursor[0], "Expected a type for this field declaration"); + } AstNode *field = make_field(f, name_list, name_count, type, is_using); return field; } -Token parse_procedure_signature(AstFile *f, - AstNode **param_list, isize *param_count, - AstNode **result_list, isize *result_count); - -AstNode *parse_proc_type(AstFile *f) { - AstNode *params = NULL; - AstNode *results = NULL; - isize param_count = 0; - isize result_count = 0; - - Token proc_token = parse_procedure_signature(f, ¶ms, ¶m_count, &results, &result_count); - - return make_proc_type(f, proc_token, params, param_count, results, result_count); -} - - -AstNode *parse_parameter_list(AstFile *f, isize *param_count_, TokenKind separator, b32 allow_using) { +AstNode *parse_parameter_list(AstFile *f, isize *param_count_) { AstNode *param_list = NULL; AstNode *param_list_curr = NULL; isize param_count = 0; while (f->cursor[0].kind == Token_Identifier || - (allow_using && f->cursor[0].kind == Token_using)) { - if (!allow_using && allow_token(f, Token_using)) { - ast_file_err(f, f->cursor[-1], "`using` is only allowed within structures (at the moment)"); - } - AstNode *field = parse_field_decl(f, allow_using); + f->cursor[0].kind == Token_using) { + AstNode *field = parse_field_decl(f); DLIST_APPEND(param_list, param_list_curr, field); param_count += field->Field.name_count; - if (f->cursor[0].kind != separator) + if (f->cursor[0].kind != Token_Comma) break; next_token(f); } @@ -1746,14 +1773,18 @@ AstNode *parse_struct_params(AstFile *f, isize *decl_count_) { AstNode *parse_identifier_or_type(AstFile *f) { switch (f->cursor[0].kind) { case Token_Identifier: { - AstNode *ident = parse_identifier(f); + AstNode *e = parse_identifier(f); while (f->cursor[0].kind == Token_Period) { Token token = f->cursor[0]; next_token(f); AstNode *sel = parse_identifier(f); - ident = make_selector_expr(f, token, ident, sel); + e = make_selector_expr(f, token, e, sel); + } + if (f->cursor[0].kind == Token_OpenParen) { + // HACK NOTE(bill): For type_of_val(expr) + e = parse_call_expr(f, e); } - return ident; + return e; } case Token_Pointer: @@ -1765,7 +1796,7 @@ AstNode *parse_identifier_or_type(AstFile *f) { AstNode *count_expr = NULL; if (f->cursor[0].kind == Token_Ellipsis) { - count_expr = make_ellipsis(f, f->cursor[0]); + count_expr = make_ellipsis(f, f->cursor[0], NULL); next_token(f); } else if (f->cursor[0].kind != Token_CloseBracket) { count_expr = parse_expr(f, false); @@ -1922,7 +1953,7 @@ Token parse_procedure_signature(AstFile *f, AstNode **result_list, isize *result_count) { Token proc_token = expect_token(f, Token_proc); expect_token(f, Token_OpenParen); - *param_list = parse_parameter_list(f, param_count, Token_Comma, true); + *param_list = parse_parameter_list(f, param_count); expect_token(f, Token_CloseParen); *result_list = parse_results(f, result_count); return proc_token; |