Example #1
0
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;
}
Example #2
0
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;
}
Example #3
0
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;
}
Example #4
0
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;
}
Example #5
0
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;
}