#include "ctx.h" #include static bool parse_block_params( struct ivy_parser *parser, struct ivy_ast_block_node *block) { while (1) { if (parse_symbol(parser, IVY_SYM_PIPE)) { break; } if (!parse_symbol(parser, IVY_SYM_COLON)) { parse_trace( parser, "expected `|`, or `:` followed by parameter " "name"); return false; } struct ivy_token *ident = NULL; if (!parse_word(parser, &ident)) { parse_trace( parser, "expected parameter identifier after `:`"); return false; } struct ivy_ast_ident_node *ident_node = create_node(IVY_AST_IDENT); ident_node->n_content = ident; fx_queue_push_back(&block->n_arg, &ident_node->n_base.n_entry); } return true; } bool parse_block(struct ivy_parser *parser, struct ivy_ast_node **out) { if (!parse_symbol(parser, IVY_SYM_LEFT_BRACKET)) { parse_trace(parser, "expected `[` before block contents"); return false; } struct ivy_ast_block_node *block = create_node(IVY_AST_BLOCK); if (!block) { parser->p_status = IVY_ERR_NO_MEMORY; return false; } bool result = true; if (peek_symbol(parser, IVY_SYM_COLON)) { result = parse_block_params(parser, block); } if (!result) { parse_trace(parser, "invalid block parameter list"); return false; } bool prev_was_expr = false; while (1) { struct ivy_ast_node *child = NULL; if (parse_linefeed(parser)) { continue; } if (parse_symbol(parser, IVY_SYM_RIGHT_BRACKET)) { break; } if (prev_was_expr) { if (!parse_symbol(parser, IVY_SYM_DOT)) { parse_trace( parser, "expected `.` after expression"); result = false; break; } prev_was_expr = false; continue; } if (peek_expr_start(parser)) { result = parse_expr(parser, EXPR_PARSE_NORMAL, &child); prev_was_expr = true; } else { parse_trace(parser, "expected `]` or expression"); result = false; } if (!result || !child) { break; } fx_queue_push_back(&block->n_expr, &child->n_entry); } *out = generic_node(block); return result; }