susumu.yata
null+****@clear*****
Thu Nov 12 12:33:14 JST 2015
susumu.yata 2015-11-12 12:33:14 +0900 (Thu, 12 Nov 2015) New Revision: 9c37273f94858dce4e7d3bfeb4ed658f54f4f757 https://github.com/groonga/groonga/commit/9c37273f94858dce4e7d3bfeb4ed658f54f4f757 Message: grn_ts: move definitions of grn_ts_expr_parser into lib/ts/ts_expr_parser Added files: lib/ts/ts_expr_parser.h Copied files: lib/ts/ts_expr_parser.c (from lib/ts/ts_expr.c) Modified files: lib/ts/sources.am lib/ts/ts_expr.c lib/ts/ts_expr_node.c Modified: lib/ts/sources.am (+2 -0) =================================================================== --- lib/ts/sources.am 2015-11-12 12:04:01 +0900 (dcaec2b) +++ lib/ts/sources.am 2015-11-12 12:33:14 +0900 (25e82fd) @@ -5,6 +5,8 @@ libgrnts_la_SOURCES = \ ts_expr.h \ ts_expr_node.c \ ts_expr_node.h \ + ts_expr_parser.c \ + ts_expr_parser.h \ ts_log.h \ ts_str.c \ ts_str.h \ Modified: lib/ts/ts_expr.c (+2 -1220) =================================================================== --- lib/ts/ts_expr.c 2015-11-12 12:04:01 +0900 (935c4c6) +++ lib/ts/ts_expr.c 2015-11-12 12:33:14 +0900 (ede1472) @@ -22,7 +22,7 @@ #include <stdlib.h> #include <string.h> -#include "../grn_ctx_impl.h" +#include "../grn_ctx.h" #include "../grn_dat.h" #include "../grn_db.h" #include "../grn_geo.h" @@ -33,6 +33,7 @@ #include "ts_log.h" #include "ts_str.h" #include "ts_util.h" +#include "ts_expr_parser.h" /*------------------------------------------------------------- * Built-in data kinds. @@ -173,1225 +174,6 @@ grn_ts_op_get_n_args(grn_ts_op_type op_type) { } } -/* - * grn_ts_op_get_precedence() returns the precedence. - * A prior operator has a higher precedence. - */ -static grn_ts_op_precedence -grn_ts_op_get_precedence(grn_ts_op_type op_type) { - switch (op_type) { - case GRN_TS_OP_LOGICAL_NOT: - case GRN_TS_OP_BITWISE_NOT: - case GRN_TS_OP_POSITIVE: - case GRN_TS_OP_NEGATIVE: { - return 14; - } - case GRN_TS_OP_LOGICAL_AND: { - return 5; - } - case GRN_TS_OP_LOGICAL_OR: { - return 3; - } - case GRN_TS_OP_LOGICAL_SUB: { - return 4; - } - case GRN_TS_OP_BITWISE_AND: { - return 8; - } - case GRN_TS_OP_BITWISE_OR: { - return 6; - } - case GRN_TS_OP_BITWISE_XOR: { - return 7; - } - case GRN_TS_OP_EQUAL: - case GRN_TS_OP_NOT_EQUAL: { - return 9; - } - case GRN_TS_OP_LESS: - case GRN_TS_OP_LESS_EQUAL: - case GRN_TS_OP_GREATER: - case GRN_TS_OP_GREATER_EQUAL: { - return 10; - } - case GRN_TS_OP_SHIFT_ARITHMETIC_LEFT: - case GRN_TS_OP_SHIFT_ARITHMETIC_RIGHT: - case GRN_TS_OP_SHIFT_LOGICAL_LEFT: - case GRN_TS_OP_SHIFT_LOGICAL_RIGHT: { - return 11; - } - case GRN_TS_OP_PLUS: - case GRN_TS_OP_MINUS: { - return 12; - } - case GRN_TS_OP_MULTIPLICATION: - case GRN_TS_OP_DIVISION: - case GRN_TS_OP_MODULUS: { - return 13; - } - default: { - return 0; - } - } -} - -/*------------------------------------------------------------- - * grn_ts_expr_parser. - */ - -/* - * FIXME: A grn_ts_expr_parser object is designed to parse one expression - * string. grn_ts_expr_parser_parse() should not be called more than - * once. - */ - -typedef enum { - GRN_TS_EXPR_DUMMY_TOKEN, /* No extra data. */ - GRN_TS_EXPR_START_TOKEN, /* No extra data. */ - GRN_TS_EXPR_END_TOKEN, /* No extra data. */ - GRN_TS_EXPR_CONST_TOKEN, /* +data_kind, content and buf. */ - GRN_TS_EXPR_NAME_TOKEN, /* +name. */ - GRN_TS_EXPR_OP_TOKEN, /* +op_type. */ - GRN_TS_EXPR_BRIDGE_TOKEN, /* No extra data. */ - GRN_TS_EXPR_BRACKET_TOKEN /* No extra data. */ -} grn_ts_expr_token_type; - -#define GRN_TS_EXPR_TOKEN_COMMON_MEMBERS\ - grn_ts_str src; /* Source string. */\ - grn_ts_expr_token_type type; /* Token type. */ - -typedef struct { - GRN_TS_EXPR_TOKEN_COMMON_MEMBERS -} grn_ts_expr_token; - -typedef grn_ts_expr_token grn_ts_expr_dummy_token; -typedef grn_ts_expr_token grn_ts_expr_start_token; -typedef grn_ts_expr_token grn_ts_expr_end_token; - -typedef struct { - GRN_TS_EXPR_TOKEN_COMMON_MEMBERS - grn_ts_data_kind data_kind; /* The data kind of the const. */ - grn_ts_any content; /* The const. */ - grn_ts_buf buf; /* Buffer for content.as_text. */ -} grn_ts_expr_const_token; - -typedef grn_ts_expr_token grn_ts_expr_name_token; - -typedef struct { - GRN_TS_EXPR_TOKEN_COMMON_MEMBERS - grn_ts_op_type op_type; /* Operator type. */ -} grn_ts_expr_op_token; - -typedef grn_ts_expr_token grn_ts_expr_bridge_token; -typedef grn_ts_expr_token grn_ts_expr_bracket_token; - -typedef struct { - grn_ts_expr *expr; /* Associated expression. */ - grn_ts_buf str_buf; /* Buffer for a source string. */ - grn_ts_expr_token **tokens; /* Tokens. */ - size_t n_tokens; /* Number of tokens. */ - size_t max_n_tokens; /* Max. number of tokens. */ - grn_ts_expr_dummy_token *dummy_tokens; /* Dummy tokens. */ - size_t n_dummy_tokens; /* Number of dummy tokens. */ - grn_ts_expr_token **stack; /* Token stack. */ - size_t stack_depth; /* Token stack's current depth. */ -} grn_ts_expr_parser; - -#define GRN_TS_EXPR_TOKEN_INIT(TYPE)\ - memset(token, 0, sizeof(*token));\ - token->type = GRN_TS_EXPR_ ## TYPE ## _TOKEN;\ - token->src = src; -/* grn_ts_expr_dummy_token_init() initializes a token. */ -static void -grn_ts_expr_dummy_token_init(grn_ctx *ctx, grn_ts_expr_dummy_token *token, - grn_ts_str src) { - GRN_TS_EXPR_TOKEN_INIT(DUMMY) -} - -/* grn_ts_expr_start_token_init() initializes a token. */ -static void -grn_ts_expr_start_token_init(grn_ctx *ctx, grn_ts_expr_start_token *token, - grn_ts_str src) { - GRN_TS_EXPR_TOKEN_INIT(START) -} - -/* grn_ts_expr_end_token_init() initializes a token. */ -static void -grn_ts_expr_end_token_init(grn_ctx *ctx, grn_ts_expr_end_token *token, - grn_ts_str src) { - GRN_TS_EXPR_TOKEN_INIT(END) -} - -/* grn_ts_expr_const_token_init() initializes a token. */ -static void -grn_ts_expr_const_token_init(grn_ctx *ctx, grn_ts_expr_const_token *token, - grn_ts_str src) { - GRN_TS_EXPR_TOKEN_INIT(CONST); - grn_ts_buf_init(ctx, &token->buf); -} - -/* grn_ts_expr_name_token_init() initializes a token. */ -static void -grn_ts_expr_name_token_init(grn_ctx *ctx, grn_ts_expr_name_token *token, - grn_ts_str src) { - GRN_TS_EXPR_TOKEN_INIT(NAME); -} - -/* grn_ts_expr_op_token_init() initializes a token. */ -static void -grn_ts_expr_op_token_init(grn_ctx *ctx, grn_ts_expr_op_token *token, - grn_ts_str src) { - GRN_TS_EXPR_TOKEN_INIT(OP); -} - -/* grn_ts_expr_bridge_token_init() initializes a token. */ -static void -grn_ts_expr_bridge_token_init(grn_ctx *ctx, grn_ts_expr_bridge_token *token, - grn_ts_str src) { - GRN_TS_EXPR_TOKEN_INIT(BRIDGE) -} - -/* grn_ts_expr_bracket_token_init() initializes a token. */ -static void -grn_ts_expr_bracket_token_init(grn_ctx *ctx, grn_ts_expr_bracket_token *token, - grn_ts_str src) { - GRN_TS_EXPR_TOKEN_INIT(BRACKET) -} -#undef GRN_TS_EXPR_TOKEN_INIT - -/* grn_ts_expr_dummy_token_fin() finalizes a token. */ -static void -grn_ts_expr_dummy_token_fin(grn_ctx *ctx, grn_ts_expr_dummy_token *token) { - /* Nothing to do. */ -} - -/* grn_ts_expr_start_token_fin() finalizes a token. */ -static void -grn_ts_expr_start_token_fin(grn_ctx *ctx, grn_ts_expr_start_token *token) { - /* Nothing to do. */ -} - -/* grn_ts_expr_end_token_fin() finalizes a token. */ -static void -grn_ts_expr_end_token_fin(grn_ctx *ctx, grn_ts_expr_end_token *token) { - /* Nothing to do. */ -} - -/* grn_ts_expr_const_token_fin() finalizes a token. */ -static void -grn_ts_expr_const_token_fin(grn_ctx *ctx, grn_ts_expr_const_token *token) { - grn_ts_buf_fin(ctx, &token->buf); -} - -/* grn_ts_expr_name_token_fin() finalizes a token. */ -static void -grn_ts_expr_name_token_fin(grn_ctx *ctx, grn_ts_expr_name_token *token) { - /* Nothing to do. */ -} - -/* grn_ts_expr_op_token_fin() finalizes a token. */ -static void -grn_ts_expr_op_token_fin(grn_ctx *ctx, grn_ts_expr_op_token *token) { - /* Nothing to do. */ -} - -/* grn_ts_expr_bridge_token_fin() finalizes a token. */ -static void -grn_ts_expr_bridge_token_fin(grn_ctx *ctx, grn_ts_expr_bridge_token *token) { - /* Nothing to do. */ -} - -/* grn_ts_expr_bracket_token_fin() finalizes a token. */ -static void -grn_ts_expr_bracket_token_fin(grn_ctx *ctx, grn_ts_expr_bracket_token *token) { - /* Nothing to do. */ -} - -#define GRN_TS_EXPR_TOKEN_OPEN(TYPE, type)\ - grn_ts_expr_ ## type ## _token *new_token;\ - new_token = GRN_MALLOCN(grn_ts_expr_ ## type ## _token, 1);\ - if (!new_token) {\ - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1",\ - sizeof(grn_ts_expr_ ## type ## _token));\ - }\ - grn_ts_expr_ ## type ## _token_init(ctx, new_token, src);\ - *token = new_token; -/* grn_ts_expr_dummy_token_open() creates a token. */ -/* -static grn_rc -grn_ts_expr_dummy_token_open(grn_ctx *ctx, grn_ts_str src, - grn_ts_expr_dummy_token **token) { - GRN_TS_EXPR_TOKEN_OPEN(DUMMY, dummy) - return GRN_SUCCESS; -} -*/ - -/* grn_ts_expr_start_token_open() creates a token. */ -static grn_rc -grn_ts_expr_start_token_open(grn_ctx *ctx, grn_ts_str src, - grn_ts_expr_start_token **token) { - GRN_TS_EXPR_TOKEN_OPEN(START, start) - return GRN_SUCCESS; -} - -/* grn_ts_expr_end_token_open() creates a token. */ -static grn_rc -grn_ts_expr_end_token_open(grn_ctx *ctx, grn_ts_str src, - grn_ts_expr_end_token **token) { - GRN_TS_EXPR_TOKEN_OPEN(END, end) - return GRN_SUCCESS; -} - -/* grn_ts_expr_const_token_open() creates a token. */ -static grn_rc -grn_ts_expr_const_token_open(grn_ctx *ctx, grn_ts_str src, - grn_ts_expr_const_token **token) { - GRN_TS_EXPR_TOKEN_OPEN(CONST, const) - return GRN_SUCCESS; -} - -/* grn_ts_expr_name_token_open() creates a token. */ -static grn_rc -grn_ts_expr_name_token_open(grn_ctx *ctx, grn_ts_str src, - grn_ts_expr_name_token **token) { - GRN_TS_EXPR_TOKEN_OPEN(NAME, name) - return GRN_SUCCESS; -} - -/* grn_ts_expr_op_token_open() creates a token. */ -static grn_rc -grn_ts_expr_op_token_open(grn_ctx *ctx, grn_ts_str src, grn_ts_op_type op_type, - grn_ts_expr_op_token **token) { - GRN_TS_EXPR_TOKEN_OPEN(OP, op) - new_token->op_type = op_type; - return GRN_SUCCESS; -} - -/* grn_ts_expr_bridge_token_open() creates a token. */ -static grn_rc -grn_ts_expr_bridge_token_open(grn_ctx *ctx, grn_ts_str src, - grn_ts_expr_bridge_token **token) { - GRN_TS_EXPR_TOKEN_OPEN(BRIDGE, bridge) - return GRN_SUCCESS; -} - -/* grn_ts_expr_bracket_token_open() creates a token. */ -static grn_rc -grn_ts_expr_bracket_token_open(grn_ctx *ctx, grn_ts_str src, - grn_ts_expr_bracket_token **token) { - GRN_TS_EXPR_TOKEN_OPEN(BRACKET, bracket) - return GRN_SUCCESS; -} -#undef GRN_TS_EXPR_TOKEN_OPEN - -#define GRN_TS_EXPR_TOKEN_CLOSE_CASE(TYPE, type)\ - case GRN_TS_EXPR_ ## TYPE ## _TOKEN: {\ - grn_ts_expr_ ## type ## _token *type ## _token;\ - type ## _token = (grn_ts_expr_ ## type ## _token *)token;\ - grn_ts_expr_ ## type ## _token_fin(ctx, type ## _token);\ - break;\ - } -/* grn_ts_expr_token_close() destroys a token. */ -static void -grn_ts_expr_token_close(grn_ctx *ctx, grn_ts_expr_token *token) { - switch (token->type) { - GRN_TS_EXPR_TOKEN_CLOSE_CASE(DUMMY, dummy) - GRN_TS_EXPR_TOKEN_CLOSE_CASE(START, start) - GRN_TS_EXPR_TOKEN_CLOSE_CASE(END, end) - GRN_TS_EXPR_TOKEN_CLOSE_CASE(CONST, const) - GRN_TS_EXPR_TOKEN_CLOSE_CASE(NAME, name) - GRN_TS_EXPR_TOKEN_CLOSE_CASE(OP, op) - GRN_TS_EXPR_TOKEN_CLOSE_CASE(BRACKET, bracket) - GRN_TS_EXPR_TOKEN_CLOSE_CASE(BRIDGE, bridge) - } - GRN_FREE(token); -} -#undef GRN_TS_EXPR_TOKEN_CLOSE_CASE - -/* grn_ts_expr_parser_init() initializes a parser. */ -static void -grn_ts_expr_parser_init(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_expr_parser *parser) { - memset(parser, 0, sizeof(*parser)); - parser->expr = expr; - grn_ts_buf_init(ctx, &parser->str_buf); - parser->tokens = NULL; - parser->dummy_tokens = NULL; - parser->stack = NULL; -} - -/* grn_ts_expr_parser_fin() finalizes a parser. */ -static void -grn_ts_expr_parser_fin(grn_ctx *ctx, grn_ts_expr_parser *parser) { - if (parser->stack) { - GRN_FREE(parser->stack); - } - if (parser->dummy_tokens) { - size_t i; - for (i = 0; i < parser->n_dummy_tokens; i++) { - grn_ts_expr_dummy_token_fin(ctx, &parser->dummy_tokens[i]); - } - GRN_FREE(parser->dummy_tokens); - } - if (parser->tokens) { - size_t i; - for (i = 0; i < parser->n_tokens; i++) { - grn_ts_expr_token_close(ctx, parser->tokens[i]); - } - GRN_FREE(parser->tokens); - } - grn_ts_buf_fin(ctx, &parser->str_buf); -} - -/* grn_ts_expr_parser_open() creates a parser. */ -static grn_rc -grn_ts_expr_parser_open(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_expr_parser **parser) { - grn_ts_expr_parser *new_parser = GRN_MALLOCN(grn_ts_expr_parser, 1); - if (!new_parser) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1", - sizeof(grn_ts_expr_parser)); - } - grn_ts_expr_parser_init(ctx, expr, new_parser); - *parser = new_parser; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_close() destroys a parser. */ -static void -grn_ts_expr_parser_close(grn_ctx *ctx, grn_ts_expr_parser *parser) { - grn_ts_expr_parser_fin(ctx, parser); - GRN_FREE(parser); -} - -/* grn_ts_expr_parser_tokenize_start() creates the start token. */ -static grn_rc -grn_ts_expr_parser_tokenize_start(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, grn_ts_expr_token **token) { - grn_ts_str token_str = { str.ptr, 0 }; - grn_ts_expr_start_token *new_token; - grn_rc rc = grn_ts_expr_start_token_open(ctx, token_str, &new_token); - if (rc != GRN_SUCCESS) { - return rc; - } - *token = (grn_ts_expr_token *)new_token; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_tokenize_end() creates the end token. */ -static grn_rc -grn_ts_expr_parser_tokenize_end(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, grn_ts_expr_token **token) { - grn_ts_str token_str = { str.ptr, 0 }; - grn_ts_expr_end_token *new_token; - grn_rc rc = grn_ts_expr_end_token_open(ctx, token_str, &new_token); - if (rc != GRN_SUCCESS) { - return rc; - } - *token = (grn_ts_expr_token *)new_token; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_tokenize_number() tokenizes an Int or Float literal. */ -static grn_rc -grn_ts_expr_parser_tokenize_number(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, grn_ts_expr_token **token) { - char *end; - grn_rc rc; - grn_ts_int int_value; - grn_ts_str token_str; - grn_ts_expr_const_token *new_token; - - int_value = strtol(str.ptr, &end, 0); - if ((end != str.ptr) && (*end != '.') && (*end != 'e')) { - if (grn_ts_byte_is_name_char(*end)) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, - "unterminated Int literal: \"%.*s\"", - (int)str.size, str.ptr); - } - token_str.ptr = str.ptr; - token_str.size = end - str.ptr; - rc = grn_ts_expr_const_token_open(ctx, token_str, &new_token); - if (rc != GRN_SUCCESS) { - return rc; - } - new_token->data_kind = GRN_TS_INT; - new_token->content.as_int = int_value; - } else { - grn_ts_float float_value = strtod(str.ptr, &end); - if (end == str.ptr) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid number literal: \"%.*s\"", - (int)str.size, str.ptr); - } - if (grn_ts_byte_is_name_char(*end)) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, - "unterminated Float literal: \"%.*s\"", - (int)str.size, str.ptr); - } - token_str.ptr = str.ptr; - token_str.size = end - str.ptr; - rc = grn_ts_expr_const_token_open(ctx, token_str, &new_token); - if (rc != GRN_SUCCESS) { - return rc; - } - new_token->data_kind = GRN_TS_FLOAT; - new_token->content.as_float = float_value; - } - *token = (grn_ts_expr_token *)new_token; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_tokenize_text() tokenizes a Text literal. */ -static grn_rc -grn_ts_expr_parser_tokenize_text(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, grn_ts_expr_token **token) { - size_t i, n_escapes = 0; - grn_rc rc; - grn_ts_str token_str; - grn_ts_expr_const_token *new_token; - for (i = 1; i < str.size; i++) { - if (str.ptr[i] == '\\') { - i++; - n_escapes++; - } else if (str.ptr[i] == '"') { - break; - } - } - if (i >= str.size) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "no closing double quote: \"%.*s\"", - (int)str.size, str.ptr); - } - token_str.ptr = str.ptr; - token_str.size = i + 1; - rc = grn_ts_expr_const_token_open(ctx, token_str, &new_token); - if (rc != GRN_SUCCESS) { - return rc; - } - new_token->data_kind = GRN_TS_TEXT; - if (n_escapes) { - char *buf_ptr; - const char *str_ptr = str.ptr + 1; - size_t size = token_str.size - 2 - n_escapes; - rc = grn_ts_buf_resize(ctx, &new_token->buf, size); - if (rc != GRN_SUCCESS) { - grn_ts_expr_token_close(ctx, (grn_ts_expr_token *)new_token); - return rc; - } - buf_ptr = (char *)new_token->buf.ptr; - for (i = 0; i < size; i++) { - if (str_ptr[i] == '\\') { - str_ptr++; - } - buf_ptr[i] = str_ptr[i]; - } - new_token->content.as_text.ptr = buf_ptr; - new_token->content.as_text.size = size; - } else { - new_token->content.as_text.ptr = token_str.ptr + 1; - new_token->content.as_text.size = token_str.size - 2; - } - *token = (grn_ts_expr_token *)new_token; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_tokenize_name() tokenizes a Bool literal or a name. */ -static grn_rc -grn_ts_expr_parser_tokenize_name(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, grn_ts_expr_token **token) { - size_t i; - grn_ts_str token_str; - for (i = 1; i < str.size; i++) { - if (!grn_ts_byte_is_name_char(str.ptr[i])) { - break; - } - } - token_str.ptr = str.ptr; - token_str.size = i; - - if (grn_ts_str_is_bool(token_str)) { - grn_ts_expr_const_token *new_token; - grn_rc rc = grn_ts_expr_const_token_open(ctx, token_str, &new_token); - if (rc != GRN_SUCCESS) { - return rc; - } - new_token->data_kind = GRN_TS_BOOL; - if (token_str.ptr[0] == 't') { - new_token->content.as_bool = GRN_TRUE; - } else { - new_token->content.as_bool = GRN_FALSE; - } - *token = (grn_ts_expr_token *)new_token; - return GRN_SUCCESS; - } - return grn_ts_expr_name_token_open(ctx, token_str, token); -} - -/* grn_ts_expr_parser_tokenize_bridge() tokenizes a bridge. */ -static grn_rc -grn_ts_expr_parser_tokenize_bridge(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, grn_ts_expr_token **token) { - grn_ts_str token_str = { str.ptr, 1 }; - grn_ts_expr_bridge_token *new_token; - grn_rc rc = grn_ts_expr_bridge_token_open(ctx, token_str, &new_token); - if (rc != GRN_SUCCESS) { - return rc; - } - *token = (grn_ts_expr_token *)new_token; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_tokenize_bracket() tokenizes a bracket. */ -static grn_rc -grn_ts_expr_parser_tokenize_bracket(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, - grn_ts_expr_token **token) { - grn_ts_str token_str = { str.ptr, 1 }; - grn_ts_expr_bracket_token *new_token; - grn_rc rc = grn_ts_expr_bracket_token_open(ctx, token_str, &new_token); - if (rc != GRN_SUCCESS) { - return rc; - } - *token = (grn_ts_expr_token *)new_token; - return GRN_SUCCESS; -} - -/* - * grn_ts_expr_parsre_tokenize_sign() tokenizes an operator '+' or '-'. - * Note that '+' and '-' have two roles each. - * '+' is GRN_TS_OP_POSITIVE or GRN_TS_OP_PLUS. - * '-' is GRN_TS_OP_NEGATIVE or GRN_TS_OP_MINUS. - */ -static grn_rc -grn_ts_expr_parser_tokenize_sign(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, grn_ts_expr_token **token) { - size_t n_args; - grn_rc rc; - grn_ts_op_type op_type; - grn_ts_str token_str = { str.ptr, 1 }; - grn_ts_expr_token *prev_token = parser->tokens[parser->n_tokens - 1]; - grn_ts_expr_op_token *new_token; - switch (prev_token->type) { - case GRN_TS_EXPR_START_TOKEN: - case GRN_TS_EXPR_OP_TOKEN: { - n_args = 1; - break; - } - case GRN_TS_EXPR_CONST_TOKEN: - case GRN_TS_EXPR_NAME_TOKEN: { - n_args = 2; - break; - } - case GRN_TS_EXPR_BRACKET_TOKEN: { - grn_ts_str bracket; - const grn_ts_expr_bracket_token *bracket_token; - bracket_token = (const grn_ts_expr_bracket_token *)prev_token; - bracket = bracket_token->src; - switch (bracket.ptr[0]) { - case '(': case '[': { - n_args = 1; - break; - } - case ')': case ']': { - n_args = 2; - break; - } - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "undefined bracket: \"%.*s\"", - (int)bracket.size, bracket.ptr); - } - } - break; - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence: %d", - prev_token->type); - } - } - if (token_str.ptr[0] == '+') { - op_type = (n_args == 1) ? GRN_TS_OP_POSITIVE : GRN_TS_OP_PLUS; - } else { - op_type = (n_args == 1) ? GRN_TS_OP_NEGATIVE : GRN_TS_OP_MINUS; - } - rc = grn_ts_expr_op_token_open(ctx, token_str, op_type, &new_token); - if (rc != GRN_SUCCESS) { - return rc; - } - *token = (grn_ts_expr_token *)new_token; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_tokenize_op() tokenizes an operator. */ -static grn_rc -grn_ts_expr_parser_tokenize_op(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, grn_ts_expr_token **token) { - grn_rc rc = GRN_SUCCESS; - grn_ts_str token_str = str; - grn_ts_op_type op_type; - grn_ts_expr_op_token *new_token; - switch (str.ptr[0]) { - case '+': case '-': { - return grn_ts_expr_parser_tokenize_sign(ctx, parser, str, token); - } - case '!': { - if ((str.size >= 2) && (str.ptr[1] == '=')) { - token_str.size = 2; - op_type = GRN_TS_OP_NOT_EQUAL; - } else { - token_str.size = 1; - op_type = GRN_TS_OP_LOGICAL_NOT; - } - rc = grn_ts_expr_op_token_open(ctx, token_str, op_type, &new_token); - break; - } -#define GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE(label, TYPE_1, TYPE_2, TYPE_3,\ - TYPE_EQUAL)\ - case label: {\ - if ((str.size >= 2) && (str.ptr[1] == '=')) {\ - token_str.size = 2;\ - op_type = GRN_TS_OP_ ## TYPE_EQUAL;\ - } else if ((str.size >= 2) && (str.ptr[1] == label)) {\ - if ((str.size >= 3) && (str.ptr[2] == label)) {\ - token_str.size = 3;\ - op_type = GRN_TS_OP_ ## TYPE_3;\ - } else {\ - token_str.size = 2;\ - op_type = GRN_TS_OP_ ## TYPE_2;\ - }\ - } else {\ - token_str.size = 1;\ - op_type = GRN_TS_OP_ ## TYPE_1;\ - }\ - rc = grn_ts_expr_op_token_open(ctx, token_str, op_type, &new_token);\ - break;\ - } - GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('<', LESS, SHIFT_ARITHMETIC_LEFT, - SHIFT_LOGICAL_LEFT, LESS_EQUAL) - GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('>', GREATER, SHIFT_ARITHMETIC_RIGHT, - SHIFT_LOGICAL_RIGHT, GREATER_EQUAL) -#undef GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE - case '&': { - if ((str.size >= 2) && (str.ptr[1] == '&')) { - token_str.size = 2; - op_type = GRN_TS_OP_LOGICAL_AND; - } else if ((str.size >= 2) && (str.ptr[1] == '&')) { - token_str.size = 2; - op_type = GRN_TS_OP_LOGICAL_SUB; - } else { - token_str.size = 1; - op_type = GRN_TS_OP_BITWISE_AND; - } - rc = grn_ts_expr_op_token_open(ctx, token_str, op_type, &new_token); - break; - } - case '|': { - if ((str.size >= 2) && (str.ptr[1] == '|')) { - token_str.size = 2; - op_type = GRN_TS_OP_LOGICAL_OR; - } else { - token_str.size = 1; - op_type = GRN_TS_OP_BITWISE_OR; - } - rc = grn_ts_expr_op_token_open(ctx, token_str, op_type, &new_token); - break; - } - case '=': { - if ((str.size < 2) || (str.ptr[1] != '=')) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, - "single equal not available: =\"%.*s\"", - (int)str.size, str.ptr); - } - token_str.size = 2; - rc = grn_ts_expr_op_token_open(ctx, token_str, GRN_TS_OP_EQUAL, - &new_token); - break; - } -#define GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE(label, TYPE)\ - case label: {\ - token_str.size = 1;\ - rc = grn_ts_expr_op_token_open(ctx, token_str, GRN_TS_OP_ ## TYPE,\ - &new_token);\ - break;\ - } - GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('~', BITWISE_NOT) - GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('^', BITWISE_XOR) - GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('*', MULTIPLICATION) - GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('/', DIVISION) - GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('%', MODULUS) -#undef GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid character: \"%.*s\"", - (int)str.size, str.ptr); - } - } - if (rc != GRN_SUCCESS) { - return rc; - } - *token = (grn_ts_expr_token *)new_token; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_tokenize_next() extracts the next token. */ -static grn_rc -grn_ts_expr_parser_tokenize_next(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str, grn_ts_expr_token **token) { - grn_ts_str rest; - if (!parser->n_tokens) { - return grn_ts_expr_parser_tokenize_start(ctx, parser, str, token); - } - rest = grn_ts_str_trim_left(str); - if (!rest.size) { - return grn_ts_expr_parser_tokenize_end(ctx, parser, rest, token); - } - if (grn_ts_str_has_number_prefix(rest)) { - grn_ts_expr_token *prev_token; - if ((rest.ptr[0] != '+') && (rest.ptr[0] != '-')) { - return grn_ts_expr_parser_tokenize_number(ctx, parser, rest, token); - } - prev_token = parser->tokens[parser->n_tokens - 1]; - switch (prev_token->type) { - case GRN_TS_EXPR_START_TOKEN: - case GRN_TS_EXPR_OP_TOKEN: { - return grn_ts_expr_parser_tokenize_number(ctx, parser, rest, token); - } - case GRN_TS_EXPR_BRACKET_TOKEN: { - if ((prev_token->src.ptr[0] == '(') || - (prev_token->src.ptr[0] == '[')) { - return grn_ts_expr_parser_tokenize_number(ctx, parser, rest, token); - } - break; - } - default: { - break; - } - } - } - if (rest.ptr[0] == '"') { - return grn_ts_expr_parser_tokenize_text(ctx, parser, rest, token); - } - if (grn_ts_byte_is_name_char(rest.ptr[0])) { - return grn_ts_expr_parser_tokenize_name(ctx, parser, rest, token); - } - switch (rest.ptr[0]) { - case '(': case ')': case '[': case ']': { - return grn_ts_expr_parser_tokenize_bracket(ctx, parser, rest, token); - } - case '.': { - return grn_ts_expr_parser_tokenize_bridge(ctx, parser, rest, token); - } - default: { - return grn_ts_expr_parser_tokenize_op(ctx, parser, rest, token); - } - } -} - -/* - * grn_ts_expr_parser_reserve_tokens() extends a token buffer for a new token. - */ -static grn_rc -grn_ts_expr_parser_reserve_tokens(grn_ctx *ctx, grn_ts_expr_parser *parser) { - size_t i, n_bytes, new_max_n_tokens; - grn_ts_expr_token **new_tokens; - if (parser->n_tokens < parser->max_n_tokens) { - return GRN_SUCCESS; - } - new_max_n_tokens = parser->n_tokens * 2; - if (!new_max_n_tokens) { - new_max_n_tokens = 1; - } - n_bytes = sizeof(grn_ts_expr_token *) * new_max_n_tokens; - new_tokens = (grn_ts_expr_token **)GRN_REALLOC(parser->tokens, n_bytes); - if (!new_tokens) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_REALLOC failed: %zu", - n_bytes); - } - for (i = parser->n_tokens; i < new_max_n_tokens; i++) { - new_tokens[i] = NULL; - } - parser->tokens = new_tokens; - parser->max_n_tokens = new_max_n_tokens; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_tokenize() tokenizes a string. */ -static grn_rc -grn_ts_expr_parser_tokenize(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_str str) { - grn_ts_str rest = str; - const char *end = str.ptr + str.size; - grn_ts_expr_token *token = NULL; - GRN_TS_DEBUG("str = \"%.*s\"", (int)str.size, str.ptr); - do { - grn_rc rc = grn_ts_expr_parser_reserve_tokens(ctx, parser); - if (rc != GRN_SUCCESS) { - return rc; - } - rc = grn_ts_expr_parser_tokenize_next(ctx, parser, rest, &token); - if (rc != GRN_SUCCESS) { - return rc; - } - if ((token->type != GRN_TS_EXPR_START_TOKEN) && - (token->type != GRN_TS_EXPR_END_TOKEN)) { - GRN_TS_DEBUG("token = \"%.*s\"", (int)token->src.size, token->src.ptr); - } - parser->tokens[parser->n_tokens++] = token; - rest.ptr = token->src.ptr + token->src.size; - rest.size = end - rest.ptr; - } while (token->type != GRN_TS_EXPR_END_TOKEN); - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_push_const() pushes a token to an expression. */ -static grn_rc -grn_ts_expr_parser_push_const(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_expr_const_token *token) { - switch (token->data_kind) { - case GRN_TS_BOOL: { - return grn_ts_expr_push_bool(ctx, parser->expr, token->content.as_bool); - } - case GRN_TS_INT: { - return grn_ts_expr_push_int(ctx, parser->expr, token->content.as_int); - } - case GRN_TS_FLOAT: { - return grn_ts_expr_push_float(ctx, parser->expr, - token->content.as_float); - } - case GRN_TS_TEXT: { - return grn_ts_expr_push_text(ctx, parser->expr, token->content.as_text); - } - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", - token->data_kind); - } - } -} - -/* grn_ts_expr_parser_push_name() pushes a token to an expression. */ -static grn_rc -grn_ts_expr_parser_push_name(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_expr_name_token *token) { - return grn_ts_expr_push_name(ctx, parser->expr, - token->src.ptr, token->src.size); -} - -/* grn_ts_expr_parser_push_op() pushes a token to an expression. */ -static grn_rc -grn_ts_expr_parser_push_op(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_expr_op_token *token) { - return grn_ts_expr_push_op(ctx, parser->expr, token->op_type); -} - -/* - * 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_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; - 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. */ - switch (stack[depth - 2]->type) { - case GRN_TS_EXPR_BRIDGE_TOKEN: { - rc = grn_ts_expr_end_subexpr(ctx, parser->expr); - if (rc != GRN_SUCCESS) { - return rc; - } - 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) { - return GRN_END_OF_DATA; - } - rc = grn_ts_expr_parser_push_op(ctx, parser, op_token); - if (rc != GRN_SUCCESS) { - return rc; - } - n_args = grn_ts_op_get_n_args(op_token->op_type); - break; - } - default: { - return GRN_END_OF_DATA; - } - } - - /* 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; - 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; - break; - } - default: { - GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, - "invalid #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 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. */ -static grn_rc -grn_ts_expr_parser_analyze_op(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_expr_op_token *token) { - size_t n_args = grn_ts_op_get_n_args(token->op_type); - 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) { - 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); - grn_rc rc = grn_ts_expr_parser_apply(ctx, parser, precedence); - if (rc != GRN_SUCCESS) { - return rc; - } - } - parser->stack[parser->stack_depth++] = (grn_ts_expr_token *)token; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_analyze_bridge() analyzes a token. */ -static grn_rc -grn_ts_expr_parser_analyze_bridge(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_expr_bridge_token *token) { - grn_rc rc = grn_ts_expr_begin_subexpr(ctx, parser->expr); - if (rc != GRN_SUCCESS) { - return rc; - } - parser->stack[parser->stack_depth++] = (grn_ts_expr_token *)token; - return GRN_SUCCESS; -} - -/* grn_ts_expr_parser_analyze_bracket() analyzes a token. */ -static grn_rc -grn_ts_expr_parser_analyze_bracket(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_expr_bracket_token *token) { - grn_ts_expr_token *ex_token = parser->stack[parser->stack_depth - 1]; - switch (token->src.ptr[0]) { - case '(': { - if (ex_token->type == GRN_TS_EXPR_DUMMY_TOKEN) { - 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) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); - } - parser->stack[parser->stack_depth++] = (grn_ts_expr_token *)token; - return GRN_SUCCESS; - } - case ')': case ']': { - grn_ts_expr_token *ex_ex_token; - grn_rc rc = grn_ts_expr_parser_apply(ctx, parser, 0); - if (rc != GRN_SUCCESS) { - return rc; - } - if (parser->stack_depth < 2) { - 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) { - 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] != '(') { - 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; - 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); - parser->stack[depth - 2] = dummy_token; - parser->stack_depth--; - // TODO: Apply a function. - } else if (token->src.ptr[0] == ']') { - size_t depth = parser->stack_depth; - if (ex_ex_token->src.ptr[0] != '[') { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); - } - parser->stack[depth - 2] = parser->stack[depth - 1]; - parser->stack_depth--; - // TODO: Push a subscript operator. - } - return GRN_SUCCESS; - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "undefined bracket: \"%.*s\"", - (int)token->src.size, token->src.ptr); - } - } -} - -/* grn_ts_expr_parser_analyze_token() analyzes a token. */ -static grn_rc -grn_ts_expr_parser_analyze_token(grn_ctx *ctx, grn_ts_expr_parser *parser, - grn_ts_expr_token *token) { - switch (token->type) { - case GRN_TS_EXPR_START_TOKEN: { - parser->stack[parser->stack_depth++] = token; - return GRN_SUCCESS; - } - case GRN_TS_EXPR_END_TOKEN: { - return grn_ts_expr_parser_apply(ctx, parser, 0); - } - case GRN_TS_EXPR_CONST_TOKEN: { - grn_ts_expr_const_token *const_token = (grn_ts_expr_const_token *)token; - grn_ts_expr_dummy_token *dummy_token; - grn_rc rc = grn_ts_expr_parser_push_const(ctx, parser, const_token); - if (rc != GRN_SUCCESS) { - return rc; - } - dummy_token = &parser->dummy_tokens[parser->n_dummy_tokens++]; - grn_ts_expr_dummy_token_init(ctx, dummy_token, token->src); - parser->stack[parser->stack_depth++] = dummy_token; - return GRN_SUCCESS; - } - case GRN_TS_EXPR_NAME_TOKEN: { - grn_ts_expr_name_token *name_token = (grn_ts_expr_name_token *)token; - grn_ts_expr_dummy_token *dummy_token; - grn_rc rc = grn_ts_expr_parser_push_name(ctx, parser, name_token); - if (rc != GRN_SUCCESS) { - return rc; - } - dummy_token = &parser->dummy_tokens[parser->n_dummy_tokens++]; - grn_ts_expr_dummy_token_init(ctx, dummy_token, token->src); - parser->stack[parser->stack_depth++] = dummy_token; - return GRN_SUCCESS; - } - case GRN_TS_EXPR_OP_TOKEN: { - grn_ts_expr_op_token *op_token = (grn_ts_expr_op_token *)token; - return grn_ts_expr_parser_analyze_op(ctx, parser, op_token); - } - case GRN_TS_EXPR_BRIDGE_TOKEN: { - grn_ts_expr_bridge_token *bridge_token; - bridge_token = (grn_ts_expr_bridge_token *)token; - return grn_ts_expr_parser_analyze_bridge(ctx, parser, bridge_token); - } - case GRN_TS_EXPR_BRACKET_TOKEN: { - grn_ts_expr_bracket_token *bracket_token; - bracket_token = (grn_ts_expr_bracket_token *)token; - return grn_ts_expr_parser_analyze_bracket(ctx, parser, bracket_token); - } - default: { - GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid token type: %d", - token->type); - } - } -} - -/* grn_ts_expr_parser_analyze() analyzes tokens. */ -static grn_rc -grn_ts_expr_parser_analyze(grn_ctx *ctx, grn_ts_expr_parser *parser) { - size_t i; - - /* Reserve temporary work spaces. */ - parser->dummy_tokens = GRN_MALLOCN(grn_ts_expr_dummy_token, - parser->n_tokens); - if (!parser->dummy_tokens) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x %zu", - sizeof(grn_ts_expr_dummy_token), parser->n_tokens); - } - parser->stack = GRN_MALLOCN(grn_ts_expr_token *, parser->n_tokens); - if (!parser->stack) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x %zu", - sizeof(grn_ts_expr_token *), parser->n_tokens); - } - - /* Analyze tokens. */ - for (i = 0; i < parser->n_tokens; i++) { - grn_rc rc; - rc = grn_ts_expr_parser_analyze_token(ctx, parser, parser->tokens[i]); - if (rc != GRN_SUCCESS) { - return rc; - } - } - if (parser->stack_depth != 2) { - GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "tokens left in stack: %zu", - parser->stack_depth); - } - return GRN_SUCCESS; -} - -/* - * grn_ts_expr_parser_parse() parses a string and pushes nodes into an - * expression. - */ -static grn_rc -grn_ts_expr_parser_parse(grn_ctx *ctx, grn_ts_expr_parser *parser, - const char *str_ptr, size_t str_size) { - grn_rc rc; - grn_ts_str str; - rc = grn_ts_buf_reserve(ctx, &parser->str_buf, str_size + 1); - if (rc != GRN_SUCCESS) { - return rc; - } - grn_memcpy(parser->str_buf.ptr, str_ptr, str_size); - ((char *)parser->str_buf.ptr)[str_size] = '\0'; - str.ptr = (const char *)parser->str_buf.ptr; - str.size = str_size; - rc = grn_ts_expr_parser_tokenize(ctx, parser, str); - if (rc != GRN_SUCCESS) { - return rc; - } - rc = grn_ts_expr_parser_analyze(ctx, parser); - if (rc != GRN_SUCCESS) { - return rc; - } - return GRN_SUCCESS; -} - /*------------------------------------------------------------- * grn_ts_expr_bridge. */ Modified: lib/ts/ts_expr_node.c (+1 -1) =================================================================== --- lib/ts/ts_expr_node.c 2015-11-12 12:04:01 +0900 (1a97e07) +++ lib/ts/ts_expr_node.c 2015-11-12 12:33:14 +0900 (c4733a9) @@ -22,7 +22,7 @@ #include <stdlib.h> #include <string.h> -#include "../grn_ctx_impl.h" +#include "../grn_ctx.h" #include "../grn_dat.h" #include "../grn_db.h" #include "../grn_geo.h" Copied: lib/ts/ts_expr_parser.c (+7 -1113) 56% =================================================================== --- lib/ts/ts_expr.c 2015-11-12 12:04:01 +0900 (935c4c6) +++ lib/ts/ts_expr_parser.c 2015-11-12 12:33:14 +0900 (d3a4987) @@ -16,116 +16,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "ts_expr.h" +#include "ts_expr_parser.h" -#include <math.h> -#include <stdlib.h> #include <string.h> -#include "../grn_ctx_impl.h" -#include "../grn_dat.h" -#include "../grn_db.h" -#include "../grn_geo.h" -#include "../grn_hash.h" -#include "../grn_pat.h" -#include "../grn_store.h" +#include "../grn_ctx.h" #include "ts_log.h" #include "ts_str.h" -#include "ts_util.h" - -/*------------------------------------------------------------- - * Built-in data kinds. - */ - -/* grn_ts_bool_is_valid() returns whether a value is valid or not. */ -inline static grn_ts_bool -grn_ts_bool_is_valid(grn_ts_bool value) { - return GRN_TRUE; -} - -/* grn_ts_int_is_valid() returns whether a value is valid or not. */ -inline static grn_ts_bool -grn_ts_int_is_valid(grn_ts_int value) { - return GRN_TRUE; -} - -/* grn_ts_float_is_valid() returns whether a value is valid or not. */ -inline static grn_ts_bool -grn_ts_float_is_valid(grn_ts_float value) { - return isfinite(value); -} - -/* grn_ts_time_is_valid() returns whether a value is valid or not. */ -inline static grn_ts_bool -grn_ts_time_is_valid(grn_ts_time value) { - return GRN_TRUE; -} - -/* grn_ts_text_is_valid() returns whether a value is valid or not. */ -inline static grn_ts_bool -grn_ts_text_is_valid(grn_ts_text value) { - return value.ptr || !value.size; -} - -/* grn_ts_geo_is_valid() returns whether a value is valid or not. */ -inline static grn_ts_bool -grn_ts_geo_is_valid(grn_ts_geo value) { - return ((value.latitude >= GRN_GEO_MIN_LATITUDE) && - (value.latitude <= GRN_GEO_MAX_LATITUDE)) && - ((value.longitude >= GRN_GEO_MIN_LONGITUDE) && - (value.longitude <= GRN_GEO_MAX_LONGITUDE)); -} - -#define GRN_TS_VECTOR_IS_VALID(type)\ - if (value.size) {\ - size_t i;\ - if (!value.ptr) {\ - return GRN_FALSE;\ - }\ - for (i = 0; i < value.size; i++) {\ - if (!grn_ts_ ## type ## _is_valid(value.ptr[i])) {\ - return GRN_FALSE;\ - }\ - }\ - }\ - return GRN_TRUE; -/* grn_ts_bool_vector_is_valid() returns whether a value is valid or not. */ -inline static grn_ts_bool -grn_ts_bool_vector_is_valid(grn_ts_bool_vector value) { - GRN_TS_VECTOR_IS_VALID(bool) -} - -/* grn_ts_int_vector_is_valid() returns whether a value is valid or not. */ -inline static grn_ts_bool -grn_ts_int_vector_is_valid(grn_ts_int_vector value) { - GRN_TS_VECTOR_IS_VALID(int) -} - -/* grn_ts_float_vector_is_valid() returns whether a value is valid or not. */ -inline static grn_ts_bool -grn_ts_float_vector_is_valid(grn_ts_float_vector value) { - GRN_TS_VECTOR_IS_VALID(float) -} - -/* grn_ts_time_vector_is_valid() returns whether a value is valid or not. */ -inline static grn_ts_bool -grn_ts_time_vector_is_valid(grn_ts_time_vector value) { - GRN_TS_VECTOR_IS_VALID(time) -} - -/* grn_ts_text_vector_is_valid() returns whether a value is valid or not. */ -inline static grn_ts_bool -grn_ts_text_vector_is_valid(grn_ts_text_vector value) { - GRN_TS_VECTOR_IS_VALID(text) -} - -/* grn_ts_geo_vector_is_valid() returns whether a value is valid or not. */ -inline static grn_ts_bool -grn_ts_geo_vector_is_valid(grn_ts_geo_vector value) { - GRN_TS_VECTOR_IS_VALID(geo) -} -#undef GRN_TS_VECTOR_IS_VALID /*------------------------------------------------------------- * Operators. @@ -285,7 +183,7 @@ typedef struct { typedef grn_ts_expr_token grn_ts_expr_bridge_token; typedef grn_ts_expr_token grn_ts_expr_bracket_token; -typedef struct { +struct grn_ts_expr_parser { grn_ts_expr *expr; /* Associated expression. */ grn_ts_buf str_buf; /* Buffer for a source string. */ grn_ts_expr_token **tokens; /* Tokens. */ @@ -295,7 +193,7 @@ typedef struct { size_t n_dummy_tokens; /* Number of dummy tokens. */ grn_ts_expr_token **stack; /* Token stack. */ size_t stack_depth; /* Token stack's current depth. */ -} grn_ts_expr_parser; +}; #define GRN_TS_EXPR_TOKEN_INIT(TYPE)\ memset(token, 0, sizeof(*token));\ @@ -543,8 +441,7 @@ grn_ts_expr_parser_fin(grn_ctx *ctx, grn_ts_expr_parser *parser) { grn_ts_buf_fin(ctx, &parser->str_buf); } -/* grn_ts_expr_parser_open() creates a parser. */ -static grn_rc +grn_rc grn_ts_expr_parser_open(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_expr_parser **parser) { grn_ts_expr_parser *new_parser = GRN_MALLOCN(grn_ts_expr_parser, 1); @@ -557,8 +454,7 @@ grn_ts_expr_parser_open(grn_ctx *ctx, grn_ts_expr *expr, return GRN_SUCCESS; } -/* grn_ts_expr_parser_close() destroys a parser. */ -static void +void grn_ts_expr_parser_close(grn_ctx *ctx, grn_ts_expr_parser *parser) { grn_ts_expr_parser_fin(ctx, parser); GRN_FREE(parser); @@ -1364,11 +1260,7 @@ grn_ts_expr_parser_analyze(grn_ctx *ctx, grn_ts_expr_parser *parser) { return GRN_SUCCESS; } -/* - * grn_ts_expr_parser_parse() parses a string and pushes nodes into an - * expression. - */ -static grn_rc +grn_rc grn_ts_expr_parser_parse(grn_ctx *ctx, grn_ts_expr_parser *parser, const char *str_ptr, size_t str_size) { grn_rc rc; @@ -1391,1001 +1283,3 @@ grn_ts_expr_parser_parse(grn_ctx *ctx, grn_ts_expr_parser *parser, } return GRN_SUCCESS; } - -/*------------------------------------------------------------- - * grn_ts_expr_bridge. - */ - -/* grn_ts_expr_bridge_init() initializes a bridge. */ -static void -grn_ts_expr_bridge_init(grn_ctx *ctx, grn_ts_expr_bridge *bridge) { - memset(bridge, 0, sizeof(*bridge)); - bridge->src_table = NULL; - bridge->dest_table = NULL; -} - -/* grn_ts_expr_bridge_fin() finalizes a bridge. */ -static void -grn_ts_expr_bridge_fin(grn_ctx *ctx, grn_ts_expr_bridge *bridge) { - if (bridge->dest_table) { - grn_obj_unlink(ctx, bridge->dest_table); - } - /* Note: bridge->src_table does not increment a reference count. */ -} - -/*------------------------------------------------------------- - * grn_ts_expr. - */ - -/* grn_ts_expr_init() initializes an expression. */ -static void -grn_ts_expr_init(grn_ctx *ctx, grn_ts_expr *expr) { - memset(expr, 0, sizeof(*expr)); - expr->table = NULL; - expr->curr_table = NULL; - expr->root = NULL; - expr->stack = NULL; - expr->bridges = NULL; -} - -/* grn_ts_expr_fin() finalizes an expression. */ -static void -grn_ts_expr_fin(grn_ctx *ctx, grn_ts_expr *expr) { - size_t i; - if (expr->bridges) { - for (i = 0; i < expr->n_bridges; i++) { - grn_ts_expr_bridge_fin(ctx, &expr->bridges[i]); - } - GRN_FREE(expr->bridges); - } - if (expr->stack) { - for (i = 0; i < expr->stack_depth; i++) { - if (expr->stack[i]) { - grn_ts_expr_node_close(ctx, expr->stack[i]); - } - } - GRN_FREE(expr->stack); - } - /* Note: expr->curr_table does not increment a reference count. */ - if (expr->table) { - grn_obj_unlink(ctx, expr->table); - } -} - -grn_rc -grn_ts_expr_open(grn_ctx *ctx, grn_obj *table, grn_ts_expr **expr) { - grn_rc rc; - grn_ts_expr *new_expr; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!table || !grn_ts_obj_is_table(ctx, table) || !expr) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - new_expr = GRN_MALLOCN(grn_ts_expr, 1); - if (!new_expr) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1", - sizeof(grn_ts_expr)); - } - rc = grn_ts_obj_increment_ref_count(ctx, table); - if (rc != GRN_SUCCESS) { - GRN_FREE(new_expr); - return rc; - } - grn_ts_expr_init(ctx, new_expr); - new_expr->table = table; - new_expr->curr_table = table; - *expr = new_expr; - return GRN_SUCCESS; -} - -grn_rc -grn_ts_expr_parse(grn_ctx *ctx, grn_obj *table, - const char *str_ptr, size_t str_size, grn_ts_expr **expr) { - grn_rc rc; - grn_ts_expr *new_expr; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!table || !grn_ts_obj_is_table(ctx, table) || - (!str_ptr && str_size) || !expr) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - rc = grn_ts_expr_open(ctx, table, &new_expr); - if (rc != GRN_SUCCESS) { - return rc; - } - rc = grn_ts_expr_push(ctx, new_expr, str_ptr, str_size); - if (rc == GRN_SUCCESS) { - rc = grn_ts_expr_complete(ctx, new_expr); - } - if (rc != GRN_SUCCESS) { - grn_ts_expr_close(ctx, new_expr); - return rc; - } - *expr = new_expr; - return GRN_SUCCESS; -} - -grn_rc -grn_ts_expr_close(grn_ctx *ctx, grn_ts_expr *expr) { - if (!ctx || !expr) { - return GRN_INVALID_ARGUMENT; - } - grn_ts_expr_fin(ctx, expr); - GRN_FREE(expr); - return GRN_SUCCESS; -} - -grn_obj * -grn_ts_expr_get_table(grn_ctx *ctx, grn_ts_expr *expr) { - if (!ctx || !expr) { - return NULL; - } - /* The reference counting will never fail in practice. */ - if (grn_ts_obj_increment_ref_count(ctx, expr->table) != GRN_SUCCESS) { - return NULL; - } - return expr->table; -} - -grn_ts_expr_type -grn_ts_expr_get_type(grn_ctx *ctx, grn_ts_expr *expr) { - return (!ctx || !expr) ? GRN_TS_EXPR_BROKEN : expr->type; -} - -grn_ts_data_kind -grn_ts_expr_get_data_kind(grn_ctx *ctx, grn_ts_expr *expr) { - return (!ctx || !expr) ? GRN_TS_VOID : expr->data_kind; -} - -grn_ts_data_type -grn_ts_expr_get_data_type(grn_ctx *ctx, grn_ts_expr *expr) { - return (!ctx || !expr) ? GRN_DB_VOID : expr->data_type; -} - -grn_ts_expr_node * -grn_ts_expr_get_root(grn_ctx *ctx, grn_ts_expr *expr) { - return (!ctx || !expr) ? NULL : expr->root; -} - -/* grn_ts_expr_reserve_stack() extends a stack. */ -static grn_rc -grn_ts_expr_reserve_stack(grn_ctx *ctx, grn_ts_expr *expr) { - size_t i, n_bytes, new_size; - grn_ts_expr_node **new_stack; - if (expr->stack_depth < expr->stack_size) { - return GRN_SUCCESS; - } - new_size = expr->stack_size ? (expr->stack_size * 2) : 1; - n_bytes = sizeof(grn_ts_expr_node *) * new_size; - new_stack = GRN_REALLOC(expr->stack, n_bytes); - if (!new_stack) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_REALLOC failed: %zu", - n_bytes); - } - for (i = expr->stack_size; i < new_size; i++) { - new_stack[i] = NULL; - } - expr->stack = new_stack; - expr->stack_size = new_size; - return GRN_SUCCESS; -} - -/* grn_ts_expr_deref() dereferences a node. */ -static grn_rc -grn_ts_expr_deref(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_expr_node **node_ptr) { - grn_ts_expr_node *node = *node_ptr; - while (node->data_kind == GRN_TS_REF) { - grn_rc rc; - grn_ts_expr_node *key_node, *bridge_node; - grn_id table_id = node->data_type; - grn_obj *table = grn_ctx_at(ctx, table_id); - if (!table) { - return GRN_OBJECT_CORRUPT; - } - if (!grn_ts_obj_is_table(ctx, table)) { - grn_obj_unlink(ctx, table); - return GRN_OBJECT_CORRUPT; - } - rc = grn_ts_expr_key_node_open(ctx, table, &key_node); - grn_obj_unlink(ctx, table); - if (rc != GRN_SUCCESS) { - return rc; - } - rc = grn_ts_expr_bridge_node_open(ctx, node, key_node, &bridge_node); - if (rc != GRN_SUCCESS) { - return rc; - } - node = bridge_node; - } - *node_ptr = node; - return GRN_SUCCESS; -} - -grn_rc -grn_ts_expr_push(grn_ctx *ctx, grn_ts_expr *expr, - const char *str_ptr, size_t str_size) { - grn_rc rc; - grn_ts_expr_parser *parser; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) || - (!str_ptr && str_size)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - rc = grn_ts_expr_parser_open(ctx, expr, &parser); - if (rc != GRN_SUCCESS) { - return rc; - } - rc = grn_ts_expr_parser_parse(ctx, parser, str_ptr, str_size); - grn_ts_expr_parser_close(ctx, parser); - return rc; -} - -grn_rc -grn_ts_expr_push_name(grn_ctx *ctx, grn_ts_expr *expr, - const char *name_ptr, size_t name_size) { - grn_obj *column; - grn_ts_str name = { name_ptr, name_size }; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) || - !grn_ts_str_is_name(name)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - if (grn_ts_str_is_id_name(name)) { - return grn_ts_expr_push_id(ctx, expr); - } - if (grn_ts_str_is_score_name(name)) { - return grn_ts_expr_push_score(ctx, expr); - } - if (grn_ts_str_is_key_name(name)) { - return grn_ts_expr_push_key(ctx, expr); - } - if (grn_ts_str_is_value_name(name)) { - return grn_ts_expr_push_value(ctx, expr); - } - /* grn_obj_column() returns a column or accessor. */ - column = grn_obj_column(ctx, expr->curr_table, name.ptr, name.size); - if (!column) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "object not found: \"%.*s\"", - (int)name.size, name.ptr); - } - return grn_ts_expr_push_obj(ctx, expr, column); -} - -#define GRN_TS_EXPR_PUSH_BULK_CASE(TYPE, kind)\ - case GRN_DB_ ## TYPE: {\ - return grn_ts_expr_push_ ## kind(ctx, expr, GRN_ ## TYPE ## _VALUE(obj));\ - } -/* grn_ts_expr_push_bulk() pushes a scalar. */ -static grn_rc -grn_ts_expr_push_bulk(grn_ctx *ctx, grn_ts_expr *expr, grn_obj *obj) { - switch (obj->header.domain) { - GRN_TS_EXPR_PUSH_BULK_CASE(BOOL, bool) - GRN_TS_EXPR_PUSH_BULK_CASE(INT8, int) - GRN_TS_EXPR_PUSH_BULK_CASE(INT16, int) - GRN_TS_EXPR_PUSH_BULK_CASE(INT32, int) - GRN_TS_EXPR_PUSH_BULK_CASE(INT64, int) - GRN_TS_EXPR_PUSH_BULK_CASE(UINT8, int) - GRN_TS_EXPR_PUSH_BULK_CASE(UINT16, int) - GRN_TS_EXPR_PUSH_BULK_CASE(UINT32, int) - /* The behavior is undefined if a value is greater than 2^63 - 1. */ - GRN_TS_EXPR_PUSH_BULK_CASE(UINT64, int) - GRN_TS_EXPR_PUSH_BULK_CASE(FLOAT, float) - GRN_TS_EXPR_PUSH_BULK_CASE(TIME, time) - case GRN_DB_SHORT_TEXT: - case GRN_DB_TEXT: - case GRN_DB_LONG_TEXT: { - grn_ts_text value = { GRN_TEXT_VALUE(obj), GRN_TEXT_LEN(obj) }; - return grn_ts_expr_push_text(ctx, expr, value); - } - case GRN_DB_TOKYO_GEO_POINT: { - grn_ts_geo value; - GRN_GEO_POINT_VALUE(obj, value.latitude, value.longitude); - return grn_ts_expr_push_tokyo_geo(ctx, expr, value); - } - case GRN_DB_WGS84_GEO_POINT: { - grn_ts_geo value; - GRN_GEO_POINT_VALUE(obj, value.latitude, value.longitude); - return grn_ts_expr_push_wgs84_geo(ctx, expr, value); - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "not bulk"); - } - } -} -#undef GRN_TS_EXPR_PUSH_BULK_CASE - -#define GRN_TS_EXPR_PUSH_UVECTOR_CASE(TYPE, kind)\ - case GRN_DB_ ## TYPE: {\ - grn_ts_ ## kind ##_vector value = { (grn_ts_ ## kind *)GRN_BULK_HEAD(obj),\ - grn_uvector_size(ctx, obj) };\ - return grn_ts_expr_push_ ## kind ## _vector(ctx, expr, value);\ - } -#define GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST(TYPE, kind)\ - case GRN_DB_ ## TYPE: {\ - size_t i;\ - grn_rc rc;\ - grn_ts_ ## kind *buf;\ - grn_ts_ ## kind ## _vector value = { NULL, grn_uvector_size(ctx, obj) };\ - if (!value.size) {\ - return grn_ts_expr_push_ ## kind ## _vector(ctx, expr, value);\ - }\ - buf = GRN_MALLOCN(grn_ts_ ## kind, value.size);\ - if (!buf) {\ - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE,\ - "GRN_MALLOCN failed: %zu x 1",\ - sizeof(grn_ts_ ## kind));\ - }\ - for (i = 0; i < value.size; i++) {\ - buf[i] = GRN_ ## TYPE ##_VALUE_AT(obj, i);\ - }\ - value.ptr = buf;\ - rc = grn_ts_expr_push_ ## kind ## _vector(ctx, expr, value);\ - GRN_FREE(buf);\ - return rc;\ - } -/* grn_ts_expr_push_uvector() pushes an array of fixed-size values. */ -static grn_rc -grn_ts_expr_push_uvector(grn_ctx *ctx, grn_ts_expr *expr, grn_obj *obj) { - switch (obj->header.domain) { - GRN_TS_EXPR_PUSH_UVECTOR_CASE(BOOL, bool) - GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST(INT8, int) - GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST(INT16, int) - GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST(INT32, int) - GRN_TS_EXPR_PUSH_UVECTOR_CASE(INT64, int) - GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST(UINT8, int) - GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST(UINT16, int) - GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST(UINT32, int) - GRN_TS_EXPR_PUSH_UVECTOR_CASE(UINT64, int) - GRN_TS_EXPR_PUSH_UVECTOR_CASE(TIME, time) - GRN_TS_EXPR_PUSH_UVECTOR_CASE(TOKYO_GEO_POINT, tokyo_geo) - GRN_TS_EXPR_PUSH_UVECTOR_CASE(WGS84_GEO_POINT, wgs84_geo) - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data type: %d", - obj->header.domain); - } - } -} -#undef GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST -#undef GRN_TS_EXPR_PUSH_UVECTOR_CASE - -/* grn_ts_expr_push_vector() pushes an array of texts. */ -static grn_rc -grn_ts_expr_push_vector(grn_ctx *ctx, grn_ts_expr *expr, grn_obj *obj) { - switch (obj->header.domain) { - case GRN_DB_SHORT_TEXT: - case GRN_DB_TEXT: - case GRN_DB_LONG_TEXT: { - size_t i; - grn_rc rc; - grn_ts_text *buf; - grn_ts_text_vector value = { NULL, grn_vector_size(ctx, obj) }; - if (!value.size) { - return grn_ts_expr_push_text_vector(ctx, expr, value); - } - buf = GRN_MALLOCN(grn_ts_text, value.size); - if (!buf) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, - "GRN_MALLOCN failed: %zu x %zu", - sizeof(grn_ts_text), value.size); - } - for (i = 0; i < value.size; i++) { - buf[i].size = grn_vector_get_element(ctx, obj, i, &buf[i].ptr, - NULL, NULL); - } - value.ptr = buf; - rc = grn_ts_expr_push_text_vector(ctx, expr, value); - GRN_FREE(buf); - return rc; - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data type: %d", - obj->header.domain); - } - } -} - -static grn_rc -grn_ts_expr_push_single_accessor(grn_ctx *ctx, grn_ts_expr *expr, - grn_accessor *accessor) { - switch (accessor->action) { - case GRN_ACCESSOR_GET_ID: { - return grn_ts_expr_push_id(ctx, expr); - } - case GRN_ACCESSOR_GET_SCORE: { - return grn_ts_expr_push_score(ctx, expr); - } - case GRN_ACCESSOR_GET_KEY: { - if (accessor->obj != expr->curr_table) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "table conflict"); - } - return grn_ts_expr_push_key(ctx, expr); - } - case GRN_ACCESSOR_GET_VALUE: { - if (accessor->obj != expr->curr_table) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "table conflict"); - } - return grn_ts_expr_push_value(ctx, expr); - } - case GRN_ACCESSOR_GET_COLUMN_VALUE: { - return grn_ts_expr_push_column(ctx, expr, accessor->obj); - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid accessor action: %d", - accessor->action); - } - } -} - -static grn_rc -grn_ts_expr_push_accessor(grn_ctx *ctx, grn_ts_expr *expr, - grn_accessor *accessor) { - grn_rc rc = grn_ts_expr_push_single_accessor(ctx, expr, accessor); - if (rc != GRN_SUCCESS) { - return rc; - } - for (accessor = accessor->next; accessor; accessor = accessor->next) { - rc = grn_ts_expr_begin_subexpr(ctx, expr); - if (rc != GRN_SUCCESS) { - return rc; - } - rc = grn_ts_expr_push_single_accessor(ctx, expr, accessor); - if (rc != GRN_SUCCESS) { - return rc; - } - rc = grn_ts_expr_end_subexpr(ctx, expr); - if (rc != GRN_SUCCESS) { - return rc; - } - } - return GRN_SUCCESS; -} - -grn_rc -grn_ts_expr_push_obj(grn_ctx *ctx, grn_ts_expr *expr, grn_obj *obj) { - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) || !obj) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - switch (obj->header.type) { - case GRN_BULK: { - return grn_ts_expr_push_bulk(ctx, expr, obj); - } - case GRN_UVECTOR: { - return grn_ts_expr_push_uvector(ctx, expr, obj); - } - case GRN_VECTOR: { - return grn_ts_expr_push_vector(ctx, expr, obj); - } - case GRN_ACCESSOR: { - return grn_ts_expr_push_accessor(ctx, expr, (grn_accessor *)obj); - } - case GRN_COLUMN_FIX_SIZE: - case GRN_COLUMN_VAR_SIZE: { - return grn_ts_expr_push_column(ctx, expr, obj); - } - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid object type: %d", - obj->header.type); - } - } -} - -grn_rc -grn_ts_expr_push_id(grn_ctx *ctx, grn_ts_expr *expr) { - grn_rc rc; - grn_ts_expr_node *node; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - rc = grn_ts_expr_reserve_stack(ctx, expr); - if (rc == GRN_SUCCESS) { - rc = grn_ts_expr_id_node_open(ctx, &node); - if (rc == GRN_SUCCESS) { - expr->stack[expr->stack_depth++] = node; - } - } - return rc; -} - -grn_rc -grn_ts_expr_push_score(grn_ctx *ctx, grn_ts_expr *expr) { - grn_rc rc; - grn_ts_expr_node *node; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - rc = grn_ts_expr_reserve_stack(ctx, expr); - if (rc == GRN_SUCCESS) { - rc = grn_ts_expr_score_node_open(ctx, &node); - if (rc == GRN_SUCCESS) { - expr->stack[expr->stack_depth++] = node; - } - } - return rc; -} - -grn_rc -grn_ts_expr_push_key(grn_ctx *ctx, grn_ts_expr *expr) { - grn_rc rc; - grn_ts_expr_node *node; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - rc = grn_ts_expr_reserve_stack(ctx, expr); - if (rc == GRN_SUCCESS) { - rc = grn_ts_expr_key_node_open(ctx, expr->curr_table, &node); - if (rc == GRN_SUCCESS) { - expr->stack[expr->stack_depth++] = node; - } - } - return rc; -} - -grn_rc -grn_ts_expr_push_value(grn_ctx *ctx, grn_ts_expr *expr) { - grn_rc rc; - grn_ts_expr_node *node; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - rc = grn_ts_expr_reserve_stack(ctx, expr); - if (rc == GRN_SUCCESS) { - rc = grn_ts_expr_value_node_open(ctx, expr->curr_table, &node); - if (rc == GRN_SUCCESS) { - expr->stack[expr->stack_depth++] = node; - } - } - return rc; -} - -#define GRN_TS_EXPR_PUSH_CONST_CASE(KIND, kind)\ - case GRN_TS_ ## KIND: {\ - return grn_ts_expr_push_ ## kind(ctx, expr,\ - *(const grn_ts_ ## kind *)value);\ - } -grn_rc -grn_ts_expr_push_const(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_data_kind kind, const void *value) { - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) || !value) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - switch (kind) { - GRN_TS_EXPR_PUSH_CONST_CASE(BOOL, bool) - GRN_TS_EXPR_PUSH_CONST_CASE(INT, int) - GRN_TS_EXPR_PUSH_CONST_CASE(FLOAT, float) - GRN_TS_EXPR_PUSH_CONST_CASE(TIME, time) - GRN_TS_EXPR_PUSH_CONST_CASE(TEXT, text) - GRN_TS_EXPR_PUSH_CONST_CASE(GEO, geo) - GRN_TS_EXPR_PUSH_CONST_CASE(BOOL_VECTOR, bool_vector) - GRN_TS_EXPR_PUSH_CONST_CASE(INT_VECTOR, int_vector) - GRN_TS_EXPR_PUSH_CONST_CASE(FLOAT_VECTOR, float_vector) - GRN_TS_EXPR_PUSH_CONST_CASE(TIME_VECTOR, time_vector) - GRN_TS_EXPR_PUSH_CONST_CASE(TEXT_VECTOR, text_vector) - GRN_TS_EXPR_PUSH_CONST_CASE(GEO_VECTOR, geo_vector) - default: { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", kind); - } - } -} -#undef GRN_TS_EXPR_PUSH_CONST_CASE - -grn_rc -grn_ts_expr_push_column(grn_ctx *ctx, grn_ts_expr *expr, grn_obj *column) { - grn_rc rc; - grn_ts_expr_node *node; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) || - !column || !grn_ts_obj_is_column(ctx, column) || - (DB_OBJ(expr->curr_table)->id != column->header.domain)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - rc = grn_ts_expr_reserve_stack(ctx, expr); - if (rc == GRN_SUCCESS) { - rc = grn_ts_expr_column_node_open(ctx, column, &node); - if (rc == GRN_SUCCESS) { - expr->stack[expr->stack_depth++] = node; - } - } - return rc; -} - -grn_rc -grn_ts_expr_push_op(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_op_type op_type) { - grn_rc rc; - grn_ts_expr_node **args, *node; - size_t i, n_args; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE)) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - n_args = grn_ts_op_get_n_args(op_type); - if (!n_args) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid #arguments: %zu", n_args); - } - if (n_args > expr->stack_depth) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid #arguments: %zu, %zu", - n_args, expr->stack_depth); - } - /* Arguments are the top n_args nodes in the stack. */ - args = &expr->stack[expr->stack_depth - n_args]; - for (i = 0; i < n_args; i++) { - /* - * FIXME: Operators "==" and "!=" should compare arguments as references - * if possible. - */ - rc = grn_ts_expr_deref(ctx, expr, &args[i]); - if (rc != GRN_SUCCESS) { - return rc; - } - } - expr->stack_depth -= n_args; - rc = grn_ts_expr_op_node_open(ctx, op_type, args, n_args, &node); - if (rc == GRN_SUCCESS) { - expr->stack[expr->stack_depth++] = node; - } - return rc; -} - -#define GRN_TS_EXPR_PUSH_CONST(KIND, kind)\ - grn_rc rc;\ - grn_ts_expr_node *node;\ - if (!ctx) {\ - return GRN_INVALID_ARGUMENT;\ - }\ - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) ||\ - !grn_ts_ ## kind ## _is_valid(value)) {\ - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument");\ - }\ - rc = grn_ts_expr_reserve_stack(ctx, expr);\ - if (rc == GRN_SUCCESS) {\ - rc = grn_ts_expr_const_node_open(ctx, GRN_TS_ ## KIND, &value, &node);\ - if (rc == GRN_SUCCESS) {\ - expr->stack[expr->stack_depth++] = node;\ - }\ - } -grn_rc -grn_ts_expr_push_bool(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_bool value) { - GRN_TS_EXPR_PUSH_CONST(BOOL, bool) - return rc; -} - -grn_rc -grn_ts_expr_push_int(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_int value) { - GRN_TS_EXPR_PUSH_CONST(INT, int) - return rc; -} - -grn_rc -grn_ts_expr_push_float(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_float value) { - GRN_TS_EXPR_PUSH_CONST(FLOAT, float) - return rc; -} - -grn_rc -grn_ts_expr_push_time(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_time value) { - GRN_TS_EXPR_PUSH_CONST(TIME, time) - return rc; -} - -grn_rc -grn_ts_expr_push_text(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_text value) { - GRN_TS_EXPR_PUSH_CONST(TEXT, text) - return rc; -} - -grn_rc -grn_ts_expr_push_geo(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_geo value) { - GRN_TS_EXPR_PUSH_CONST(GEO, geo) - return rc; -} - -grn_rc -grn_ts_expr_push_tokyo_geo(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_geo value) { - GRN_TS_EXPR_PUSH_CONST(GEO, geo) - node->data_type = GRN_DB_TOKYO_GEO_POINT; - return rc; -} - -grn_rc -grn_ts_expr_push_wgs84_geo(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_geo value) { - GRN_TS_EXPR_PUSH_CONST(GEO, geo) - node->data_type = GRN_DB_WGS84_GEO_POINT; - return rc; -} - -grn_rc -grn_ts_expr_push_bool_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_bool_vector value) { - GRN_TS_EXPR_PUSH_CONST(BOOL_VECTOR, bool_vector) - return rc; -} - -grn_rc -grn_ts_expr_push_int_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_int_vector value) { - GRN_TS_EXPR_PUSH_CONST(INT_VECTOR, int_vector) - return rc; -} - -grn_rc -grn_ts_expr_push_float_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_float_vector value) { - GRN_TS_EXPR_PUSH_CONST(FLOAT_VECTOR, float_vector) - return rc; -} - -grn_rc -grn_ts_expr_push_time_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_time_vector value) { - GRN_TS_EXPR_PUSH_CONST(TIME_VECTOR, time_vector) - return rc; -} - -grn_rc -grn_ts_expr_push_text_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_text_vector value) { - GRN_TS_EXPR_PUSH_CONST(TEXT_VECTOR, text_vector) - return rc; -} - -grn_rc -grn_ts_expr_push_geo_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_geo_vector value) { - GRN_TS_EXPR_PUSH_CONST(GEO_VECTOR, geo_vector) - return rc; -} - -grn_rc -grn_ts_expr_push_tokyo_geo_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_geo_vector value) { - GRN_TS_EXPR_PUSH_CONST(GEO_VECTOR, geo_vector) - node->data_type = GRN_DB_TOKYO_GEO_POINT; - return rc; -} - -grn_rc -grn_ts_expr_push_wgs84_geo_vector(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_geo_vector value) { - GRN_TS_EXPR_PUSH_CONST(GEO_VECTOR, geo_vector) - node->data_type = GRN_DB_TOKYO_GEO_POINT; - return rc; -} -#undef GRN_TS_EXPR_PUSH_CONST - -/* grn_ts_expr_reserve_bridges() extends a bridge buffer for a new bridge. */ -static grn_rc -grn_ts_expr_reserve_bridges(grn_ctx *ctx, grn_ts_expr *expr) { - size_t n_bytes, new_max_n_bridges; - grn_ts_expr_bridge *new_bridges; - if (expr->n_bridges < expr->max_n_bridges) { - return GRN_SUCCESS; - } - new_max_n_bridges = expr->n_bridges * 2; - if (!new_max_n_bridges) { - new_max_n_bridges = 1; - } - n_bytes = sizeof(grn_ts_expr_bridge) * new_max_n_bridges; - new_bridges = (grn_ts_expr_bridge *)GRN_REALLOC(expr->bridges, n_bytes); - if (!new_bridges) { - GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_REALLOC failed: %zu", - n_bytes); - } - expr->bridges = new_bridges; - expr->max_n_bridges = new_max_n_bridges; - return GRN_SUCCESS; -} - -grn_rc -grn_ts_expr_begin_subexpr(grn_ctx *ctx, grn_ts_expr *expr) { - grn_rc rc; - grn_obj *obj; - grn_ts_expr_node *node; - grn_ts_expr_bridge *bridge; - if (!ctx) { - return GRN_INVALID_ARGUMENT; - } - if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) || !expr->stack_depth) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); - } - - /* Check whehter or not the latest node refers to a table. */ - node = expr->stack[expr->stack_depth - 1]; - if ((node->data_kind & ~GRN_TS_VECTOR_FLAG) != GRN_TS_REF) { - GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", - node->data_kind); - } - obj = grn_ctx_at(ctx, node->data_type); - if (!obj) { - GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "grn_ctx_at failed: %d", - node->data_type); - } - if (!grn_ts_obj_is_table(ctx, obj)) { - grn_obj_unlink(ctx, obj); - GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "not table: %d", node->data_type); - } - - /* Creates a bridge to a subexpression. */ - rc = grn_ts_expr_reserve_bridges(ctx, expr); - if (rc != GRN_SUCCESS) { - grn_obj_unlink(ctx, obj); - return rc; - } - bridge = &expr->bridges[expr->n_bridges++]; - grn_ts_expr_bridge_init(ctx, bridge); - bridge->src_table = expr->curr_table; - bridge->dest_table = obj; - bridge->stack_depth = expr->stack_depth; - expr->curr_table = bridge->dest_table; - return GRN_SUCCESS; -} - -grn_rc -grn_ts_expr_end_subexpr(grn_ctx *ctx, grn_ts_expr *expr) { - grn_rc rc; - grn_ts_expr_node **args, *node; - grn_ts_expr_bridge *bridge; - if (!ctx || !expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) || - (expr->stack_depth < 2) || !expr->n_bridges) { - return GRN_INVALID_ARGUMENT; - } - /* Check whehter or not the subexpression is complete.*/ - bridge = &expr->bridges[expr->n_bridges - 1]; - if (expr->stack_depth != (bridge->stack_depth + 1)) { - return GRN_INVALID_ARGUMENT; - } - /* Creates a bridge node. */ - args = &expr->stack[expr->stack_depth - 2]; - rc = grn_ts_expr_bridge_node_open(ctx, args[0], args[1], &node); - if (rc != GRN_SUCCESS) { - return rc; - } - /* Note: grn_ts_expr_reserve_stack() is not required. */ - expr->stack_depth -= 2; - expr->stack[expr->stack_depth++] = node; - expr->curr_table = bridge->src_table; - grn_ts_expr_bridge_fin(ctx, bridge); - expr->n_bridges--; - return GRN_SUCCESS; -} - -grn_rc -grn_ts_expr_complete(grn_ctx *ctx, grn_ts_expr *expr) { - grn_rc rc; - grn_ts_expr_node *root; - if (!ctx || !expr || (expr->type != GRN_TS_EXPR_INCOMPLETE)) { - return GRN_INVALID_ARGUMENT; - } - if (expr->stack_depth != 1) { - return GRN_INVALID_ARGUMENT; - } - rc = grn_ts_expr_deref(ctx, expr, &expr->stack[0]); - if (rc != GRN_SUCCESS) { - return rc; - } - root = expr->stack[0]; - switch (root->data_kind) { - case GRN_TS_REF: - case GRN_TS_REF_VECTOR: { - return GRN_INVALID_ARGUMENT; - } - default: { - break; - } - } - switch (root->type) { - case GRN_TS_EXPR_ID_NODE: { - expr->type = GRN_TS_EXPR_ID; - break; - } - case GRN_TS_EXPR_SCORE_NODE: { - expr->type = GRN_TS_EXPR_SCORE; - break; - } - case GRN_TS_EXPR_KEY_NODE: - case GRN_TS_EXPR_VALUE_NODE: { - expr->type = GRN_TS_EXPR_VARIABLE; - break; - } - case GRN_TS_EXPR_CONST_NODE: { - expr->type = GRN_TS_EXPR_CONST; - break; - } - case GRN_TS_EXPR_COLUMN_NODE: - case GRN_TS_EXPR_OP_NODE: - case GRN_TS_EXPR_BRIDGE_NODE: { - expr->type = GRN_TS_EXPR_VARIABLE; - break; - } - default: { - return GRN_INVALID_ARGUMENT; - } - } - expr->data_type = root->data_type; - expr->data_kind = root->data_kind; - expr->root = root; - return GRN_SUCCESS; -} - -grn_rc -grn_ts_expr_evaluate_to_buf(grn_ctx *ctx, grn_ts_expr *expr, - const grn_ts_record *in, size_t n_in, - grn_ts_buf *out) { - if (!ctx || !expr || (expr->type == GRN_TS_EXPR_INCOMPLETE) || - (expr->type == GRN_TS_EXPR_BROKEN) || (!in && n_in) || !out) { - return GRN_INVALID_ARGUMENT; - } - if (!n_in) { - return GRN_SUCCESS; - } - return grn_ts_expr_node_evaluate_to_buf(ctx, expr->root, in, n_in, out); -} - -grn_rc -grn_ts_expr_evaluate(grn_ctx *ctx, grn_ts_expr *expr, - const grn_ts_record *in, size_t n_in, void *out) { - if (!ctx || !expr || (expr->type == GRN_TS_EXPR_INCOMPLETE) || - (expr->type == GRN_TS_EXPR_BROKEN) || (!in && n_in) || (n_in && !out)) { - return GRN_INVALID_ARGUMENT; - } - if (!n_in) { - return GRN_SUCCESS; - } - return grn_ts_expr_node_evaluate(ctx, expr->root, in, n_in, out); -} - -grn_rc -grn_ts_expr_filter(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_record *in, size_t n_in, - grn_ts_record *out, size_t *n_out) { - if (!ctx || !expr || (expr->type == GRN_TS_EXPR_INCOMPLETE) || - (expr->type == GRN_TS_EXPR_BROKEN) || (!in && n_in) || - !out || !n_out) { - return GRN_INVALID_ARGUMENT; - } - if (!n_in) { - *n_out = 0; - return GRN_SUCCESS; - } - return grn_ts_expr_node_filter(ctx, expr->root, in, n_in, out, n_out); -} - -grn_rc -grn_ts_expr_adjust(grn_ctx *ctx, grn_ts_expr *expr, - grn_ts_record *io, size_t n_io) { - if (!ctx || !expr || (expr->type == GRN_TS_EXPR_INCOMPLETE) || - (expr->type == GRN_TS_EXPR_BROKEN) || (!io && n_io)) { - return GRN_INVALID_ARGUMENT; - } - if (!n_io) { - return GRN_SUCCESS; - } - return grn_ts_expr_node_adjust(ctx, expr->root, io, n_io); -} Added: lib/ts/ts_expr_parser.h (+49 -0) 100644 =================================================================== --- /dev/null +++ lib/ts/ts_expr_parser.h 2015-11-12 12:33:14 +0900 (e92d54c) @@ -0,0 +1,49 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef GRN_TS_EXPR_PARSER_H +#define GRN_TS_EXPR_PARSER_H + +#include "ts_expr.h" +#include "ts_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct grn_ts_expr_parser grn_ts_expr_parser; + +/* grn_ts_expr_parser_open() creates a parser. */ +grn_rc grn_ts_expr_parser_open(grn_ctx *ctx, grn_ts_expr *expr, + grn_ts_expr_parser **parser); + +/* grn_ts_expr_parser_close() destroys a parser. */ +void grn_ts_expr_parser_close(grn_ctx *ctx, grn_ts_expr_parser *parser); + +/* + * grn_ts_expr_parser_parse() parses a string and pushes nodes into an + * expression. + */ +grn_rc grn_ts_expr_parser_parse(grn_ctx *ctx, grn_ts_expr_parser *parser, + const char *str_ptr, size_t str_size); + +#ifdef __cplusplus +} +#endif + +#endif /* GRN_TS_EXPR_PARSER_H */