#include "../syntax.h" bool parse_func(struct bshell_parse_ctx *ctx, struct bshell_ast_node **out) { if (!parse_keyword(ctx, BSHELL_KW_FUNC)) { return false; } struct bshell_lex_token *name = NULL; if (!parse_word(ctx, &name)) { report_error(ctx, "expected function identifier"); return false; } struct bshell_func_ast_node *func = (struct bshell_func_ast_node *)bshell_ast_node_create( BSHELL_AST_FUNC); if (!func) { ctx->p_status = BSHELL_ERR_NO_MEMORY; bshell_lex_token_destroy(name); return false; } func->n_name = name; if (!parse_symbol(ctx, BSHELL_SYM_LEFT_PAREN)) { report_error(ctx, "expected `(` after function identifier"); bshell_ast_node_destroy((struct bshell_ast_node *)func); return false; } size_t nr_args = 0; bool ok = true; while (1) { if (parse_symbol(ctx, BSHELL_SYM_RIGHT_PAREN)) { break; } if (nr_args > 0 && !parse_symbol(ctx, BSHELL_SYM_COMMA)) { report_error( ctx, "expected `,` or `)` after parameter name"); ok = false; break; } struct bshell_lex_token *param_token = NULL; struct bshell_var_ast_node *param_node = NULL; if (!parse_var(ctx, ¶m_token)) { report_error(ctx, "expected parameter variable"); ok = false; break; } param_node = (struct bshell_var_ast_node *)bshell_ast_node_create( BSHELL_AST_VAR); if (!param_node) { ok = false; ctx->p_status = BSHELL_ERR_NO_MEMORY; bshell_lex_token_destroy(param_token); break; } param_node->n_ident = param_token; fx_queue_push_back( &func->n_params, ¶m_node->n_base.n_entry); } if (!ok) { if (ctx->p_status == BSHELL_SUCCESS) { ctx->p_status = BSHELL_ERR_BAD_SYNTAX; } bshell_ast_node_destroy((struct bshell_ast_node *)func); return false; } if (!parse_block(ctx, &func->n_body)) { report_error(ctx, "failed to parse function body"); bshell_ast_node_destroy((struct bshell_ast_node *)func); return false; } *out = (struct bshell_ast_node *)func; return true; }