static struct ast_node *ast_parser_acc_return_statement(struct ast_parser *p) { struct token *tok; struct ast_node *expr; struct ast_node *n = NULL; const struct inplocation_mark *start; tok = lexer_lookahead(parser_lexer(p), 1); if (!tok) { return NULL; } if (tok->type != TOKEN_KW_RETURN) { return NULL; } start = token_get_start(tok); //consume the return keyword lexer_curr_token_advance(parser_lexer(p)); expr = ast_parser_acc_expression(p); if (!expr) { parser_synerr(p, lexer_last_token_end(parser_lexer(p)), NULL, "Expected an expression for the return statement"); goto end; } n = ast_returnstmt_create(start, ast_node_endmark(expr), expr); if (!n) { RF_ERROR("Could not create a return statement during parsing"); } end: return n; }
struct ast_node *ast_parser_acc_block(struct ast_parser *p, bool expect_braces) { struct ast_node *n; struct token *tok; struct ast_node *element; const struct inplocation_mark *start = NULL; const struct inplocation_mark *end = NULL; lexer_push(parser_lexer(p)); tok = lexer_lookahead(parser_lexer(p), 1); if (!tok) { goto err; } if (expect_braces) { if (tok->type != TOKEN_SM_OCBRACE) { goto err; } // consume '{' lexer_curr_token_advance(parser_lexer(p)); start = token_get_start(tok); } if (!(n = ast_block_create())) { goto err; } //try to parse the first element if (!(element = ast_parser_acc_block_element(p))) { if (!expect_braces) { goto err_free_block; } //else just find the terminating '}' and return tok = lexer_lookahead(parser_lexer(p), 1); if (!tok || tok->type != TOKEN_SM_CCBRACE) { parser_synerr( p, lexer_last_token_end(parser_lexer(p)), NULL, "Expected an expression or a '}' at block end" ); goto err_free_block; } //consume the '}' lexer_curr_token_advance(parser_lexer(p)); ast_node_set_start(n, start); ast_node_set_end(n, token_get_end(tok)); return n; //empty block } if (!start) { start = ast_node_startmark(element); } end = ast_node_endmark(element); ast_block_add_element(n, element); // now add elements to the block while ((element = ast_parser_acc_block_element(p))) { ast_block_add_element(n, element); end = ast_node_endmark(element); } if (expect_braces) { tok = lexer_lookahead(parser_lexer(p), 1); if (!tok || tok->type != TOKEN_SM_CCBRACE) { parser_synerr( p, lexer_last_token_end(parser_lexer(p)), NULL, "Expected an expression or a '}' at block end" ); goto err_free_block; } //consume the '}' lexer_curr_token_advance(parser_lexer(p)); end = token_get_end(tok); } ast_node_set_start(n, start); ast_node_set_end(n, end); lexer_pop(parser_lexer(p)); return n; err_free_block: ast_node_destroy(n); err: lexer_rollback(parser_lexer(p)); return NULL; }
struct ast_node *parser_acc_fndecl(struct parser *p, int fndecl_position) { struct ast_node *n; struct token *tok; struct token *oparen_tok; struct ast_node *name; struct ast_node *genr = NULL; struct ast_node *args = NULL; struct ast_node *ret_type = NULL; const struct inplocation_mark *start; const struct inplocation_mark *end; lexer_push(p->lexer); tok = lexer_lookahead(p->lexer, 1); if (fndecl_position != FNDECL_PARTOF_FOREIGN_IMPORT) { if (!tok || tok->type != TOKEN_KW_FUNCTION) { goto err; } //consume function keyword lexer_next_token(p->lexer); } // start should be either start of fn, or start of next token (an identifier) start = token_get_start(tok); name = parser_acc_identifier(p); if (!name) { parser_synerr(p, lexer_last_token_start(p->lexer), NULL, "Expected an identifier for the function name after 'fn'"); goto err; } tok = lexer_lookahead(p->lexer, 1); if (GENRDECL_START_COND(tok)) { genr = parser_acc_genrdecl(p); if (!genr) { goto err; } } tok = lexer_next_token(p->lexer); if (!tok || tok->type != TOKEN_SM_OPAREN) { parser_synerr(p, lexer_last_token_start(p->lexer), NULL, "Expected '(' at function declaration"); goto err_free_genr; } oparen_tok = tok; args = parser_acc_typedesc(p); if (!args && parser_has_syntax_error_reset(p)) { parser_synerr(p, token_get_end(tok), NULL, "Expected either a type description for the function's " "arguments or ')' after '('"); goto err_free_genr; } tok = lexer_next_token(p->lexer); if (!tok || tok->type != TOKEN_SM_CPAREN) { if (args) { parser_synerr(p, lexer_last_token_end(p->lexer), NULL, "Expected ')' at function declaration after " "type description"); } else { parser_synerr(p, token_get_end(oparen_tok), NULL, "Expected ')' at function declaration after '('"); } goto err_free_args; } end = token_get_end(tok); tok = lexer_lookahead(p->lexer, 1); if (tok && tok->type == TOKEN_OP_IMPL) { //consume '->' lexer_next_token(p->lexer); ret_type = parser_acc_typedesc(p); if (!ret_type) { parser_synerr(p, token_get_end(tok), NULL, "Expected type description for the function's " "return type after '->'"); goto err_free_args; } end = ast_node_endmark(ret_type); } n = ast_fndecl_create(start, end, fndecl_position, name, genr, args, ret_type); if (!n) { RF_ERRNOMEM(); goto err_free_rettype; } lexer_pop(p->lexer); return n; err_free_rettype: if (ret_type) { ast_node_destroy(ret_type); } err_free_args: if (args) { ast_node_destroy(args); } err_free_genr: if (genr) { ast_node_destroy(genr); } err: lexer_rollback(p->lexer); return NULL; }
struct ast_node *parser_acc_typeinstance(struct parser *p) { struct ast_node *n = NULL; struct token *tok; struct ast_node *class_name; struct ast_node *type_name; struct ast_node *genr = NULL; const struct inplocation_mark *start; enum parser_fnimpl_list_err err; tok = lexer_lookahead(p->lexer, 1); if (!tok || tok->type != TOKEN_KW_TYPEINSTANCE) { return NULL; } start = token_get_start(tok); //consumer typeclass isntance keyword lexer_next_token(p->lexer); class_name = parser_acc_identifier(p); if (!class_name) { parser_synerr(p, lexer_last_token_start(p->lexer), NULL, "Expected an identifier for the typeclass instance " "name after 'instance'"); goto err; } type_name = parser_acc_identifier(p); if (!type_name) { parser_synerr(p, lexer_last_token_start(p->lexer), NULL, "Expected an identifier for the name of \""RF_STR_PF_FMT"\" " "typeclass instance", RF_STR_PF_ARG(ast_identifier_str(class_name))); goto err; } genr = parser_acc_genrdecl(p); if (!genr && parser_has_syntax_error_reset(p)) { parser_synerr(p, ast_node_endmark(type_name), NULL, "Expected a generic declaration for type instance \"" RF_STR_PF_FMT"\" after type name \""RF_STR_PF_FMT"\"", RF_STR_PF_ARG(ast_identifier_str(class_name)), RF_STR_PF_ARG(ast_identifier_str(type_name))); goto err; } tok = lexer_next_token(p->lexer); if (!tok || tok->type != TOKEN_SM_OCBRACE) { parser_synerr(p, ast_node_endmark(type_name), NULL, "Expected '{' at type instance \""RF_STR_PF_FMT"\" " "after \""RF_STR_PF_FMT"\"", RF_STR_PF_ARG(ast_identifier_str(class_name)), RF_STR_PF_ARG(ast_identifier_str(type_name))); goto err_free_genr; } n = ast_typeinstance_create(start, NULL, class_name, type_name, genr); if (!n) { RF_ERRNOMEM(); goto err_free_genr; } err = parser_acc_fnimpl_list(p, n); switch (err) { case PARSER_FNIMPL_LIST_EMPTY: parser_synerr(p, token_get_end(tok), NULL, "Expected at least one function implementation inside " "the body of typeinstace \""RF_STR_PF_FMT"\" for " "\""RF_STR_PF_FMT"\" after'{'", RF_STR_PF_ARG(ast_identifier_str(class_name)), RF_STR_PF_ARG(ast_identifier_str(type_name))); goto err_free_typeinstance; break; case PARSER_FNIMPL_LIST_FAILURE: parser_synerr(p, lexer_last_token_end(p->lexer), NULL, "Expected a proper function implementation inside " "the body of typeinstace \""RF_STR_PF_FMT"\" for " "\""RF_STR_PF_FMT"\" after'{'", RF_STR_PF_ARG(ast_identifier_str(class_name)), RF_STR_PF_ARG(ast_identifier_str(type_name))); goto err_free_typeinstance; break; default: // SUCCESS break; } tok = lexer_next_token(p->lexer); if (!tok || tok->type != TOKEN_SM_CCBRACE) { parser_synerr(p, lexer_last_token_end(p->lexer), NULL, "Expected '}' at the end of \""RF_STR_PF_FMT"\" " "typeinstance for \""RF_STR_PF_FMT"\"", RF_STR_PF_ARG(ast_identifier_str(class_name)), RF_STR_PF_ARG(ast_identifier_str(type_name))); goto err_free_typeinstance; } ast_node_set_end(n, token_get_end(tok)); return n; err_free_genr: if (genr) { ast_node_destroy(genr); } err_free_typeinstance: if (n) { ast_node_destroy(n); } err: return NULL; }
struct ast_node *parser_acc_typeclass(struct parser *p) { struct ast_node *n = NULL; struct token *tok; struct ast_node *name; struct ast_node *genr = NULL; const struct inplocation_mark *start; enum parser_fndecl_list_err err; tok = lexer_lookahead(p->lexer, 1); if (!tok || tok->type != TOKEN_KW_TYPECLASS) { return NULL; } start = token_get_start(tok); lexer_push(p->lexer); //consume typeclass keyword lexer_next_token(p->lexer); name = parser_acc_identifier(p); if (!name) { parser_synerr(p, lexer_last_token_start(p->lexer), NULL, "Expected an identifier for the typeclass " "name after 'class'"); goto err; } genr = parser_acc_genrdecl(p); if (!genr && parser_has_syntax_error_reset(p)) { parser_synerr(p, ast_node_endmark(name), NULL, "Expected a generic declaration for typeclass \"" RF_STR_PF_FMT"\" after identifier", RF_STR_PF_ARG(ast_identifier_str(name))); goto err_free_genr; } tok = lexer_next_token(p->lexer); if (!tok || tok->type != TOKEN_SM_OCBRACE) { parser_synerr(p, ast_node_endmark(name), NULL, "Expected '{' at \""RF_STR_PF_FMT"\" typeclass " "declaration after identifier", RF_STR_PF_ARG(ast_identifier_str(name))); goto err_free_genr; } n = ast_typeclass_create(start, NULL, name, genr); if (!n) { RF_ERRNOMEM(); goto err_free_genr; } err = parser_acc_fndecl_list(p, n, FNDECL_PARTOF_TYPECLASS); switch (err) { case PARSER_FNDECL_LIST_EMPTY: parser_synerr(p, token_get_end(tok), NULL, "Expected at least one function declaration inside " "the body of typeclass \""RF_STR_PF_FMT"\" after '{'", RF_STR_PF_ARG(ast_identifier_str(name))); goto err_free_typeclass; break; case PARSER_FNDECL_LIST_FAILURE: parser_synerr(p, lexer_last_token_end(p->lexer), NULL, "Expected a proper function declaration inside " "typeclass \""RF_STR_PF_FMT"\"", RF_STR_PF_ARG(ast_identifier_str(name))); goto err_free_typeclass; break; default: // SUCCESS break; } tok = lexer_next_token(p->lexer); if (!tok || tok->type != TOKEN_SM_CCBRACE) { parser_synerr(p, lexer_last_token_end(p->lexer), NULL, "Expected '}' at the end of \""RF_STR_PF_FMT"\" " "typeclass declaration", RF_STR_PF_ARG(ast_identifier_str(name))); goto err_free_typeclass; } ast_node_set_end(n, token_get_end(tok)); lexer_pop(p->lexer); return n; err_free_genr: if (genr) { ast_node_destroy(genr); } err_free_typeclass: if (n) { ast_node_destroy(n); } err: lexer_rollback(p->lexer); return NULL; }
struct ast_node *parser_acc_ifexpr(struct parser *p, enum token_type if_type) { struct ast_node *n; struct ast_node *branch; struct token *tok; const struct inplocation_mark *start; RF_ASSERT(if_type == TOKEN_KW_IF || if_type == TOKEN_KW_ELIF, "parse_ifexp called with invalid token type"); tok = lexer_lookahead(p->lexer, 1); if (!tok || tok->type != if_type) { return NULL; } start = token_get_start(tok); // consume 'if' or 'elif' lexer_next_token(p->lexer); lexer_push(p->lexer); // parse the taken branch branch = parser_acc_condbranch(p, tok); if (!branch) { goto err; } // create the if expression n = ast_ifexpr_create(start, ast_node_endmark(branch), branch, NULL); if (!n) { ast_node_destroy(branch); RF_ERRNOMEM(); goto err; } tok = lexer_lookahead(p->lexer, 1); while (tok && (tok->type == TOKEN_KW_ELIF || tok->type == TOKEN_KW_ELSE)) { if (tok->type == TOKEN_KW_ELIF) { branch = parser_acc_ifexpr(p, TOKEN_KW_ELIF); if (!branch) { // error reporting should already happen in parser_acc_ifexpr() goto err_free; } } else { //can only be an else lexer_next_token(p->lexer); // consume it branch = parser_acc_block(p, true); if (!branch) { parser_synerr(p, token_get_end(tok), NULL, "Expected a block after 'else'"); goto err_free; } } ast_ifexpr_add_fallthrough_branch(n, branch); ast_node_set_end(n, ast_node_endmark(branch)); tok = lexer_lookahead(p->lexer, 1); } lexer_pop(p->lexer); return n; err_free: ast_node_destroy(n); err: lexer_rollback(p->lexer); return NULL; }