コード例 #1
0
ファイル: lexer.c プロジェクト: whoverse/libwholex
bool lexer_lookahead_matches_special(lexer_state_t* lex, const char* special) {
    if ( lex->error || lexer_lookahead(lex) == NULL ) return NULL;

    token_t* token = lexer_lookahead(lex);

    if ( token->type == special_token ) {
        return strcmp((char*) token->value, special) == 0;
    }

    return false;
}
コード例 #2
0
ファイル: actions.c プロジェクト: HaochuanXJTU/ovs
static void
parse_actions(struct action_context *ctx)
{
    /* "drop;" by itself is a valid (empty) set of actions, but it can't be
     * combined with other actions because that doesn't make sense. */
    if (ctx->lexer->token.type == LEX_T_ID
        && !strcmp(ctx->lexer->token.s, "drop")
        && lexer_lookahead(ctx->lexer) == LEX_T_SEMICOLON) {
        lexer_get(ctx->lexer);  /* Skip "drop". */
        lexer_get(ctx->lexer);  /* Skip ";". */
        if (ctx->lexer->token.type != LEX_T_END) {
            action_syntax_error(ctx, "expecting end of input");
        }
        return;
    }

    while (ctx->lexer->token.type != LEX_T_END) {
        if (ctx->lexer->token.type != LEX_T_ID) {
            action_syntax_error(ctx, NULL);
            break;
        }

        enum lex_type lookahead = lexer_lookahead(ctx->lexer);
        if (lookahead == LEX_T_EQUALS || lookahead == LEX_T_EXCHANGE
            || lookahead == LEX_T_LSQUARE) {
            parse_set_action(ctx);
        } else if (lexer_match_id(ctx->lexer, "next")) {
            parse_next_action(ctx);
        } else if (lexer_match_id(ctx->lexer, "output")) {
            emit_resubmit(ctx, ctx->output_ptable);
        } else if (lexer_match_id(ctx->lexer, "ip4.ttl")) {
            if (lexer_match(ctx->lexer, LEX_T_DECREMENT)) {
                struct expr *e = expr_parse_string("ip4", ctx->symtab,
                                                   &ctx->error);
                ctx->prereqs = expr_combine(EXPR_T_AND, ctx->prereqs, e);
                ofpact_put_DEC_TTL(ctx->ofpacts);
            } else {
                action_syntax_error(ctx, "expecting `--'");
            }
        } else if (lexer_match_id(ctx->lexer, "ct_next")) {
            emit_ct(ctx, true, false);
        } else if (lexer_match_id(ctx->lexer, "ct_commit")) {
            emit_ct(ctx, false, true);
        } else {
            action_syntax_error(ctx, "expecting action");
        }
        if (!lexer_match(ctx->lexer, LEX_T_SEMICOLON)) {
            action_syntax_error(ctx, "expecting ';'");
        }
        if (ctx->error) {
            return;
        }
    }
}
コード例 #3
0
ファイル: actions.c プロジェクト: AlexanderFroemmgen/ovs
static bool
parse_action(struct action_context *ctx)
{
    if (ctx->lexer->token.type != LEX_T_ID) {
        action_syntax_error(ctx, NULL);
        return false;
    }

    enum lex_type lookahead = lexer_lookahead(ctx->lexer);
    if (lookahead == LEX_T_EQUALS || lookahead == LEX_T_EXCHANGE
        || lookahead == LEX_T_LSQUARE) {
        parse_set_action(ctx);
    } else if (lexer_match_id(ctx->lexer, "next")) {
        parse_next_action(ctx);
    } else if (lexer_match_id(ctx->lexer, "output")) {
        emit_resubmit(ctx, ctx->ap->output_ptable);
    } else if (lexer_match_id(ctx->lexer, "ip.ttl")) {
        if (lexer_match(ctx->lexer, LEX_T_DECREMENT)) {
            add_prerequisite(ctx, "ip");
            ofpact_put_DEC_TTL(ctx->ofpacts);
        } else {
            action_syntax_error(ctx, "expecting `--'");
        }
    } else if (lexer_match_id(ctx->lexer, "ct_next")) {
        emit_ct(ctx, true, false);
    } else if (lexer_match_id(ctx->lexer, "ct_commit")) {
        emit_ct(ctx, false, true);
    } else {
        action_syntax_error(ctx, "expecting action");
    }
    if (!lexer_match(ctx->lexer, LEX_T_SEMICOLON)) {
        action_syntax_error(ctx, "expecting ';'");
    }
    return !ctx->error;
}
コード例 #4
0
ファイル: block.c プロジェクト: refu-lang/refu
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;
}
コード例 #5
0
ファイル: function.c プロジェクト: pirapira/refulangcore
struct ast_node *parser_acc_fnimpl(struct parser *p)
{
    struct ast_node *n;
    struct ast_node *decl;
    struct ast_node *body;
    struct token *tok;

    decl = parser_acc_fndecl(p, FNDECL_PARTOF_IMPL);
    if (!decl) {
        return NULL;
    }    
    tok = lexer_lookahead(p->lexer, 1);
    if (!tok) {
        goto fail_free_decl;
    }

