struct rir_object *rir_parse_global(struct rir_parser *p, const struct RFstring *name) { struct token *tok = NULL; // consume 'global' if (!rir_parse_instr_start(p, rir_tokentype_to_str(RIR_TOK_GLOBAL))) { return NULL; } if (!(tok = lexer_expect_token(parser_lexer(p), RIR_TOK_IDENTIFIER))) { rirparser_synerr(p, lexer_last_token_start(parser_lexer(p)), NULL, "Expected a type identifier as first argument of 'global'."); return NULL; } struct ast_node *type_id = tok->value.value.ast; if (!lexer_expect_token(parser_lexer(p), RIR_TOK_SM_COMMA)) { rirparser_synerr(p, lexer_last_token_start(parser_lexer(p)), NULL, "Expected a ',' after the first argument of 'global'."); return NULL; } if (!(tok = lexer_expect_token(parser_lexer(p), RIR_TOK_STRING_LITERAL))) { rirparser_synerr(p, lexer_last_token_start(parser_lexer(p)), NULL, "Expected a string literal as second argument of 'global'."); return NULL; } struct ast_node *string_lit = tok->value.value.ast; // create and add it to the global literals struct rir_object *ret = rir_global_create_parsed(p, name, type_id, string_lit); if (!ret) { return NULL; } // consume the last parentheses if (!lexer_expect_token(parser_lexer(p), RIR_TOK_SM_CPAREN)) { rirparser_synerr(p, lexer_last_token_start(parser_lexer(p)), NULL, "Expected a closing ')' at the end of 'global'."); return NULL; } return ret; }
struct ast_node *parser_acc_fncall(struct parser *p, bool expect_it) { struct ast_node *n; struct token *tok; struct ast_node *name; struct ast_node *genr = NULL; struct ast_node *args = NULL; lexer_push(p->lexer); name = parser_acc_identifier(p); if (!name) { goto err; } genr = parser_acc_genrattr(p, false); if (!genr && parser_has_syntax_error(p)) { // name is an identifier and even in failure does not need to get destroyed here goto err; } tok = lexer_lookahead(p->lexer, 1); if (!tok || tok->type != TOKEN_SM_OPAREN) { if (expect_it) { parser_synerr(p, lexer_last_token_start(p->lexer), NULL, "Expected '('"); } goto err_free_genr; } //consume '(' lexer_next_token(p->lexer); args = parser_acc_expression(p); if (!args) { if (parser_has_syntax_error(p)) { parser_synerr(p, lexer_last_token_start(p->lexer), NULL, "Expected argument expression for function call"); goto err_free_genr; } } tok = lexer_lookahead(p->lexer, 1); if (!tok || tok->type != TOKEN_SM_CPAREN) { if (expect_it) { parser_synerr(p, lexer_last_token_end(p->lexer), NULL, "Expected ')' at end of "RF_STR_PF_FMT" function call", RF_STR_PF_ARG(ast_identifier_str(name))); } goto err_free_args; } //consume ')' lexer_next_token(p->lexer); n = ast_fncall_create(ast_node_startmark(name), token_get_end(tok), name, args, genr); if (!n) { RF_ERRNOMEM(); goto err_free_args; } lexer_pop(p->lexer); return n; 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_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_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; }