susumu.yata
null+****@clear*****
Wed Oct 7 12:42:06 JST 2015
susumu.yata 2015-10-07 12:42:06 +0900 (Wed, 07 Oct 2015) New Revision: 81aadf4ca40d58b5eac70ac955b431c11f8faef4 https://github.com/groonga/groonga/commit/81aadf4ca40d58b5eac70ac955b431c11f8faef4 Message: grn_ts: add error messages for grn_ts_expr_parser GitHub: #412 Modified files: lib/ts.c Modified: lib/ts.c (+78 -44) =================================================================== --- lib/ts.c 2015-10-07 11:52:03 +0900 (0c5781f) +++ lib/ts.c 2015-10-07 12:42:06 +0900 (52a44ae) @@ -5105,6 +5105,7 @@ grn_ts_expr_parser_tokenize_op(grn_ctx *ctx, grn_ts_expr_parser *parser, grn_ts_expr_op_token *new_token; switch (str.ptr[0]) { case '+': case '-': { + // FIXME: Suppress a warning. rc = grn_ts_expr_parser_tokenize_sign(ctx, parser, str, &new_token); break; } @@ -5308,69 +5309,99 @@ grn_ts_expr_parser_push_op(grn_ctx *ctx, grn_ts_expr_parser *parser, return grn_ts_expr_push_op(ctx, parser->expr, token->op_type); } -/* grn_ts_expr_parser_apply() applies bridges and prior operators. */ +/* + * grn_ts_expr_parser_apply_one() applies a bridge or prior operator. + * If there is no target, this function returns GRN_END_OF_DATA. + */ +// FIXME: Support a ternary operator. static grn_rc -grn_ts_expr_parser_apply(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_op_precedence precedence_threshold) { - grn_rc rc = GRN_SUCCESS; +grn_ts_expr_parser_apply_one(grn_ctx *ctx, grn_ts_expr_parser *parser, + grn_ts_op_precedence precedence_threshold) { + grn_rc rc; + grn_ts_str src; grn_ts_expr_token **stack = parser->stack; - size_t depth = parser->stack_depth; - while (depth >= 2) { - size_t n_args; - grn_ts_str src; - grn_ts_expr_dummy_token *dummy_token; - if (stack[depth - 1]->type != GRN_TS_EXPR_DUMMY_TOKEN) { - rc = GRN_INVALID_ARGUMENT; - break; - } + grn_ts_expr_dummy_token *dummy_token; + size_t n_args, depth = parser->stack_depth; + if (depth < 2) { + return GRN_END_OF_DATA; + } + if (stack[depth - 1]->type != GRN_TS_EXPR_DUMMY_TOKEN) { + GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "argument must be dummy token"); + } - /* Check the number of arguments. */ - if (stack[depth - 2]->type == GRN_TS_EXPR_BRIDGE_TOKEN) { - n_args = 2; + /* Check the number of arguments. */ + switch (stack[depth - 2]->type) { + case GRN_TS_EXPR_BRIDGE_TOKEN: { rc = grn_ts_expr_end_subexpr(ctx, parser->expr); if (rc != GRN_SUCCESS) { - break; + return rc; } - } else if (stack[depth - 2]->type == GRN_TS_EXPR_OP_TOKEN) { + n_args = 2; + break; + } + case GRN_TS_EXPR_OP_TOKEN: { grn_ts_expr_op_token *op_token; grn_ts_op_precedence precedence; op_token = (grn_ts_expr_op_token *)stack[depth - 2]; precedence = grn_ts_op_get_precedence(op_token->op_type); if (precedence < precedence_threshold) { - break; + return GRN_END_OF_DATA; } rc = grn_ts_expr_parser_push_op(ctx, parser, op_token); if (rc != GRN_SUCCESS) { - break; + return rc; } n_args = grn_ts_op_get_n_args(op_token->op_type); - } else { break; } + default: { + return GRN_END_OF_DATA; + } + } - /* Concatenate the source strings. */ - if (n_args == 1) { + /* Concatenate the source strings. */ + switch (n_args) { + case 1: { grn_ts_expr_token *arg = stack[depth - 1]; src.ptr = stack[depth - 2]->src.ptr; src.size = (arg->src.ptr + arg->src.size) - src.ptr; - } else if (n_args == 2) { + break; + } + case 2: { grn_ts_expr_token *args[2] = { stack[depth - 3], stack[depth - 1] }; src.ptr = args[0]->src.ptr; src.size = (args[1]->src.ptr + args[1]->src.size) - src.ptr; - } else { - rc = GRN_UNKNOWN_ERROR; break; } - - /* Replace the operator and argument tokens with a dummy token. */ - dummy_token = &parser->dummy_tokens[parser->n_dummy_tokens++]; - GRN_TS_DEBUG("dummy token: \"%.*s\"", (int)src.size, src.ptr); - grn_ts_expr_dummy_token_init(ctx, dummy_token, src); - depth -= n_args + 1; - stack[depth++] = dummy_token; + default: { + GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, + "invalid number of arguments: %zu", n_args); + } } + + /* Replace the operator and argument tokens with a dummy token. */ + dummy_token = &parser->dummy_tokens[parser->n_dummy_tokens++]; + GRN_TS_DEBUG("dummy token: \"%.*s\"", (int)src.size, src.ptr); + grn_ts_expr_dummy_token_init(ctx, dummy_token, src); + depth -= n_args + 1; + stack[depth++] = dummy_token; parser->stack_depth = depth; - return rc; + return GRN_SUCCESS; +} + +/* grn_ts_expr_parser_apply() applies bridges and prior operators. */ +static grn_rc +grn_ts_expr_parser_apply(grn_ctx *ctx, grn_ts_expr_parser *parser, + grn_ts_op_precedence precedence_threshold) { + for ( ; ; ) { + grn_rc rc = grn_ts_expr_parser_apply_one(ctx, parser, + precedence_threshold); + if (rc == GRN_END_OF_DATA) { + return GRN_SUCCESS; + } else if (rc != GRN_SUCCESS) { + return rc; + } + } } /* grn_ts_expr_parser_analyze_op() analyzes a token. */ @@ -5381,7 +5412,7 @@ grn_ts_expr_parser_analyze_op(grn_ctx *ctx, grn_ts_expr_parser *parser, grn_ts_expr_token *ex_token = parser->stack[parser->stack_depth - 1]; if (n_args == 1) { if (ex_token->type == GRN_TS_EXPR_DUMMY_TOKEN) { - return GRN_INVALID_FORMAT; + GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); } } else if (n_args == 2) { grn_ts_op_precedence precedence = grn_ts_op_get_precedence(token->op_type); @@ -5414,14 +5445,14 @@ grn_ts_expr_parser_analyze_bracket(grn_ctx *ctx, grn_ts_expr_parser *parser, switch (token->src.ptr[0]) { case '(': { if (ex_token->type == GRN_TS_EXPR_DUMMY_TOKEN) { - return GRN_INVALID_FORMAT; + GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); } parser->stack[parser->stack_depth++] = (grn_ts_expr_token *)token; return GRN_SUCCESS; } case '[': { if (ex_token->type != GRN_TS_EXPR_DUMMY_TOKEN) { - return GRN_INVALID_FORMAT; + GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); } parser->stack[parser->stack_depth++] = (grn_ts_expr_token *)token; return GRN_SUCCESS; @@ -5433,18 +5464,18 @@ grn_ts_expr_parser_analyze_bracket(grn_ctx *ctx, grn_ts_expr_parser *parser, return rc; } if (parser->stack_depth < 2) { - return GRN_INVALID_FORMAT; + GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); } ex_ex_token = parser->stack[parser->stack_depth - 2]; if (ex_ex_token->type != GRN_TS_EXPR_BRACKET_TOKEN) { - return GRN_INVALID_FORMAT; + GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); } if (token->src.ptr[0] == ')') { size_t depth = parser->stack_depth; grn_ts_str src; grn_ts_expr_dummy_token *dummy_token; if (ex_ex_token->src.ptr[0] != '(') { - return GRN_INVALID_FORMAT; + GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); } src.ptr = ex_ex_token->src.ptr; src.size = (token->src.ptr + token->src.size) - src.ptr; @@ -5457,7 +5488,7 @@ grn_ts_expr_parser_analyze_bracket(grn_ctx *ctx, grn_ts_expr_parser *parser, } else if (token->src.ptr[0] == ']') { size_t depth = parser->stack_depth; if (ex_ex_token->src.ptr[0] != '[') { - return GRN_INVALID_FORMAT; + GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); } parser->stack[depth - 2] = parser->stack[depth - 1]; parser->stack_depth--; @@ -5466,7 +5497,8 @@ grn_ts_expr_parser_analyze_bracket(grn_ctx *ctx, grn_ts_expr_parser *parser, return GRN_SUCCESS; } default: { - return GRN_INVALID_FORMAT; + GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "undefined bracket: \"%.*s\"", + (int)token->src.size, token->src.ptr); } } } @@ -5522,7 +5554,8 @@ grn_ts_expr_parser_analyze_token(grn_ctx *ctx, grn_ts_expr_parser *parser, return grn_ts_expr_parser_analyze_bracket(ctx, parser, bracket_token); } default: { - return GRN_INVALID_ARGUMENT; + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid token type: %d", + token->type); } } } @@ -5552,7 +5585,8 @@ grn_ts_expr_parser_analyze(grn_ctx *ctx, grn_ts_expr_parser *parser) { } } if (parser->stack_depth != 2) { - return GRN_INVALID_FORMAT; + GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "tokens left in stack: %zu", + parser->stack_depth); } return GRN_SUCCESS; } -------------- next part -------------- HTML����������������������������...Download