    if (tok->type == TOKEN_SM_OCBRACE) {
        // normal function body
        body = parser_acc_block(p, true);
        if (!body) {
            parser_synerr(p, ast_node_endmark(decl), NULL,
                          "Expected a body for \""RF_STR_PF_FMT"\" function "
                          "implementation", RF_STR_PF_ARG(ast_fndecl_name_str(decl)));
            goto fail_free_decl;
        }
    } else {
        // attempt to find a headless match expression as the function body
        body = parser_acc_matchexpr(p, false, true);
        if (!body) {
            parser_synerr(p, ast_node_endmark(decl), NULL,
                          "Expected a body for \""RF_STR_PF_FMT"\" function "
                          "implementation", RF_STR_PF_ARG(ast_fndecl_name_str(decl)));
            goto fail_free_decl;
        }
        // now set the matchexpr's fn_args since this is a headless matchexpr
        ast_matchexpr_set_fnargs(body, ast_fndecl_args_get(decl));
    }
        
    n = ast_fnimpl_create(ast_node_startmark(decl),
                          ast_node_endmark(body),
                          decl,
                          body);
    if (!n) {
        RF_ERRNOMEM();
        ast_node_destroy(body);
        ast_node_destroy(decl);
        return NULL;
    }
    return n;

fail_free_decl:
    ast_node_destroy(decl);
    return NULL;
}
コード例 #6
0
ファイル: function.c プロジェクト: pirapira/refulangcore
enum parser_fnimpl_list_err parser_acc_fnimpl_list(struct parser *p,
                                                   struct ast_node *parent)
{
   struct ast_node *impl;
   struct token *tok;
   tok = lexer_lookahead(p->lexer, 1);

   if (!tok || tok->type != TOKEN_KW_FUNCTION) {
       return PARSER_FNIMPL_LIST_EMPTY;
   }

   while (tok && tok->type == TOKEN_KW_FUNCTION) {
       impl = parser_acc_fnimpl(p);
       if (!impl) {
           return PARSER_FNIMPL_LIST_FAILURE;
       }
       ast_node_add_child(parent, impl);
       tok = lexer_lookahead(p->lexer, 1);
   }

   return PARSER_FNIMPL_LIST_SUCCESS;
}
コード例 #7
0
ファイル: function.c プロジェクト: pirapira/refulangcore
enum parser_fndecl_list_err parser_acc_fndecl_list(struct parser *p,
                                                   struct ast_node *parent,
                                                   int fndecl_position)
{
    struct ast_node *decl;
    struct token *tok;
    tok = lexer_lookahead(p->lexer, 1);

    if (!tok || tok->type != TOKEN_KW_FUNCTION) {
        return PARSER_FNDECL_LIST_EMPTY;
    }

    while (tok && tok->type == TOKEN_KW_FUNCTION) {
        decl = parser_acc_fndecl(p, fndecl_position);
        if (!decl) {
            return PARSER_FNDECL_LIST_FAILURE;
        }
        ast_node_add_child(parent, decl);
        tok = lexer_lookahead(p->lexer, 1);
    }

    return PARSER_FNDECL_LIST_SUCCESS;
}
コード例 #8
0
ファイル: block.c プロジェクト: refu-lang/refu
static struct ast_node *ast_parser_acc_expr_statement(struct ast_parser *p)
{
    struct token *tok;
    struct ast_node *n = NULL;

    tok = lexer_lookahead(parser_lexer(p), 1);

    if (TOKEN_IS_BLOCK_START(tok)) {
        n = ast_parser_acc_block(p, true);
    } else if (TOKEN_IS_TYPEDECL_START(tok)) {
        n = ast_parser_acc_typedecl(p);
    } else if (TOKEN_IS_RETURNSTMT_START(tok)) {
        n = ast_parser_acc_return_statement(p);
    }

    return n;
}
コード例 #9
0
ファイル: actions.c プロジェクト: AlexanderFroemmgen/ovs
static void
parse_actions(struct action_context *ctx)
{
    /* "drop;" by itself is a valid (empty) set of actions, but it can't be
     * combined with other actions because that doesn't make sense. */
    if (ctx->lexer->token.type == LEX_T_ID
        && !strcmp(ctx->lexer->token.s, "drop")
        && lexer_lookahead(ctx->lexer) == LEX_T_SEMICOLON) {
        lexer_get(ctx->lexer);  /* Skip "drop". */
        lexer_get(ctx->lexer);  /* Skip ";". */
        if (ctx->lexer->token.type != LEX_T_END) {
            action_syntax_error(ctx, "expecting end of input");
        }
        return;
    }

    while (ctx->lexer->token.type != LEX_T_END) {
        if (!parse_action(ctx)) {
            return;
        }
    }
}
コード例 #10
0
ファイル: lexer.c プロジェクト: whoverse/libwholex
bool lexer_lookahead_matches(lexer_state_t* lex, token_types_t tokentype) {
    if ( lex->error || lexer_lookahead(lex) == NULL ) return NULL;

    return lexer_lookahead(lex)->type == tokentype;
}
コード例 #11
0
ファイル: block.c プロジェクト: refu-lang/refu
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;
}
コード例 #12
0
ファイル: function.c プロジェクト: pirapira/refulangcore
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;
}
コード例 #13
0
ファイル: function.c プロジェクト: pirapira/refulangcore
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;
}
コード例 #14
0
ファイル: typeclass.c プロジェクト: pirapira/refulangcore
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;
}
コード例 #15
0
ファイル: typeclass.c プロジェクト: pirapira/refulangcore
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;
}
コード例 #16
0
ファイル: ifexpr.c プロジェクト: pirapira/refulangcore
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;
}