diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2016-01-13 18:15:51 -0700 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2016-01-13 18:15:51 -0700 |
| commit | b28b7f63d15ab0fdd9064c6c58e6339705edbc27 (patch) | |
| tree | 8139f31b749a6838bb92d16053e371f826224d32 /src/parser.cpp | |
| parent | cb46d0b5b0d1d83856adab34b461049f5cfac019 (diff) | |
| download | zig-b28b7f63d15ab0fdd9064c6c58e6339705edbc27.tar.gz zig-b28b7f63d15ab0fdd9064c6c58e6339705edbc27.zip | |
all types are now expressions
See #22
Diffstat (limited to 'src/parser.cpp')
| -rw-r--r-- | src/parser.cpp | 919 |
1 files changed, 393 insertions, 526 deletions
diff --git a/src/parser.cpp b/src/parser.cpp index b9c55ef319..de9dcf0a17 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -62,6 +62,7 @@ static const char *prefix_op_str(PrefixOp prefix_op) { case PrefixOpAddressOf: return "&"; case PrefixOpConstAddressOf: return "&const"; case PrefixOpDereference: return "*"; + case PrefixOpMaybe: return "?"; } zig_unreachable(); } @@ -80,8 +81,6 @@ const char *node_type_str(NodeType node_type) { return "FnProto"; case NodeTypeParamDecl: return "ParamDecl"; - case NodeTypeType: - return "Type"; case NodeTypeBlock: return "Block"; case NodeTypeBinOpExpr: @@ -108,16 +107,12 @@ const char *node_type_str(NodeType node_type) { return "StringLiteral"; case NodeTypeCharLiteral: return "CharLiteral"; - case NodeTypeUnreachable: - return "Unreachable"; case NodeTypeSymbol: return "Symbol"; case NodeTypePrefixOpExpr: return "PrefixOpExpr"; case NodeTypeUse: return "Use"; - case NodeTypeVoid: - return "Void"; case NodeTypeBoolLiteral: return "BoolLiteral"; case NodeTypeNullLiteral: @@ -144,14 +139,12 @@ const char *node_type_str(NodeType node_type) { return "StructDecl"; case NodeTypeStructField: return "StructField"; - case NodeTypeStructValueExpr: - return "StructValueExpr"; case NodeTypeStructValueField: return "StructValueField"; - case NodeTypeCompilerFnExpr: - return "CompilerFnExpr"; - case NodeTypeCompilerFnType: - return "CompilerFnType"; + case NodeTypeContainerInitExpr: + return "ContainerInitExpr"; + case NodeTypeArrayType: + return "ArrayType"; } zig_unreachable(); } @@ -214,47 +207,6 @@ void ast_print(AstNode *node, int indent) { break; } - case NodeTypeType: - switch (node->data.type.type) { - case AstNodeTypeTypePrimitive: - { - Buf *name_buf = &node->data.type.primitive_name; - fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf)); - break; - } - case AstNodeTypeTypePointer: - { - const char *const_or_mut_str = node->data.type.is_const ? "const " : ""; - const char *noalias_or_not_str = node->data.type.is_noalias ? "noalias " : ""; - fprintf(stderr, "%s%s PointerType\n", const_or_mut_str, noalias_or_not_str); - - ast_print(node->data.type.child_type, indent + 2); - break; - } - case AstNodeTypeTypeArray: - { - const char *const_or_mut_str = node->data.type.is_const ? "const " : ""; - const char *noalias_or_not_str = node->data.type.is_noalias ? "noalias " : ""; - fprintf(stderr, "%s%s ArrayType\n", const_or_mut_str, noalias_or_not_str); - if (node->data.type.array_size) - ast_print(node->data.type.array_size, indent + 2); - ast_print(node->data.type.child_type, indent + 2); - break; - } - case AstNodeTypeTypeMaybe: - { - fprintf(stderr, "MaybeType\n"); - ast_print(node->data.type.child_type, indent + 2); - break; - } - case AstNodeTypeTypeCompilerExpr: - { - fprintf(stderr, "CompilerExprType\n"); - ast_print(node->data.type.compiler_expr, indent + 2); - break; - } - } - break; case NodeTypeReturnExpr: fprintf(stderr, "%s\n", node_type_str(node->type)); if (node->data.return_expr.expr) @@ -348,18 +300,12 @@ void ast_print(AstNode *node, int indent) { fprintf(stderr, "%s '%c'\n", node_type_str(node->type), node->data.char_literal.value); break; } - case NodeTypeUnreachable: - fprintf(stderr, "Unreachable\n"); - break; case NodeTypeSymbol: fprintf(stderr, "Symbol %s\n", buf_ptr(&node->data.symbol_expr.symbol)); break; case NodeTypeUse: fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.use.path)); break; - case NodeTypeVoid: - fprintf(stderr, "%s\n", node_type_str(node->type)); - break; case NodeTypeBoolLiteral: fprintf(stderr, "%s '%s'\n", node_type_str(node->type), node->data.bool_literal.value ? "true" : "false"); @@ -431,24 +377,28 @@ void ast_print(AstNode *node, int indent) { ast_print(node->data.struct_field.type, indent + 2); } break; - case NodeTypeStructValueExpr: - fprintf(stderr, "%s\n", node_type_str(node->type)); - ast_print(node->data.struct_val_expr.type, indent + 2); - for (int i = 0; i < node->data.struct_val_expr.fields.length; i += 1) { - AstNode *child = node->data.struct_val_expr.fields.at(i); - ast_print(child, indent + 2); - } - break; case NodeTypeStructValueField: fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.struct_val_field.name)); ast_print(node->data.struct_val_field.expr, indent + 2); break; - case NodeTypeCompilerFnExpr: - fprintf(stderr, "%s\n", node_type_str(node->type)); - break; - case NodeTypeCompilerFnType: + case NodeTypeContainerInitExpr: fprintf(stderr, "%s\n", node_type_str(node->type)); + ast_print(node->data.container_init_expr.type, indent + 2); + for (int i = 0; i < node->data.container_init_expr.entries.length; i += 1) { + AstNode *child = node->data.container_init_expr.entries.at(i); + ast_print(child, indent + 2); + } break; + case NodeTypeArrayType: + { + const char *const_str = node->data.array_type.is_const ? "const" : "var"; + fprintf(stderr, "%s %s\n", node_type_str(node->type), const_str); + if (node->data.array_type.size) { + ast_print(node->data.array_type.size, indent + 2); + } + ast_print(node->data.array_type.child_type, indent + 2); + break; + } } } @@ -539,9 +489,8 @@ static AstNode *ast_create_node_with_node(ParseContext *pc, NodeType type, AstNo } static AstNode *ast_create_void_type_node(ParseContext *pc, Token *token) { - AstNode *node = ast_create_node(pc, NodeTypeType, token); - node->data.type.type = AstNodeTypeTypePrimitive; - buf_init_from_str(&node->data.type.primitive_name, "void"); + AstNode *node = ast_create_node(pc, NodeTypeSymbol, token); + buf_init_from_str(&node->data.symbol_expr.symbol, "void"); return node; } @@ -961,7 +910,7 @@ static AstNode *ast_parse_expression(ParseContext *pc, int *token_index, bool ma static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandatory); static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool mandatory); static AstNode *ast_parse_block_expr(ParseContext *pc, int *token_index, bool mandatory); -static AstNode *ast_parse_type(ParseContext *pc, int *token_index); +static AstNode *ast_parse_unwrap_maybe_expr(ParseContext *pc, int *token_index, bool mandatory); static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) { if (token->id != token_id) { @@ -1022,172 +971,42 @@ static void ast_parse_directives(ParseContext *pc, int *token_index, zig_unreachable(); } -static void ast_parse_type_assume_amp(ParseContext *pc, int *token_index, AstNode *node) { - node->data.type.type = AstNodeTypeTypePointer; - Token *first_type_token = &pc->tokens->at(*token_index); - if (first_type_token->id == TokenIdKeywordConst) { - node->data.type.is_const = true; - *token_index += 1; - first_type_token = &pc->tokens->at(*token_index); - if (first_type_token->id == TokenIdKeywordNoAlias) { - node->data.type.is_noalias = true; - *token_index += 1; - } - } else if (first_type_token->id == TokenIdKeywordNoAlias) { - node->data.type.is_noalias = true; - *token_index += 1; - } - - node->data.type.child_type = ast_parse_type(pc, token_index); -} - /* -CompilerFnType : token(NumberSign) token(Symbol) token(LParen) Expression token(RParen) +ParamDecl : option(token(NoAlias)) token(Symbol) token(Colon) UnwrapMaybeExpression | token(Ellipsis) */ -static AstNode *ast_parse_compiler_fn_type(ParseContext *pc, int *token_index, bool mandatory) { - Token *token = &pc->tokens->at(*token_index); +static AstNode *ast_parse_param_decl(ParseContext *pc, int *token_index) { + Token *first_token = &pc->tokens->at(*token_index); - if (token->id == TokenIdNumberSign) { + if (first_token->id == TokenIdEllipsis) { *token_index += 1; - } else if (mandatory) { - ast_invalid_token_error(pc, token); - } else { return nullptr; } - Token *name_symbol = ast_eat_token(pc, token_index, TokenIdSymbol); - ast_eat_token(pc, token_index, TokenIdLParen); - - AstNode *node = ast_create_node(pc, NodeTypeCompilerFnType, token); - ast_buf_from_token(pc, name_symbol, &node->data.compiler_fn_type.name); - node->data.compiler_fn_type.type = ast_parse_type(pc, token_index); + AstNode *node = ast_create_node(pc, NodeTypeParamDecl, first_token); + Token *name_token; - ast_eat_token(pc, token_index, TokenIdRParen); - return node; -} - -/* -CompilerFnExpr : token(NumberSign) token(Symbol) token(LParen) Expression token(RParen) -*/ -static AstNode *ast_parse_compiler_fn_call(ParseContext *pc, int *token_index, bool mandatory) { - Token *token = &pc->tokens->at(*token_index); - - if (token->id == TokenIdNumberSign) { + if (first_token->id == TokenIdKeywordNoAlias) { + node->data.param_decl.is_noalias = true; + *token_index += 1; + name_token = ast_eat_token(pc, token_index, TokenIdSymbol); + } else if (first_token->id == TokenIdSymbol) { + name_token = first_token; *token_index += 1; - } else if (mandatory) { - ast_invalid_token_error(pc, token); } else { - return nullptr; + ast_invalid_token_error(pc, first_token); } - Token *name_symbol = ast_eat_token(pc, token_index, TokenIdSymbol); - ast_eat_token(pc, token_index, TokenIdLParen); - - AstNode *node = ast_create_node(pc, NodeTypeCompilerFnExpr, token); - ast_buf_from_token(pc, name_symbol, &node->data.compiler_fn_expr.name); - node->data.compiler_fn_expr.expr = ast_parse_expression(pc, token_index, true); - - ast_eat_token(pc, token_index, TokenIdRParen); - return node; -} - -/* -Type : token(Symbol) | token(Unreachable) | token(Void) | PointerType | ArrayType | MaybeType | CompilerFnExpr -PointerType : token(Ampersand) option(token(Const)) option(token(NoAlias)) Type -ArrayType : token(LBracket) option(Expression) token(RBracket) option(token(Const)) option(token(NoAlias)) Type -*/ -static AstNode *ast_parse_type(ParseContext *pc, int *token_index) { - Token *token = &pc->tokens->at(*token_index); - AstNode *node = ast_create_node(pc, NodeTypeType, token); - - AstNode *compiler_fn_expr = ast_parse_compiler_fn_call(pc, token_index, false); - if (compiler_fn_expr) { - node->data.type.type = AstNodeTypeTypeCompilerExpr; - node->data.type.compiler_expr = compiler_fn_expr; - return node; - } + ast_buf_from_token(pc, name_token, &node->data.param_decl.name); + Token *colon = &pc->tokens->at(*token_index); *token_index += 1; + ast_expect_token(pc, colon, TokenIdColon); - if (token->id == TokenIdKeywordUnreachable) { - node->data.type.type = AstNodeTypeTypePrimitive; - buf_init_from_str(&node->data.type.primitive_name, "unreachable"); - } else if (token->id == TokenIdKeywordVoid) { - node->data.type.type = AstNodeTypeTypePrimitive; - buf_init_from_str(&node->data.type.primitive_name, "void"); - } else if (token->id == TokenIdSymbol) { - node->data.type.type = AstNodeTypeTypePrimitive; - ast_buf_from_token(pc, token, &node->data.type.primitive_name); - } else if (token->id == TokenIdAmpersand) { - ast_parse_type_assume_amp(pc, token_index, node); - } else if (token->id == TokenIdMaybe) { - node->data.type.type = AstNodeTypeTypeMaybe; - node->data.type.child_type = ast_parse_type(pc, token_index); - } else if (token->id == TokenIdBoolAnd) { - // Pretend that we got 2 ampersand tokens - node->data.type.type = AstNodeTypeTypePointer; - - node->data.type.child_type = ast_create_node_no_line_info(pc, NodeTypeType); - node->data.type.child_type->line = token->start_line; - node->data.type.child_type->column = token->start_column + 1; - - ast_parse_type_assume_amp(pc, token_index, node->data.type.child_type); - } else if (token->id == TokenIdLBracket) { - node->data.type.type = AstNodeTypeTypeArray; - - node->data.type.array_size = ast_parse_expression(pc, token_index, false); - - ast_eat_token(pc, token_index, TokenIdRBracket); - - Token *const_tok = &pc->tokens->at(*token_index); - if (const_tok->id == TokenIdKeywordConst) { - *token_index += 1; - node->data.type.is_const = true; - - Token *next_tok = &pc->tokens->at(*token_index); - if (next_tok->id == TokenIdKeywordNoAlias) { - *token_index += 1; - node->data.type.is_noalias = true; - } - } else if (const_tok->id == TokenIdKeywordNoAlias) { - *token_index += 1; - node->data.type.is_noalias = true; - } - - node->data.type.child_type = ast_parse_type(pc, token_index); - } else { - ast_invalid_token_error(pc, token); - } + node->data.param_decl.type = ast_parse_unwrap_maybe_expr(pc, token_index, true); return node; } -/* -ParamDecl : token(Symbol) token(Colon) Type | token(Ellipsis) -*/ -static AstNode *ast_parse_param_decl(ParseContext *pc, int *token_index) { - Token *param_name = &pc->tokens->at(*token_index); - *token_index += 1; - - if (param_name->id == TokenIdSymbol) { - AstNode *node = ast_create_node(pc, NodeTypeParamDecl, param_name); - - ast_buf_from_token(pc, param_name, &node->data.param_decl.name); - - Token *colon = &pc->tokens->at(*token_index); - *token_index += 1; - ast_expect_token(pc, colon, TokenIdColon); - - node->data.param_decl.type = ast_parse_type(pc, token_index); - - return node; - } else if (param_name->id == TokenIdEllipsis) { - return nullptr; - } else { - ast_invalid_token_error(pc, param_name); - } -} - static void ast_parse_param_decl_list(ParseContext *pc, int *token_index, ZigList<AstNode *> *params, bool *is_var_args) @@ -1274,52 +1093,222 @@ static AstNode *ast_parse_grouped_expr(ParseContext *pc, int *token_index, bool } /* -StructValueExpression : token(Symbol) token(LBrace) list(StructValueExpressionField, token(Comma)) token(RBrace) -StructValueExpressionField : token(Dot) token(Symbol) token(Eq) Expression +ArrayType : token(LBracket) option(Expression) token(RBracket) option(token(Const)) Expression */ -static AstNode *ast_parse_struct_val_expr(ParseContext *pc, int *token_index) { - Token *first_token = &pc->tokens->at(*token_index); - AstNode *node = ast_create_node(pc, NodeTypeStructValueExpr, first_token); +static AstNode *ast_parse_array_type_expr(ParseContext *pc, int *token_index, bool mandatory) { + Token *l_bracket = &pc->tokens->at(*token_index); + if (l_bracket->id != TokenIdLBracket) { + if (mandatory) { + ast_invalid_token_error(pc, l_bracket); + } else { + return nullptr; + } + } - node->data.struct_val_expr.type = ast_parse_type(pc, token_index); + *token_index += 1; - ast_eat_token(pc, token_index, TokenIdLBrace); + AstNode *node = ast_create_node(pc, NodeTypeArrayType, l_bracket); + node->data.array_type.size = ast_parse_expression(pc, token_index, false); + + ast_eat_token(pc, token_index, TokenIdRBracket); + + Token *const_tok = &pc->tokens->at(*token_index); + if (const_tok->id == TokenIdKeywordConst) { + *token_index += 1; + node->data.array_type.is_const = true; + } + + node->data.array_type.child_type = ast_parse_expression(pc, token_index, true); + + return node; +} + +/* +AsmInputItem : token(LBracket) token(Symbol) token(RBracket) token(String) token(LParen) Expression token(RParen) +*/ +static void ast_parse_asm_input_item(ParseContext *pc, int *token_index, AstNode *node) { + ast_eat_token(pc, token_index, TokenIdLBracket); + Token *alias = ast_eat_token(pc, token_index, TokenIdSymbol); + ast_eat_token(pc, token_index, TokenIdRBracket); + + Token *constraint = ast_eat_token(pc, token_index, TokenIdStringLiteral); + + ast_eat_token(pc, token_index, TokenIdLParen); + AstNode *expr_node = ast_parse_expression(pc, token_index, true); + ast_eat_token(pc, token_index, TokenIdRParen); + + AsmInput *asm_input = allocate<AsmInput>(1); + ast_buf_from_token(pc, alias, &asm_input->asm_symbolic_name); + parse_string_literal(pc, constraint, &asm_input->constraint, nullptr, nullptr); + asm_input->expr = expr_node; + node->data.asm_expr.input_list.append(asm_input); +} + +/* +AsmOutputItem : token(LBracket) token(Symbol) token(RBracket) token(String) token(LParen) (token(Symbol) | token(Arrow) Expression) token(RParen) +*/ +static void ast_parse_asm_output_item(ParseContext *pc, int *token_index, AstNode *node) { + ast_eat_token(pc, token_index, TokenIdLBracket); + Token *alias = ast_eat_token(pc, token_index, TokenIdSymbol); + ast_eat_token(pc, token_index, TokenIdRBracket); + + Token *constraint = ast_eat_token(pc, token_index, TokenIdStringLiteral); + + AsmOutput *asm_output = allocate<AsmOutput>(1); + + ast_eat_token(pc, token_index, TokenIdLParen); + + Token *token = &pc->tokens->at(*token_index); + *token_index += 1; + if (token->id == TokenIdSymbol) { + ast_buf_from_token(pc, token, &asm_output->variable_name); + } else if (token->id == TokenIdArrow) { + asm_output->return_type = ast_parse_expression(pc, token_index, true); + } else { + ast_invalid_token_error(pc, token); + } + + ast_eat_token(pc, token_index, TokenIdRParen); + + ast_buf_from_token(pc, alias, &asm_output->asm_symbolic_name); + parse_string_literal(pc, constraint, &asm_output->constraint, nullptr, nullptr); + node->data.asm_expr.output_list.append(asm_output); +} + +/* +AsmClobbers: token(Colon) list(token(String), token(Comma)) +*/ +static void ast_parse_asm_clobbers(ParseContext *pc, int *token_index, AstNode *node) { + Token *colon_tok = &pc->tokens->at(*token_index); + + if (colon_tok->id != TokenIdColon) + return; + + *token_index += 1; for (;;) { - Token *token = &pc->tokens->at(*token_index); + Token *string_tok = &pc->tokens->at(*token_index); + ast_expect_token(pc, string_tok, TokenIdStringLiteral); *token_index += 1; - if (token->id == TokenIdRBrace) { - return node; - } else if (token->id == TokenIdDot) { - Token *field_name_tok = ast_eat_token(pc, token_index, TokenIdSymbol); - ast_eat_token(pc, token_index, TokenIdEq); + Buf *clobber_buf = buf_alloc(); + parse_string_literal(pc, string_tok, clobber_buf, nullptr, nullptr); + node->data.asm_expr.clobber_list.append(clobber_buf); - AstNode *field_node = ast_create_node(pc, NodeTypeStructValueField, token); + Token *comma = &pc->tokens->at(*token_index); - ast_buf_from_token(pc, field_name_tok, &field_node->data.struct_val_field.name); - field_node->data.struct_val_field.expr = ast_parse_expression(pc, token_index, true); + if (comma->id == TokenIdComma) { + *token_index += 1; + continue; + } else { + break; + } + } +} - node->data.struct_val_expr.fields.append(field_node); +/* +AsmInput : token(Colon) list(AsmInputItem, token(Comma)) option(AsmClobbers) +*/ +static void ast_parse_asm_input(ParseContext *pc, int *token_index, AstNode *node) { + Token *colon_tok = &pc->tokens->at(*token_index); - Token *comma_tok = &pc->tokens->at(*token_index); - if (comma_tok->id == TokenIdComma) { - *token_index += 1; - } else if (comma_tok->id != TokenIdRBrace) { - ast_invalid_token_error(pc, comma_tok); - } else { - *token_index += 1; - return node; - } + if (colon_tok->id != TokenIdColon) + return; + + *token_index += 1; + + for (;;) { + ast_parse_asm_input_item(pc, token_index, node); + + Token *comma = &pc->tokens->at(*token_index); + + if (comma->id == TokenIdComma) { + *token_index += 1; + continue; } else { - ast_invalid_token_error(pc, token); + break; } } + + ast_parse_asm_clobbers(pc, token_index, node); } /* -PrimaryExpression : token(Number) | token(String) | token(CharLiteral) | KeywordLiteral | GroupedExpression | Goto | token(Break) | token(Continue) | BlockExpression | token(Symbol) | StructValueExpression | CompilerFnType | (token(AtSign) token(Symbol) FnCallExpression) -KeywordLiteral : token(Unreachable) | token(Void) | token(True) | token(False) | token(Null) +AsmOutput : token(Colon) list(AsmOutputItem, token(Comma)) option(AsmInput) +*/ +static void ast_parse_asm_output(ParseContext *pc, int *token_index, AstNode *node) { + Token *colon_tok = &pc->tokens->at(*token_index); + + if (colon_tok->id != TokenIdColon) + return; + + *token_index += 1; + + for (;;) { + ast_parse_asm_output_item(pc, token_index, node); + + Token *comma = &pc->tokens->at(*token_index); + + if (comma->id == TokenIdComma) { + *token_index += 1; + continue; + } else { + break; + } + } + + ast_parse_asm_input(pc, token_index, node); +} + +/* +AsmExpression : token(Asm) option(token(Volatile)) token(LParen) token(String) option(AsmOutput) token(RParen) +*/ +static AstNode *ast_parse_asm_expr(ParseContext *pc, int *token_index, bool mandatory) { + Token *asm_token = &pc->tokens->at(*token_index); + + if (asm_token->id != TokenIdKeywordAsm) { + if (mandatory) { + ast_invalid_token_error(pc, asm_token); + } else { + return nullptr; + } + } + + AstNode *node = ast_create_node(pc, NodeTypeAsmExpr, asm_token); + + *token_index += 1; + Token *lparen_tok = &pc->tokens->at(*token_index); + + if (lparen_tok->id == TokenIdKeywordVolatile) { + node->data.asm_expr.is_volatile = true; + + *token_index += 1; + lparen_tok = &pc->tokens->at(*token_index); + } + + ast_expect_token(pc, lparen_tok, TokenIdLParen); + *token_index += 1; + + Token *template_tok = &pc->tokens->at(*token_index); + ast_expect_token(pc, template_tok, TokenIdStringLiteral); + *token_index += 1; + + parse_string_literal(pc, template_tok, &node->data.asm_expr.asm_template, nullptr, + &node->data.asm_expr.offset_map); + parse_asm_template(pc, node); + + ast_parse_asm_output(pc, token_index, node); + + Token *rparen_tok = &pc->tokens->at(*token_index); + ast_expect_token(pc, rparen_tok, TokenIdRParen); + *token_index += 1; + + return node; +} + +/* +PrimaryExpression : token(Number) | token(String) | token(CharLiteral) | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | token(Symbol) | (token(AtSign) token(Symbol) FnCallExpression) | ArrayType | AsmExpression +KeywordLiteral : token(True) | token(False) | token(Null) | token(Break) | token(Continue) */ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool mandatory) { Token *token = &pc->tokens->at(*token_index); @@ -1339,14 +1328,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool node->data.char_literal.value = parse_char_literal(pc, token); *token_index += 1; return node; - } else if (token->id == TokenIdKeywordUnreachable) { - AstNode *node = ast_create_node(pc, NodeTypeUnreachable, token); - *token_index += 1; - return node; - } else if (token->id == TokenIdKeywordVoid) { - AstNode *node = ast_create_node(pc, NodeTypeVoid, token); - *token_index += 1; - return node; } else if (token->id == TokenIdKeywordTrue) { AstNode *node = ast_create_node(pc, NodeTypeBoolLiteral, token); node->data.bool_literal.value = true; @@ -1361,6 +1342,14 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool AstNode *node = ast_create_node(pc, NodeTypeNullLiteral, token); *token_index += 1; return node; + } else if (token->id == TokenIdKeywordBreak) { + AstNode *node = ast_create_node(pc, NodeTypeBreak, token); + *token_index += 1; + return node; + } else if (token->id == TokenIdKeywordContinue) { + AstNode *node = ast_create_node(pc, NodeTypeContinue, token); + *token_index += 1; + return node; } else if (token->id == TokenIdAtSign) { *token_index += 1; Token *name_tok = ast_eat_token(pc, token_index, TokenIdSymbol); @@ -1374,16 +1363,10 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool node->data.fn_call_expr.is_builtin = true; return node; } else if (token->id == TokenIdSymbol) { - Token *next_token = &pc->tokens->at(*token_index + 1); - - if (next_token->id == TokenIdLBrace) { - return ast_parse_struct_val_expr(pc, token_index); - } else { - *token_index += 1; - AstNode *node = ast_create_node(pc, NodeTypeSymbol, token); - ast_buf_from_token(pc, token, &node->data.symbol_expr.symbol); - return node; - } + *token_index += 1; + AstNode *node = ast_create_node(pc, NodeTypeSymbol, token); + ast_buf_from_token(pc, token, &node->data.symbol_expr.symbol); + return node; } else if (token->id == TokenIdKeywordGoto) { AstNode *node = ast_create_node(pc, NodeTypeGoto, token); *token_index += 1; @@ -1394,14 +1377,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool ast_buf_from_token(pc, dest_symbol, &node->data.goto_expr.name); return node; - } else if (token->id == TokenIdKeywordBreak) { - AstNode *node = ast_create_node(pc, NodeTypeBreak, token); - *token_index += 1; - return node; - } else if (token->id == TokenIdKeywordContinue) { - AstNode *node = ast_create_node(pc, NodeTypeContinue, token); - *token_index += 1; - return node; } AstNode *grouped_expr_node = ast_parse_grouped_expr(pc, token_index, false); @@ -1414,9 +1389,14 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool return block_expr_node; } - AstNode *compiler_fn_type = ast_parse_compiler_fn_type(pc, token_index, false); - if (compiler_fn_type) { - return compiler_fn_type; + AstNode *array_type_node = ast_parse_array_type_expr(pc, token_index, false); + if (array_type_node) { + return array_type_node; + } + + AstNode *asm_expr = ast_parse_asm_expr(pc, token_index, false); + if (asm_expr) { + return asm_expr; } if (!mandatory) @@ -1426,11 +1406,14 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool } /* -SuffixOpExpression : PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression) +SuffixOpExpression : PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression | ContainerInitExpression) FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen) ArrayAccessExpression : token(LBracket) Expression token(RBracket) SliceExpression : token(LBracket) Expression token(Ellipsis) option(Expression) token(RBracket) option(token(Const)) FieldAccessExpression : token(Dot) token(Symbol) +ContainerInitExpression : token(LBrace) ContainerInitBody token(RBrace) +ContainerInitBody : list(StructLiteralField, token(Comma)) | list(Expression, token(Comma)) +StructLiteralField : token(Dot) token(Symbol) token(Eq) Expression */ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, int *token_index, bool mandatory) { AstNode *primary_expr = ast_parse_primary_expr(pc, token_index, mandatory); @@ -1439,16 +1422,16 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, int *token_index, boo } while (true) { - Token *token = &pc->tokens->at(*token_index); - if (token->id == TokenIdLParen) { + Token *first_token = &pc->tokens->at(*token_index); + if (first_token->id == TokenIdLParen) { *token_index += 1; - AstNode *node = ast_create_node(pc, NodeTypeFnCallExpr, token); + AstNode *node = ast_create_node(pc, NodeTypeFnCallExpr, first_token); node->data.fn_call_expr.fn_ref_expr = primary_expr; ast_parse_fn_call_param_list(pc, token_index, &node->data.fn_call_expr.params); primary_expr = node; - } else if (token->id == TokenIdLBracket) { + } else if (first_token->id == TokenIdLBracket) { *token_index += 1; AstNode *expr_node = ast_parse_expression(pc, token_index, true); @@ -1458,7 +1441,7 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, int *token_index, boo if (ellipsis_or_r_bracket->id == TokenIdEllipsis) { *token_index += 1; - AstNode *node = ast_create_node(pc, NodeTypeSliceExpr, token); + AstNode *node = ast_create_node(pc, NodeTypeSliceExpr, first_token); node->data.slice_expr.array_ref_expr = primary_expr; node->data.slice_expr.start = expr_node; node->data.slice_expr.end = ast_parse_expression(pc, token_index, false); @@ -1475,24 +1458,89 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, int *token_index, boo } else if (ellipsis_or_r_bracket->id == TokenIdRBracket) { *token_index += 1; - AstNode *node = ast_create_node(pc, NodeTypeArrayAccessExpr, token); + AstNode *node = ast_create_node(pc, NodeTypeArrayAccessExpr, first_token); node->data.array_access_expr.array_ref_expr = primary_expr; node->data.array_access_expr.subscript = expr_node; primary_expr = node; } else { - ast_invalid_token_error(pc, token); + ast_invalid_token_error(pc, first_token); } - } else if (token->id == TokenIdDot) { + } else if (first_token->id == TokenIdDot) { *token_index += 1; Token *name_token = ast_eat_token(pc, token_index, TokenIdSymbol); - AstNode *node = ast_create_node(pc, NodeTypeFieldAccessExpr, token); + AstNode *node = ast_create_node(pc, NodeTypeFieldAccessExpr, first_token); node->data.field_access_expr.struct_expr = primary_expr; ast_buf_from_token(pc, name_token, &node->data.field_access_expr.field_name); primary_expr = node; + } else if (first_token->id == TokenIdLBrace) { + *token_index += 1; + + AstNode *node = ast_create_node(pc, NodeTypeContainerInitExpr, first_token); + node->data.container_init_expr.type = primary_expr; + + Token *token = &pc->tokens->at(*token_index); + if (token->id == TokenIdDot) { + for (;;) { + if (token->id == TokenIdDot) { + ast_eat_token(pc, token_index, TokenIdDot); + Token *field_name_tok = ast_eat_token(pc, token_index, TokenIdSymbol); + ast_eat_token(pc, token_index, TokenIdEq); + + AstNode *field_node = ast_create_node(pc, NodeTypeStructValueField, token); + + ast_buf_from_token(pc, field_name_tok, &field_node->data.struct_val_field.name); + field_node->data.struct_val_field.expr = ast_parse_expression(pc, token_index, true); + + node->data.container_init_expr.entries.append(field_node); + + Token *comma_tok = &pc->tokens->at(*token_index); + if (comma_tok->id == TokenIdComma) { + *token_index += 1; + token = &pc->tokens->at(*token_index); + continue; + } else if (comma_tok->id != TokenIdRBrace) { + ast_invalid_token_error(pc, comma_tok); + } else { + *token_index += 1; + break; + } + } else if (token->id == TokenIdRBrace) { + *token_index += 1; + break; + } else { + ast_invalid_token_error(pc, token); + } + } + + } else { + for (;;) { + if (token->id == TokenIdRBrace) { + *token_index += 1; + break; + } else { + AstNode *elem_node = ast_parse_expression(pc, token_index, true); + node->data.container_init_expr.entries.append(elem_node); + + Token *comma_tok = &pc->tokens->at(*token_index); + if (comma_tok->id == TokenIdComma) { + *token_index += 1; + token = &pc->tokens->at(*token_index); + continue; + } else if (comma_tok->id != TokenIdRBrace) { + ast_invalid_token_error(pc, comma_tok); + } else { + *token_index += 1; + break; + } + } + } + } + + primary_expr = node; } else { return primary_expr; } @@ -1506,56 +1554,54 @@ static PrefixOp tok_to_prefix_op(Token *token) { case TokenIdTilde: return PrefixOpBinNot; case TokenIdAmpersand: return PrefixOpAddressOf; case TokenIdStar: return PrefixOpDereference; + case TokenIdMaybe: return PrefixOpMaybe; + case TokenIdBoolAnd: return PrefixOpAddressOf; default: return PrefixOpInvalid; } } /* +PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression PrefixOp : token(Not) | token(Dash) | token(Tilde) | token(Star) | (token(Ampersand) option(token(Const))) */ -static PrefixOp ast_parse_prefix_op(ParseContext *pc, int *token_index, bool mandatory) { +static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, bool mandatory) { Token *token = &pc->tokens->at(*token_index); - PrefixOp result = tok_to_prefix_op(token); - if (result == PrefixOpInvalid) { - if (mandatory) { - ast_invalid_token_error(pc, token); - } else { - return PrefixOpInvalid; - } + PrefixOp prefix_op = tok_to_prefix_op(token); + if (prefix_op == PrefixOpInvalid) { + return ast_parse_suffix_op_expr(pc, token_index, mandatory); } *token_index += 1; - if (result == PrefixOpAddressOf) { + AstNode *node = ast_create_node(pc, NodeTypePrefixOpExpr, token); + AstNode *parent_node = node; + if (token->id == TokenIdBoolAnd) { + // pretend that we got 2 ampersand tokens + + parent_node = ast_create_node(pc, NodeTypePrefixOpExpr, token); + parent_node->data.prefix_op_expr.primary_expr = node; + parent_node->data.prefix_op_expr.prefix_op = PrefixOpAddressOf; + + node->column += 1; + } + + if (prefix_op == PrefixOpAddressOf) { Token *token = &pc->tokens->at(*token_index); if (token->id == TokenIdKeywordConst) { *token_index += 1; - result = PrefixOpConstAddressOf; + prefix_op = PrefixOpConstAddressOf; } } - return result; -} - -/* -PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression -*/ -static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, bool mandatory) { - Token *token = &pc->tokens->at(*token_index); - PrefixOp prefix_op = ast_parse_prefix_op(pc, token_index, false); - if (prefix_op == PrefixOpInvalid) - return ast_parse_suffix_op_expr(pc, token_index, mandatory); - AstNode *prefix_op_expr = ast_parse_prefix_op_expr(pc, token_index, true); - AstNode *node = ast_create_node(pc, NodeTypePrefixOpExpr, token); node->data.prefix_op_expr.primary_expr = prefix_op_expr; node->data.prefix_op_expr.prefix_op = prefix_op; - return node; + return parent_node; } /* -CastExpression : CastExpression token(as) Type | PrefixOpExpression +CastExpression : CastExpression token(as) PrimaryExpression | PrefixOpExpression */ static AstNode *ast_parse_cast_expression(ParseContext *pc, int *token_index, bool mandatory) { AstNode *operand_1 = ast_parse_prefix_op_expr(pc, token_index, mandatory); @@ -1571,7 +1617,7 @@ static AstNode *ast_parse_cast_expression(ParseContext *pc, int *token_index, bo AstNode *node = ast_create_node(pc, NodeTypeCastExpr, as_kw); node->data.cast_expr.expr = operand_1; - node->data.cast_expr.type = ast_parse_type(pc, token_index); + node->data.cast_expr.type = ast_parse_primary_expr(pc, token_index, true); operand_1 = node; } @@ -1899,7 +1945,7 @@ static AstNode *ast_parse_else(ParseContext *pc, int *token_index, bool mandator /* IfExpression : IfVarExpression | IfBoolExpression IfBoolExpression : token(If) token(LParen) Expression token(RParen) Expression option(Else) -IfVarExpression : token(If) token(LParen) (token(Const) | token(Var)) token(Symbol) option(token(Colon) Type) Token(MaybeAssign) Expression token(RParen) Expression Option(Else) +IfVarExpression : token(If) token(LParen) (token(Const) | token(Var)) token(Symbol) option(Expression) Token(MaybeAssign) Expression token(RParen) Expression Option(Else) */ static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool mandatory) { Token *if_tok = &pc->tokens->at(*token_index); @@ -1924,11 +1970,12 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool manda ast_buf_from_token(pc, name_token, &node->data.if_var_expr.var_decl.symbol); Token *eq_or_colon = &pc->tokens->at(*token_index); - *token_index += 1; if (eq_or_colon->id == TokenIdMaybeAssign) { + *token_index += 1; node->data.if_var_expr.var_decl.expr = ast_parse_expression(pc, token_index, true); } else if (eq_or_colon->id == TokenIdColon) { - node->data.if_var_expr.var_decl.type = ast_parse_type(pc, token_index); + *token_index += 1; + node->data.if_var_expr.var_decl.type = ast_parse_expression(pc, token_index, true); ast_eat_token(pc, token_index, TokenIdMaybeAssign); node->data.if_var_expr.var_decl.expr = ast_parse_expression(pc, token_index, true); @@ -1967,7 +2014,7 @@ static AstNode *ast_parse_return_expr(ParseContext *pc, int *token_index, bool m } /* -VariableDeclaration : option(FnVisibleMod) (token(Var) | token(Const)) token(Symbol) (token(Eq) Expression | token(Colon) Type option(token(Eq) Expression)) +VariableDeclaration : option(FnVisibleMod) (token(Var) | token(Const)) token(Symbol) (token(Eq) Expression | token(Colon) UnwrapMaybeExpression option(token(Eq) Expression)) */ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, int *token_index, bool mandatory) { Token *first_token = &pc->tokens->at(*token_index); @@ -2008,8 +2055,7 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, int *token node->data.variable_declaration.expr = ast_parse_expression(pc, token_index, true); return node; } else if (eq_or_colon->id == TokenIdColon) { - node->data.variable_declaration.type = ast_parse_type(pc, token_index); - + node->data.variable_declaration.type = ast_parse_unwrap_maybe_expr(pc, token_index, true); Token *eq_token = &pc->tokens->at(*token_index); if (eq_token->id == TokenIdEq) { *token_index += 1; @@ -2138,6 +2184,7 @@ static BinOpType ast_parse_ass_op(ParseContext *pc, int *token_index, bool manda /* UnwrapMaybeExpression : BoolOrExpression token(DoubleQuestion) BoolOrExpression | BoolOrExpression */ +// this is currently the first child expression of assignment static AstNode *ast_parse_unwrap_maybe_expr(ParseContext *pc, int *token_index, bool mandatory) { AstNode *lhs = ast_parse_bool_or_expr(pc, token_index, mandatory); if (!lhs) @@ -2185,190 +2232,7 @@ static AstNode *ast_parse_ass_expr(ParseContext *pc, int *token_index, bool mand } /* -AsmInputItem : token(LBracket) token(Symbol) token(RBracket) token(String) token(LParen) Expression token(RParen) -*/ -static void ast_parse_asm_input_item(ParseContext *pc, int *token_index, AstNode *node) { - ast_eat_token(pc, token_index, TokenIdLBracket); - Token *alias = ast_eat_token(pc, token_index, TokenIdSymbol); - ast_eat_token(pc, token_index, TokenIdRBracket); - - Token *constraint = ast_eat_token(pc, token_index, TokenIdStringLiteral); - - ast_eat_token(pc, token_index, TokenIdLParen); - AstNode *expr_node = ast_parse_expression(pc, token_index, true); - ast_eat_token(pc, token_index, TokenIdRParen); - - AsmInput *asm_input = allocate<AsmInput>(1); - ast_buf_from_token(pc, alias, &asm_input->asm_symbolic_name); - parse_string_literal(pc, constraint, &asm_input->constraint, nullptr, nullptr); - asm_input->expr = expr_node; - node->data.asm_expr.input_list.append(asm_input); -} - -/* -AsmOutputItem : token(LBracket) token(Symbol) token(RBracket) token(String) token(LParen) (token(Symbol) | token(Arrow) Type) token(RParen) -*/ -static void ast_parse_asm_output_item(ParseContext *pc, int *token_index, AstNode *node) { - ast_eat_token(pc, token_index, TokenIdLBracket); - Token *alias = ast_eat_token(pc, token_index, TokenIdSymbol); - ast_eat_token(pc, token_index, TokenIdRBracket); - - Token *constraint = ast_eat_token(pc, token_index, TokenIdStringLiteral); - - AsmOutput *asm_output = allocate<AsmOutput>(1); - - ast_eat_token(pc, token_index, TokenIdLParen); - - Token *token = &pc->tokens->at(*token_index); - *token_index += 1; - if (token->id == TokenIdSymbol) { - ast_buf_from_token(pc, token, &asm_output->variable_name); - } else if (token->id == TokenIdArrow) { - asm_output->return_type = ast_parse_type(pc, token_index); - } else { - ast_invalid_token_error(pc, token); - } - - ast_eat_token(pc, token_index, TokenIdRParen); - - ast_buf_from_token(pc, alias, &asm_output->asm_symbolic_name); - parse_string_literal(pc, constraint, &asm_output->constraint, nullptr, nullptr); - node->data.asm_expr.output_list.append(asm_output); -} - -/* -AsmClobbers: token(Colon) list(token(String), token(Comma)) -*/ -static void ast_parse_asm_clobbers(ParseContext *pc, int *token_index, AstNode *node) { - Token *colon_tok = &pc->tokens->at(*token_index); - - if (colon_tok->id != TokenIdColon) - return; - - *token_index += 1; - - for (;;) { - Token *string_tok = &pc->tokens->at(*token_index); - ast_expect_token(pc, string_tok, TokenIdStringLiteral); - *token_index += 1; - - Buf *clobber_buf = buf_alloc(); - parse_string_literal(pc, string_tok, clobber_buf, nullptr, nullptr); - node->data.asm_expr.clobber_list.append(clobber_buf); - - Token *comma = &pc->tokens->at(*token_index); - - if (comma->id == TokenIdComma) { - *token_index += 1; - continue; - } else { - break; - } - } -} - -/* -AsmInput : token(Colon) list(AsmInputItem, token(Comma)) option(AsmClobbers) -*/ -static void ast_parse_asm_input(ParseContext *pc, int *token_index, AstNode *node) { - Token *colon_tok = &pc->tokens->at(*token_index); - - if (colon_tok->id != TokenIdColon) - return; - - *token_index += 1; - - for (;;) { - ast_parse_asm_input_item(pc, token_index, node); - - Token *comma = &pc->tokens->at(*token_index); - - if (comma->id == TokenIdComma) { - *token_index += 1; - continue; - } else { - break; - } - } - - ast_parse_asm_clobbers(pc, token_index, node); -} - -/* -AsmOutput : token(Colon) list(AsmOutputItem, token(Comma)) option(AsmInput) -*/ -static void ast_parse_asm_output(ParseContext *pc, int *token_index, AstNode *node) { - Token *colon_tok = &pc->tokens->at(*token_index); - - if (colon_tok->id != TokenIdColon) - return; - - *token_index += 1; - - for (;;) { - ast_parse_asm_output_item(pc, token_index, node); - - Token *comma = &pc->tokens->at(*token_index); - - if (comma->id == TokenIdComma) { - *token_index += 1; - continue; - } else { - break; - } - } - - ast_parse_asm_input(pc, token_index, node); -} - -/* -AsmExpression : token(Asm) option(token(Volatile)) token(LParen) token(String) option(AsmOutput) token(RParen) -*/ -static AstNode *ast_parse_asm_expr(ParseContext *pc, int *token_index, bool mandatory) { - Token *asm_token = &pc->tokens->at(*token_index); - - if (asm_token->id != TokenIdKeywordAsm) { - if (mandatory) { - ast_invalid_token_error(pc, asm_token); - } else { - return nullptr; - } - } - - AstNode *node = ast_create_node(pc, NodeTypeAsmExpr, asm_token); - - *token_index += 1; - Token *lparen_tok = &pc->tokens->at(*token_index); - - if (lparen_tok->id == TokenIdKeywordVolatile) { - node->data.asm_expr.is_volatile = true; - - *token_index += 1; - lparen_tok = &pc->tokens->at(*token_index); - } - - ast_expect_token(pc, lparen_tok, TokenIdLParen); - *token_index += 1; - - Token *template_tok = &pc->tokens->at(*token_index); - ast_expect_token(pc, template_tok, TokenIdStringLiteral); - *token_index += 1; - - parse_string_literal(pc, template_tok, &node->data.asm_expr.asm_template, nullptr, - &node->data.asm_expr.offset_map); - parse_asm_template(pc, node); - - ast_parse_asm_output(pc, token_index, node); - - Token *rparen_tok = &pc->tokens->at(*token_index); - ast_expect_token(pc, rparen_tok, TokenIdRParen); - *token_index += 1; - - return node; -} - -/* -NonBlockExpression : ReturnExpression | AssignmentExpression | AsmExpression +NonBlockExpression : ReturnExpression | AssignmentExpression */ static AstNode *ast_parse_non_block_expr(ParseContext *pc, int *token_index, bool mandatory) { Token *token = &pc->tokens->at(*token_index); @@ -2381,10 +2245,6 @@ static AstNode *ast_parse_non_block_expr(ParseContext *pc, int *token_index, boo if (ass_expr) return ass_expr; - AstNode *asm_expr = ast_parse_asm_expr(pc, token_index, false); - if (asm_expr) - return asm_expr; - if (mandatory) ast_invalid_token_error(pc, token); @@ -2440,6 +2300,14 @@ static AstNode *ast_parse_label(ParseContext *pc, int *token_index, bool mandato return node; } +static AstNode *ast_create_void_expr(ParseContext *pc, Token *token) { + AstNode *node = ast_create_node(pc, NodeTypeContainerInitExpr, token); + node->data.container_init_expr.type = ast_create_node(pc, NodeTypeSymbol, token); + node->data.container_init_expr.kind = ContainerInitKindArray; + buf_init_from_str(&node->data.container_init_expr.type->data.symbol_expr.symbol, "void"); + return node; +} + /* Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace) Statement : Label | VariableDeclaration token(Semicolon) | NonBlockExpression token(Semicolon) | BlockExpression @@ -2478,7 +2346,7 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato if (!statement_node) { statement_node = ast_parse_non_block_expr(pc, token_index, false); if (!statement_node) { - statement_node = ast_create_node(pc, NodeTypeVoid, last_token); + statement_node = ast_create_void_expr(pc, last_token); } } } @@ -2501,7 +2369,7 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato } /* -FnProto : many(Directive) option(FnVisibleMod) token(Fn) token(Symbol) ParamDeclList option(token(Arrow) Type) +FnProto : many(Directive) option(FnVisibleMod) token(Fn) token(Symbol) ParamDeclList option(Expression) */ static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mandatory) { Token *first_token = &pc->tokens->at(*token_index); @@ -2552,19 +2420,17 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mand ast_parse_param_decl_list(pc, token_index, &node->data.fn_proto.params, &node->data.fn_proto.is_var_args); - Token *arrow = &pc->tokens->at(*token_index); - if (arrow->id == TokenIdArrow) { - *token_index += 1; - node->data.fn_proto.return_type = ast_parse_type(pc, token_index); - } else { - node->data.fn_proto.return_type = ast_create_void_type_node(pc, arrow); + Token *next_token = &pc->tokens->at(*token_index); + node->data.fn_proto.return_type = ast_parse_expression(pc, token_index, false); + if (!node->data.fn_proto.return_type) { + node->data.fn_proto.return_type = ast_create_void_type_node(pc, next_token); } return node; } /* -FnDef : FnProto Block +FnDef : FnProto token(FatArrow) Block */ static AstNode *ast_parse_fn_def(ParseContext *pc, int *token_index, bool mandatory) { AstNode *fn_proto = ast_parse_fn_proto(pc, token_index, mandatory); @@ -2573,6 +2439,7 @@ static AstNode *ast_parse_fn_def(ParseContext *pc, int *token_index, bool mandat AstNode *node = ast_create_node_with_node(pc, NodeTypeFnDef, fn_proto); node->data.fn_def.fn_proto = fn_proto; + ast_eat_token(pc, token_index, TokenIdFatArrow); node->data.fn_def.body = ast_parse_block(pc, token_index, true); return node; @@ -2709,7 +2576,7 @@ static AstNode *ast_parse_use(ParseContext *pc, int *token_index) { /* ContainerDecl : many(Directive) option(FnVisibleMod) (token(Struct) | token(Enum)) token(Symbol) token(LBrace) many(StructMember) token(RBrace) StructMember: StructField | FnDecl -StructField : token(Symbol) token(Colon) Type token(Comma) +StructField : token(Symbol) option(token(Colon) Expression) token(Comma)) */ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) { Token *first_token = &pc->tokens->at(*token_index); @@ -2792,16 +2659,16 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) { ast_buf_from_token(pc, token, &field_node->data.struct_field.name); - Token *colon_tok = &pc->tokens->at(*token_index); - if (colon_tok->id == TokenIdColon) { + Token *expr_or_comma = &pc->tokens->at(*token_index); + if (expr_or_comma->id == TokenIdComma) { + field_node->data.struct_field.type = ast_create_void_type_node(pc, expr_or_comma); *token_index += 1; - field_node->data.struct_field.type = ast_parse_type(pc, token_index); } else { - field_node->data.struct_field.type = ast_create_void_type_node(pc, colon_tok); + ast_eat_token(pc, token_index, TokenIdColon); + field_node->data.struct_field.type = ast_parse_expression(pc, token_index, true); + ast_eat_token(pc, token_index, TokenIdComma); } - ast_eat_token(pc, token_index, TokenIdComma); - node->data.struct_decl.fields.append(field_node); } else { ast_invalid_token_error(pc, token); |
