// NOTE: The one weird define you need to know before read the code below
#define make_node(nclass, kind) onyx_ast_node_new(parser->allocator, sizeof(nclass), kind)
+#define peek_token(ahead) (parser->curr + ahead)
#define STORE_PARSER_STATE \
OnyxToken* __parser_curr = parser->curr; \
static b32 parse_possible_struct_literal(OnyxParser* parser, AstTyped* left, AstTyped** ret) {
if (parser->curr->type != '.'
- || (parser->curr + 1)->type != '{') return 0;
+ || peek_token(1)->type != '{') return 0;
AstStructLiteral* sl = make_node(AstStructLiteral, Ast_Kind_Struct_Literal);
sl->token = parser->curr;
expect_token(parser, '.');
expect_token(parser, '{');
- b32 is_named = ((parser->curr + 1)->type == '=');
+ b32 is_named = (peek_token(1)->type == '=');
OnyxToken* name = NULL;
while (parser->curr->type != '}') {
static b32 parse_possible_array_literal(OnyxParser* parser, AstTyped* left, AstTyped** ret) {
if (parser->curr->type != '.'
- || (parser->curr + 1)->type != '[') return 0;
+ || peek_token(1)->type != '[') return 0;
AstArrayLiteral* al = make_node(AstArrayLiteral, Ast_Kind_Array_Literal);
al->token = parser->curr;
AstIfWhile* root_if = if_node;
- if ((parser->curr + 1)->type == ':') {
- if_node->local = make_node(AstLocal, Ast_Kind_Local);
- if_node->local->token = expect_token(parser, Token_Type_Symbol);
+ if (peek_token(1)->type == ':') {
+ OnyxToken* local_sym = expect_token(parser, Token_Type_Symbol);
+ if_node->local = make_local(parser->allocator, local_sym, NULL);
expect_token(parser, ':');
AstIfWhile* while_node = make_node(AstIfWhile, Ast_Kind_While);
while_node->token = while_token;
- if ((parser->curr + 1)->type == ':') {
- while_node->local = make_node(AstLocal, Ast_Kind_Local);
- while_node->local->token = expect_token(parser, Token_Type_Symbol);
+ if (peek_token(1)->type == ':') {
+ OnyxToken* local_sym = expect_token(parser, Token_Type_Symbol);
+ while_node->local = make_local(parser->allocator, local_sym, NULL);
expect_token(parser, ':');
for_node->by_pointer = 1;
}
- AstLocal* var_node = make_node(AstLocal, Ast_Kind_Local);
- var_node->token = expect_token(parser, Token_Type_Symbol);
+ OnyxToken* local_sym = expect_token(parser, Token_Type_Symbol);
+ AstLocal* var_node = make_local(parser->allocator, local_sym, NULL);
for_node->var = var_node;
bh_arr_new(global_heap_allocator, switch_node->cases, 4);
- if ((parser->curr + 1)->type == ':') {
- switch_node->local = make_node(AstLocal, Ast_Kind_Local);
- switch_node->local->token = expect_token(parser, Token_Type_Symbol);
+ if (peek_token(1)->type == ':') {
+ OnyxToken* local_sym = expect_token(parser, Token_Type_Symbol);
+ switch_node->local = make_local(parser->allocator, local_sym, NULL);
expect_token(parser, ':');
return switch_node;
}
+static i32 parse_possible_compound_symbol_declaration(OnyxParser* parser, AstNode** ret) {
+ u32 token_offset = 0;
+ while (peek_token(token_offset)->type == Token_Type_Symbol) {
+ token_offset += 1;
+
+ if (peek_token(token_offset)->type != ',') break;
+ token_offset += 1;
+ }
+
+ if (peek_token(token_offset)->type != ':') return 0;
+
+ // At this point, we are sure it is a compound declaration.
+ AstCompound* local_compound = make_node(AstCompound, Ast_Kind_Compound);
+ bh_arr_new(global_heap_allocator, local_compound->exprs, token_offset / 2);
+
+ AstLocal* first_local = NULL;
+ AstLocal* prev_local = NULL;
+
+ while (parser->curr->type == Token_Type_Symbol) {
+ if (parser->hit_unexpected_token) return 1;
+
+ OnyxToken* local_sym = expect_token(parser, Token_Type_Symbol);
+ AstLocal* new_local = make_local(parser->allocator, local_sym, NULL);
+
+ if (prev_local == NULL) {
+ first_local = new_local;
+ } else {
+ prev_local->next = (AstNode *) new_local;
+ }
+ prev_local = new_local;
+
+ AstNode* sym_node = make_symbol(parser->allocator, local_sym);
+ bh_arr_push(local_compound->exprs, (AstTyped *) sym_node);
+
+ if (parser->curr->type == ',')
+ expect_token(parser, ',');
+ }
+
+ expect_token(parser, ':');
+
+ if (parser->curr->type == '=') {
+ AstBinaryOp* assignment = make_binary_op(parser->allocator, Binary_Op_Assign, (AstTyped *) local_compound, NULL);
+ assignment->token = expect_token(parser, '=');
+ assignment->right = parse_compound_expression(parser, 0);
+
+ prev_local->next = (AstNode *) assignment;
+
+ } else {
+ AstType* type_for_all = parse_type(parser);
+ bh_arr_each(AstTyped *, local, local_compound->exprs)
+ (*local)->type_node = type_for_all;
+ }
+
+ *ret = (AstNode *) first_local;
+ return 1;
+}
+
// Returns:
// 0 - if this was not a symbol declaration.
// 1 - if this was a local declaration.
// <symbol> : <type> : <expr>
// <symbol> := <expr>
// <symbol> :: <expr>
+// <symbol> (, <symbol>)* : <type>
+// <symbol> (, <symbol>)* := <expr>
static i32 parse_possible_symbol_declaration(OnyxParser* parser, AstNode** ret) {
+ // Has to start with a symbol to be a declaration
if (parser->curr->type != Token_Type_Symbol) return 0;
- if ((parser->curr + 1)->type != ':') return 0;
+
+ // If the token after the symbol is a comma, assume this is a compound declaration.
+ if (peek_token(1)->type == ',') {
+ return parse_possible_compound_symbol_declaration(parser, ret);
+ }
+
+ if (peek_token(1)->type != ':') return 0;
OnyxToken* symbol = expect_token(parser, Token_Type_Symbol);
expect_token(parser, ':');
type_node = parse_type(parser);
}
- AstLocal* local = make_node(AstLocal, Ast_Kind_Local);
- local->token = symbol;
- local->type_node = type_node;
+ AstLocal* local = make_local(parser->allocator, symbol, type_node);
*ret = (AstNode *) local;
if (parser->curr->type == '=') {
}
case Token_Type_Keyword_Use: {
- // AstUse* use_node = make_node(AstUse, Ast_Kind_Use);
- // use_node->token = expect_token(parser, Token_Type_Keyword_Use);
- // use_node->expr = parse_expression(parser);
-
needs_semicolon = 0;
+
retval = (AstNode *) parse_use_stmt(parser);
break;
}
case '#': {
if (parse_possible_directive(parser, "context_scope")) {
- AstLocal* context_tmp = make_node(AstLocal, Ast_Kind_Local);
- context_tmp->type_node = builtin_context_variable->type_node;
+ AstLocal* context_tmp = make_local(parser->allocator, NULL, builtin_context_variable->type_node);
AstBinaryOp* assignment = make_node(AstBinaryOp, Ast_Kind_Binary_Op);
assignment->operation = Binary_Op_Assign;
while (parser->curr->type != ')') {
if (parser->hit_unexpected_token) return root;
- if ((parser->curr + 1)->type == ':') {
+ if (peek_token(1)->type == ':') {
expect_token(parser, Token_Type_Symbol);
expect_token(parser, ':');
}
expect_token(parser, ':');
curr_param.vararg_kind = VA_Kind_Not_VA;
- curr_param.local = make_node(AstLocal, Ast_Kind_Param);
- curr_param.local->token = symbol;
+ curr_param.local = make_local(parser->allocator, symbol, NULL);
+ curr_param.local->kind = Ast_Kind_Param;
if (param_use) {
curr_param.local->flags |= Ast_Flag_Param_Use;