/* -*- mode: c; c-basic-offset: 2 -*- */ %name grn_expr_parser %token_prefix GRN_EXPR_TOKEN_ %include { #ifdef assert # undef assert #endif #define assert GRN_ASSERT } %token_type { int } %type suppress_unused_variable_warning { void * } %destructor suppress_unused_variable_warning { (void)efsi; } %extra_argument { efs_info *efsi } %syntax_error { { grn_ctx *ctx = efsi->ctx; grn_obj message; GRN_TEXT_INIT(&message, 0); GRN_TEXT_PUT(ctx, &message, efsi->str, efsi->cur - efsi->str); GRN_TEXT_PUTC(ctx, &message, '|'); if (efsi->cur < efsi->str_end) { GRN_TEXT_PUTC(ctx, &message, efsi->cur[0]); GRN_TEXT_PUTC(ctx, &message, '|'); GRN_TEXT_PUT(ctx, &message, efsi->cur + 1, efsi->str_end - (efsi->cur + 1)); } else { GRN_TEXT_PUTC(ctx, &message, '|'); } if (ctx->rc == GRN_SUCCESS) { ERR(GRN_SYNTAX_ERROR, "Syntax error: <%.*s>", (int)GRN_TEXT_LEN(&message), GRN_TEXT_VALUE(&message)); } else { ERR(ctx->rc, "Syntax error: <%.*s>: %s", (int)GRN_TEXT_LEN(&message), GRN_TEXT_VALUE(&message), ctx->errbuf); } GRN_OBJ_FIN(ctx, &message); } } input ::= query. input ::= expression. input ::= START_OUTPUT_COLUMNS output_columns. input ::= START_ADJUSTER adjuster. query ::= query_element. query ::= query query_element. { grn_expr_append_op(efsi->ctx, efsi->e, grn_int32_value_at(&efsi->op_stack, -1), 2); } query ::= query LOGICAL_AND query_element. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_AND, 2); } query ::= query LOGICAL_AND_NOT query_element.{ grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_AND_NOT, 2); } query ::= query LOGICAL_OR query_element.{ grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_OR, 2); } query ::= query NEGATIVE query_element.{ int weight; GRN_INT32_POP(&efsi->weight_stack, weight); grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_ADJUST, 2); } query_element ::= QSTRING. query_element ::= PARENL query PARENR. query_element ::= ADJUST query_element.{ int weight; GRN_INT32_POP(&efsi->weight_stack, weight); } query_element ::= RELATIVE_OP query_element.{ int mode; GRN_INT32_POP(&efsi->mode_stack, mode); } query_element ::= IDENTIFIER RELATIVE_OP query_element. { int mode; grn_obj *c; GRN_PTR_POP(&efsi->column_stack, c); GRN_INT32_POP(&efsi->mode_stack, mode); switch (mode) { case GRN_OP_NEAR : case GRN_OP_NEAR2 : { int max_interval; GRN_INT32_POP(&efsi->max_interval_stack, max_interval); } break; case GRN_OP_SIMILAR : { int similarity_threshold; GRN_INT32_POP(&efsi->similarity_threshold_stack, similarity_threshold); } break; default : break; } } query_element ::= BRACEL expression BRACER. { efsi->flags = efsi->default_flags; } query_element ::= EVAL primary_expression. { efsi->flags = efsi->default_flags; } expression ::= assignment_expression. expression ::= expression COMMA assignment_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_COMMA, 2); } assignment_expression ::= conditional_expression. assignment_expression ::= lefthand_side_expression ASSIGN assignment_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_ASSIGN, 2); } assignment_expression ::= lefthand_side_expression STAR_ASSIGN assignment_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_STAR_ASSIGN, 2); } assignment_expression ::= lefthand_side_expression SLASH_ASSIGN assignment_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SLASH_ASSIGN, 2); } assignment_expression ::= lefthand_side_expression MOD_ASSIGN assignment_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MOD_ASSIGN, 2); } assignment_expression ::= lefthand_side_expression PLUS_ASSIGN assignment_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PLUS_ASSIGN, 2); } assignment_expression ::= lefthand_side_expression MINUS_ASSIGN assignment_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MINUS_ASSIGN, 2); } assignment_expression ::= lefthand_side_expression SHIFTL_ASSIGN assignment_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTL_ASSIGN, 2); } assignment_expression ::= lefthand_side_expression SHIFTR_ASSIGN assignment_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTR_ASSIGN, 2); } assignment_expression ::= lefthand_side_expression SHIFTRR_ASSIGN assignment_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTRR_ASSIGN, 2); } assignment_expression ::= lefthand_side_expression AND_ASSIGN assignment_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_AND_ASSIGN, 2); } assignment_expression ::= lefthand_side_expression XOR_ASSIGN assignment_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_XOR_ASSIGN, 2); } assignment_expression ::= lefthand_side_expression OR_ASSIGN assignment_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_OR_ASSIGN, 2); } conditional_expression ::= logical_or_expression. conditional_expression ::= logical_or_expression QUESTION(A) assignment_expression COLON(B) assignment_expression. { grn_expr *e = (grn_expr *)efsi->e; e->codes[A].nargs = B - A; e->codes[B].nargs = e->codes_curr - B - 1; } logical_or_expression ::= logical_and_expression. logical_or_expression ::= logical_or_expression LOGICAL_OR logical_and_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_OR, 2); } logical_and_expression ::= bitwise_or_expression. logical_and_expression ::= logical_and_expression LOGICAL_AND bitwise_or_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_AND, 2); } logical_and_expression ::= logical_and_expression LOGICAL_AND_NOT bitwise_or_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_AND_NOT, 2); } bitwise_or_expression ::= bitwise_xor_expression. bitwise_or_expression ::= bitwise_or_expression BITWISE_OR bitwise_xor_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_BITWISE_OR, 2); } bitwise_xor_expression ::= bitwise_and_expression. bitwise_xor_expression ::= bitwise_xor_expression BITWISE_XOR bitwise_and_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_BITWISE_XOR, 2); } bitwise_and_expression ::= equality_expression. bitwise_and_expression ::= bitwise_and_expression BITWISE_AND equality_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_BITWISE_AND, 2); } equality_expression ::= relational_expression. equality_expression ::= equality_expression EQUAL relational_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_EQUAL, 2); } equality_expression ::= equality_expression NOT_EQUAL relational_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_NOT_EQUAL, 2); } relational_expression ::= shift_expression. relational_expression ::= relational_expression LESS shift_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_LESS, 2); } relational_expression ::= relational_expression GREATER shift_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_GREATER, 2); } relational_expression ::= relational_expression LESS_EQUAL shift_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_LESS_EQUAL, 2); } relational_expression ::= relational_expression GREATER_EQUAL shift_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_GREATER_EQUAL, 2); } relational_expression ::= relational_expression IN shift_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_IN, 2); } relational_expression ::= relational_expression MATCH shift_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MATCH, 2); } relational_expression ::= relational_expression NEAR shift_expression. { { int max_interval; GRN_INT32_POP(&efsi->max_interval_stack, max_interval); grn_expr_append_const_int(efsi->ctx, efsi->e, max_interval, GRN_OP_PUSH, 1); } grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_NEAR, 3); } relational_expression ::= relational_expression NEAR2 shift_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_NEAR2, 2); } relational_expression ::= relational_expression SIMILAR shift_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SIMILAR, 2); } relational_expression ::= relational_expression TERM_EXTRACT shift_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_TERM_EXTRACT, 2); } relational_expression ::= relational_expression LCP shift_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_LCP, 2); } relational_expression ::= relational_expression PREFIX shift_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PREFIX, 2); } relational_expression ::= relational_expression SUFFIX shift_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SUFFIX, 2); } relational_expression ::= relational_expression REGEXP shift_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_REGEXP, 2); } shift_expression ::= additive_expression. shift_expression ::= shift_expression SHIFTL additive_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTL, 2); } shift_expression ::= shift_expression SHIFTR additive_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTR, 2); } shift_expression ::= shift_expression SHIFTRR additive_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTRR, 2); } additive_expression ::= multiplicative_expression. additive_expression ::= additive_expression PLUS multiplicative_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PLUS, 2); } additive_expression ::= additive_expression MINUS multiplicative_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MINUS, 2); } multiplicative_expression ::= unary_expression. multiplicative_expression ::= multiplicative_expression STAR unary_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_STAR, 2); } multiplicative_expression ::= multiplicative_expression SLASH unary_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SLASH, 2); } multiplicative_expression ::= multiplicative_expression MOD unary_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MOD, 2); } unary_expression ::= postfix_expression. unary_expression ::= DELETE unary_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_DELETE, 1); } unary_expression ::= INCR unary_expression. { grn_ctx *ctx = efsi->ctx; grn_expr *e = (grn_expr *)(efsi->e); grn_expr_dfi *dfi_; unsigned int const_p; dfi_ = grn_expr_dfi_pop(e); const_p = CONSTP(dfi_->code->value); grn_expr_dfi_put(ctx, e, dfi_->type, dfi_->domain, dfi_->code); if (const_p) { ERR(GRN_SYNTAX_ERROR, "constant can't be incremented: <%.*s>", (int)(efsi->str_end - efsi->str), efsi->str); } else { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_INCR, 1); } } unary_expression ::= DECR unary_expression. { grn_ctx *ctx = efsi->ctx; grn_expr *e = (grn_expr *)(efsi->e); grn_expr_dfi *dfi_; unsigned int const_p; dfi_ = grn_expr_dfi_pop(e); const_p = CONSTP(dfi_->code->value); grn_expr_dfi_put(ctx, e, dfi_->type, dfi_->domain, dfi_->code); if (const_p) { ERR(GRN_SYNTAX_ERROR, "constant can't be decremented: <%.*s>", (int)(efsi->str_end - efsi->str), efsi->str); } else { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_DECR, 1); } } unary_expression ::= PLUS unary_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PLUS, 1); } unary_expression ::= MINUS unary_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MINUS, 1); } unary_expression ::= NOT unary_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_NOT, 1); } unary_expression ::= BITWISE_NOT unary_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_BITWISE_NOT, 1); } unary_expression ::= ADJUST unary_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_ADJUST, 1); } unary_expression ::= EXACT unary_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_EXACT, 1); } unary_expression ::= PARTIAL unary_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PARTIAL, 1); } unary_expression ::= UNSPLIT unary_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_UNSPLIT, 1); } postfix_expression ::= lefthand_side_expression. postfix_expression ::= lefthand_side_expression INCR. { grn_ctx *ctx = efsi->ctx; grn_expr *e = (grn_expr *)(efsi->e); grn_expr_dfi *dfi_; unsigned int const_p; dfi_ = grn_expr_dfi_pop(e); const_p = CONSTP(dfi_->code->value); grn_expr_dfi_put(ctx, e, dfi_->type, dfi_->domain, dfi_->code); if (const_p) { ERR(GRN_SYNTAX_ERROR, "constant can't be incremented: <%.*s>", (int)(efsi->str_end - efsi->str), efsi->str); } else { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_INCR_POST, 1); } } postfix_expression ::= lefthand_side_expression DECR. { grn_ctx *ctx = efsi->ctx; grn_expr *e = (grn_expr *)(efsi->e); grn_expr_dfi *dfi_; unsigned int const_p; dfi_ = grn_expr_dfi_pop(e); const_p = CONSTP(dfi_->code->value); grn_expr_dfi_put(ctx, e, dfi_->type, dfi_->domain, dfi_->code); if (const_p) { ERR(GRN_SYNTAX_ERROR, "constant can't be decremented: <%.*s>", (int)(efsi->str_end - efsi->str), efsi->str); } else { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_DECR_POST, 1); } } lefthand_side_expression ::= call_expression. lefthand_side_expression ::= member_expression. call_expression ::= member_expression arguments(A). { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_CALL, A); } member_expression ::= primary_expression. member_expression ::= member_expression member_expression_part. primary_expression ::= object_literal. primary_expression ::= PARENL expression PARENR. primary_expression ::= IDENTIFIER. primary_expression ::= array_literal. primary_expression ::= DECIMAL. primary_expression ::= HEX_INTEGER. primary_expression ::= STRING. primary_expression ::= BOOLEAN. primary_expression ::= NULL. array_literal ::= BRACKETL elision BRACKETR. array_literal ::= BRACKETL element_list elision BRACKETR. array_literal ::= BRACKETL element_list BRACKETR. elision ::= COMMA. elision ::= elision COMMA. element_list ::= assignment_expression. element_list ::= elision assignment_expression. element_list ::= element_list elision assignment_expression. object_literal ::= BRACEL property_name_and_value_list BRACER. { grn_ctx *ctx = efsi->ctx; grn_expr_take_obj(ctx, efsi->e, (grn_obj *)(efsi->object_literal)); grn_expr_append_obj(ctx, efsi->e, (grn_obj *)(efsi->object_literal), GRN_OP_PUSH, 1); efsi->object_literal = NULL; } property_name_and_value_list ::= . { grn_ctx *ctx = efsi->ctx; efsi->object_literal = grn_hash_create(ctx, NULL, GRN_TABLE_MAX_KEY_SIZE, sizeof(grn_obj), GRN_OBJ_KEY_VAR_SIZE|GRN_OBJ_TEMPORARY|GRN_HASH_TINY); if (!efsi->object_literal) { ERR(GRN_NO_MEMORY_AVAILABLE, "couldn't create hash table for parsing object literal: <%.*s>", (int)(efsi->str_end - efsi->str), efsi->str); } } property_name_and_value_list ::= property_name_and_value. property_name_and_value_list ::= property_name_and_value_list COMMA property_name_and_value. property_name_and_value ::= property_name COLON assignment_expression. { grn_ctx *ctx = efsi->ctx; grn_expr *e = (grn_expr *)(efsi->e); grn_obj *property = e->codes[e->codes_curr - 3].value; grn_obj *value = e->codes[e->codes_curr - 1].value; if (!efsi->object_literal) { efsi->object_literal = grn_hash_create(ctx, NULL, GRN_TABLE_MAX_KEY_SIZE, sizeof(grn_obj), GRN_OBJ_KEY_VAR_SIZE|GRN_OBJ_TEMPORARY|GRN_HASH_TINY); } if (!efsi->object_literal) { ERR(GRN_NO_MEMORY_AVAILABLE, "couldn't create hash table for parsing object literal: <%.*s>", (int)(efsi->str_end - efsi->str), efsi->str); } else { grn_obj *buf; int added; if (grn_hash_add(ctx, (grn_hash *)efsi->object_literal, GRN_TEXT_VALUE(property), GRN_TEXT_LEN(property), (void **)&buf, &added)) { if (added) { GRN_OBJ_INIT(buf, value->header.type, 0, value->header.domain); GRN_TEXT_PUT(ctx, buf, GRN_TEXT_VALUE(value), GRN_TEXT_LEN(value)); grn_expr_dfi_pop(e); e->codes_curr -= 3; } else { ERR(GRN_INVALID_ARGUMENT, "duplicated property name: <%.*s>", (int)GRN_TEXT_LEN(property), GRN_TEXT_VALUE(property)); } } else { ERR(GRN_NO_MEMORY_AVAILABLE, "failed to add a property to object literal: <%.*s>", (int)GRN_TEXT_LEN(property), GRN_TEXT_VALUE(property)); } } } property_name ::= STRING. member_expression_part ::= BRACKETL expression BRACKETR. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_GET_MEMBER, 2); } member_expression_part ::= DOT IDENTIFIER. arguments(A) ::= PARENL argument_list(B) PARENR. { A = B; } argument_list(A) ::= . { A = 0; } argument_list(A) ::= assignment_expression. { A = 1; } argument_list(A) ::= argument_list(B) COMMA assignment_expression. { A = B + 1; } output_columns(N_STACKED_COLUMNS) ::= . { N_STACKED_COLUMNS = 0; } output_columns(N_STACKED_COLUMNS) ::= output_column(SUB_N_STACKED_COLUMNS). { N_STACKED_COLUMNS = SUB_N_STACKED_COLUMNS; } /* Accept "column1,,,,,,column2" */ output_columns(N_STACKED_COLUMNS) ::= output_columns(SUB_N_STACKED_COLUMNS) COMMA. { N_STACKED_COLUMNS = SUB_N_STACKED_COLUMNS; } output_columns(N_STACKED_COLUMNS) ::= output_columns(SUB_N_STACKED_COLUMNS) COMMA output_column(NEW_N_STACKED_COLUMNS). { if (SUB_N_STACKED_COLUMNS == 0) { N_STACKED_COLUMNS = NEW_N_STACKED_COLUMNS; } else if (NEW_N_STACKED_COLUMNS == 0) { N_STACKED_COLUMNS = SUB_N_STACKED_COLUMNS; } else { if (NEW_N_STACKED_COLUMNS == 1) { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_COMMA, 2); } N_STACKED_COLUMNS = 1; } } output_column(N_STACKED_COLUMNS) ::= STAR. { grn_ctx *ctx = efsi->ctx; grn_obj *expr = efsi->e; grn_obj *variable = grn_expr_get_var_by_offset(ctx, expr, 0); if (variable) { grn_id table_id = GRN_OBJ_GET_DOMAIN(variable); grn_obj *table = grn_ctx_at(ctx, table_id); grn_obj columns_buffer; int n_columns; grn_obj **columns; GRN_PTR_INIT(&columns_buffer, GRN_OBJ_VECTOR, GRN_ID_NIL); grn_obj_columns(ctx, table, "*", strlen("*"), &columns_buffer); n_columns = GRN_BULK_VSIZE(&columns_buffer) / sizeof(grn_obj *); columns = (grn_obj **)GRN_BULK_HEAD(&columns_buffer); if (n_columns == 0) { /* do nothing */ } else if (n_columns == 1) { grn_obj *column = columns[0]; grn_expr_append_const(ctx, expr, column, GRN_OP_GET_VALUE, 1); if (column->header.type == GRN_ACCESSOR) { grn_expr_take_obj(ctx, expr, column); } } else { grn_expr *e = (grn_expr *)expr; grn_bool have_column; int i; have_column = (e->codes_curr > 0); for (i = 0; i < n_columns; i++) { grn_obj *column = columns[i]; grn_expr_append_const(ctx, expr, column, GRN_OP_GET_VALUE, 1); if (have_column || i > 0) { grn_expr_append_op(ctx, expr, GRN_OP_COMMA, 2); } if (column->header.type == GRN_ACCESSOR) { grn_expr_take_obj(ctx, expr, column); } } } GRN_OBJ_FIN(ctx, &columns_buffer); N_STACKED_COLUMNS = n_columns; } else { /* TODO: report error */ N_STACKED_COLUMNS = 0; } } output_column(N_STACKED_COLUMNS) ::= NONEXISTENT_COLUMN. { N_STACKED_COLUMNS = 0; } output_column(N_STACKED_COLUMNS) ::= assignment_expression. { N_STACKED_COLUMNS = 1; } adjuster ::= . adjuster ::= adjust_expression. adjuster ::= adjuster PLUS adjust_expression. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PLUS, 2); } adjust_expression ::= adjust_match_expression. adjust_expression ::= adjust_match_expression STAR DECIMAL. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_STAR, 2); } adjust_match_expression ::= IDENTIFIER MATCH STRING. { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MATCH, 2); }