Esempio n. 1
0
static void
parse_next_action(struct action_context *ctx)
{
    if (!ctx->n_tables) {
        action_error(ctx, "\"next\" action not allowed here.");
    } else if (lexer_match(ctx->lexer, LEX_T_LPAREN)) {
        int ltable;

        if (!action_get_int(ctx, &ltable)) {
            return;
        }
        if (!lexer_match(ctx->lexer, LEX_T_RPAREN)) {
            action_syntax_error(ctx, "expecting `)'");
            return;
        }

        if (ltable >= ctx->n_tables) {
            action_error(ctx, "\"next\" argument must be in range 0 to %d.",
                         ctx->n_tables - 1);
            return;
        }

        emit_resubmit(ctx, ctx->first_ptable + ltable);
    } else {
        if (ctx->cur_ltable < ctx->n_tables) {
            emit_resubmit(ctx, ctx->first_ptable + ctx->cur_ltable + 1);
        } else {
            action_error(ctx, "\"next\" action not allowed in last table.");
        }
    }
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
        }
    }
}
Esempio n. 4
0
struct node *parse_main(struct compiler *compiler)
{
    struct block *block;

    struct node *result = alloc_scope(compiler, &block, S_MAIN);

    block->owner = block;

    result->right = parse_statements(compiler);

    lexer_match(compiler, T_EOF);

    return result;
}
Esempio n. 5
0
struct node *parse_factor(struct compiler *compiler)
{
    switch (lexer_current(compiler))
    {
    case T_BEGIN:
        return parse_begin(compiler);

    case T_IF:
        return parse_if(compiler);

    case T_UNLESS:
        return parse_unless(compiler);

    case T_CASE:
        return parse_case(compiler);

    case T_CLASS:
        return parse_class(compiler);

    case T_MODULE:
        return parse_module(compiler);

    case T_DEF:
        return parse_method(compiler);

    case T_YIELD:
        return parse_yield(compiler);

    case T_RETURN:
        return parse_return(compiler);

    case T_BREAK:
        return parse_break(compiler);

    case T_NEXT:
        return parse_next(compiler);

    case T_REDO:
        return parse_redo(compiler);

    case T_SQUARE_OPEN:
    {
        struct node *result = alloc_node(compiler, N_ARRAY);

        lexer_next(compiler);

        if(lexer_current(compiler) == T_SQUARE_CLOSE)
            result->left  = 0;
        else
            result->left = parse_array_element(compiler);

        lexer_match(compiler, T_SQUARE_CLOSE);

        return result;
    }

    case T_STRING:
    {
        struct node *result = alloc_node(compiler, N_STRING);

        result->left = (void *)lexer_token(compiler)->start;

        lexer_next(compiler);

        return result;
    }

    case T_STRING_START:
    {
        struct node *result = alloc_node(compiler, N_STRING_CONTINUE);

        result->left = 0;
        result->middle = (void *)lexer_token(compiler)->start;

        lexer_next(compiler);

        result->right = parse_statements(compiler);

        while(lexer_current(compiler) == T_STRING_CONTINUE)
        {
            struct node *node = alloc_node(compiler, N_STRING_CONTINUE);

            node->left = result;
            node->middle = (void *)lexer_token(compiler)->start;

            lexer_next(compiler);

            node->right = parse_statements(compiler);

            result = node;
        }

        if(lexer_require(compiler, T_STRING_END))
        {
            struct node *node = alloc_node(compiler, N_STRING_START);

            node->left = result;
            node->right = (void *)lexer_token(compiler)->start;

            lexer_next(compiler);

            return node;
        }

        return result;
    }

    case T_SELF:
    {
        lexer_next(compiler);

        return &self_node;
    }

    case T_TRUE:
    {
        lexer_next(compiler);

        return alloc_node(compiler, N_TRUE);
    }

    case T_FALSE:
    {
        lexer_next(compiler);

        return alloc_node(compiler, N_FALSE);
    }

    case T_NIL:
    {
        lexer_next(compiler);

        return &nil_node;
    }

    case T_NUMBER:
    {
        struct node *result = alloc_node(compiler, N_NUMBER);

        char *text = get_token_str(lexer_token(compiler));

        result->left = (void* )atoi(text);

        lexer_next(compiler);

        return result;
    }

    case T_IVAR:
    {
        rt_value symbol = rt_symbol_from_lexer(compiler);

        lexer_next(compiler);

        switch (lexer_current(compiler))
        {
        case T_ASSIGN_ADD:
        case T_ASSIGN_SUB:
        case T_ASSIGN_MUL:
        case T_ASSIGN_DIV:
        {
            struct node *result;

            enum token_type op_type = lexer_current(compiler) - OP_TO_ASSIGN;

            lexer_next(compiler);

            result = alloc_node(compiler, N_IVAR_ASSIGN);

            result->right = alloc_node(compiler, N_BINARY_OP);
            result->right->op = op_type;
            result->right->left = alloc_node(compiler, N_IVAR);
            result->right->left->left = (void *)symbol;
            result->right->right = parse_expression(compiler);

            result->left = (void *)symbol;

            return result;
        }

        case T_ASSIGN:
        {
            struct node *result;

            lexer_next(compiler);

            result = alloc_node(compiler, N_IVAR_ASSIGN);
            result->left = (void *)symbol;
            result->right = parse_expression(compiler);

            return result;
        }

        default:
        {
            struct node *result = alloc_node(compiler, N_IVAR);

            result->left = (void *)symbol;

            return result;
        }
        }
    }

    case T_IDENT:
        return parse_identifier(compiler);

    case T_EXT_IDENT:
        return parse_call(compiler, 0, &self_node, false);

    case T_PARAM_OPEN:
    {
        lexer_next(compiler);

        struct node *result = parse_statements(compiler);

        lexer_match(compiler, T_PARAM_CLOSE);

        return result;
    }

    default:
    {
        COMPILER_ERROR(compiler, "Expected expression but found %s", token_type_names[lexer_current(compiler)]);

        lexer_next(compiler);

        return 0;
    }
    }
}