1/* -*- mode: c; c-basic-offset: 2 -*- */
2%name grn_expr_parser
3%token_prefix GRN_EXPR_TOKEN_
4%include {
5#ifdef assert
6#  undef assert
7#endif
8#define assert GRN_ASSERT
9}
10
11%token_type { int }
12
13%type suppress_unused_variable_warning { void * }
14%destructor suppress_unused_variable_warning {
15  (void)efsi;
16}
17
18%extra_argument { efs_info *efsi }
19
20%syntax_error {
21  {
22    grn_ctx *ctx = efsi->ctx;
23    grn_obj message;
24    GRN_TEXT_INIT(&message, 0);
25    GRN_TEXT_PUT(ctx, &message, efsi->str, efsi->cur - efsi->str);
26    GRN_TEXT_PUTC(ctx, &message, '|');
27    if (efsi->cur < efsi->str_end) {
28      GRN_TEXT_PUTC(ctx, &message, efsi->cur[0]);
29      GRN_TEXT_PUTC(ctx, &message, '|');
30      GRN_TEXT_PUT(ctx, &message,
31                   efsi->cur + 1, efsi->str_end - (efsi->cur + 1));
32    } else {
33      GRN_TEXT_PUTC(ctx, &message, '|');
34    }
35    if (ctx->rc == GRN_SUCCESS) {
36      ERR(GRN_SYNTAX_ERROR, "Syntax error: <%.*s>",
37          (int)GRN_TEXT_LEN(&message), GRN_TEXT_VALUE(&message));
38    } else {
39      ERR(ctx->rc, "Syntax error: <%.*s>: %s",
40          (int)GRN_TEXT_LEN(&message), GRN_TEXT_VALUE(&message),
41          ctx->errbuf);
42    }
43    GRN_OBJ_FIN(ctx, &message);
44  }
45}
46
47input ::= query.
48input ::= expression.
49input ::= START_OUTPUT_COLUMNS output_columns.
50input ::= START_ADJUSTER adjuster.
51
52query ::= query_element.
53query ::= query query_element. {
54  grn_expr_append_op(efsi->ctx, efsi->e, grn_int32_value_at(&efsi->op_stack, -1), 2);
55}
56query ::= query LOGICAL_AND query_element. {
57  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_AND, 2);
58}
59query ::= query LOGICAL_AND_NOT query_element.{
60  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_AND_NOT, 2);
61}
62query ::= query LOGICAL_OR query_element.{
63  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_OR, 2);
64}
65query ::= query NEGATIVE query_element.{
66  int weight;
67  GRN_INT32_POP(&efsi->weight_stack, weight);
68  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_ADJUST, 2);
69}
70
71query_element ::= QSTRING.
72query_element ::= PARENL query PARENR.
73
74query_element ::= ADJUST query_element.{
75  int weight;
76  GRN_INT32_POP(&efsi->weight_stack, weight);
77}
78query_element ::= RELATIVE_OP query_element.{
79  int mode;
80  GRN_INT32_POP(&efsi->mode_stack, mode);
81}
82query_element ::= IDENTIFIER RELATIVE_OP query_element. {
83  int mode;
84  grn_obj *c;
85  GRN_PTR_POP(&efsi->column_stack, c);
86  GRN_INT32_POP(&efsi->mode_stack, mode);
87  switch (mode) {
88  case GRN_OP_NEAR :
89  case GRN_OP_NEAR2 :
90    {
91      int max_interval;
92      GRN_INT32_POP(&efsi->max_interval_stack, max_interval);
93    }
94    break;
95  case GRN_OP_SIMILAR :
96    {
97      int similarity_threshold;
98      GRN_INT32_POP(&efsi->similarity_threshold_stack, similarity_threshold);
99    }
100    break;
101  default :
102    break;
103  }
104}
105query_element ::= BRACEL expression BRACER. {
106  efsi->flags = efsi->default_flags;
107}
108query_element ::= EVAL primary_expression. {
109  efsi->flags = efsi->default_flags;
110}
111
112expression ::= assignment_expression.
113expression ::= expression COMMA assignment_expression. {
114  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_COMMA, 2);
115}
116
117assignment_expression ::= conditional_expression.
118assignment_expression ::= lefthand_side_expression ASSIGN assignment_expression. {
119  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_ASSIGN, 2);
120}
121assignment_expression ::= lefthand_side_expression STAR_ASSIGN assignment_expression. {
122  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_STAR_ASSIGN, 2);
123}
124assignment_expression ::= lefthand_side_expression SLASH_ASSIGN assignment_expression. {
125  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SLASH_ASSIGN, 2);
126}
127assignment_expression ::= lefthand_side_expression MOD_ASSIGN assignment_expression. {
128  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MOD_ASSIGN, 2);
129}
130assignment_expression ::= lefthand_side_expression PLUS_ASSIGN assignment_expression. {
131  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PLUS_ASSIGN, 2);
132}
133assignment_expression ::= lefthand_side_expression MINUS_ASSIGN assignment_expression. {
134  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MINUS_ASSIGN, 2);
135}
136assignment_expression ::= lefthand_side_expression SHIFTL_ASSIGN assignment_expression. {
137  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTL_ASSIGN, 2);
138}
139assignment_expression ::= lefthand_side_expression SHIFTR_ASSIGN assignment_expression. {
140  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTR_ASSIGN, 2);
141}
142assignment_expression ::= lefthand_side_expression SHIFTRR_ASSIGN assignment_expression. {
143  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTRR_ASSIGN, 2);
144}
145assignment_expression ::= lefthand_side_expression AND_ASSIGN assignment_expression. {
146  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_AND_ASSIGN, 2);
147}
148assignment_expression ::= lefthand_side_expression XOR_ASSIGN assignment_expression. {
149  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_XOR_ASSIGN, 2);
150}
151assignment_expression ::= lefthand_side_expression OR_ASSIGN assignment_expression. {
152  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_OR_ASSIGN, 2);
153}
154
155conditional_expression ::= logical_or_expression.
156conditional_expression ::= logical_or_expression QUESTION(A) assignment_expression COLON(B) assignment_expression. {
157  grn_expr *e = (grn_expr *)efsi->e;
158  e->codes[A].nargs = B - A;
159  e->codes[B].nargs = e->codes_curr - B - 1;
160}
161
162logical_or_expression ::= logical_and_expression.
163logical_or_expression ::= logical_or_expression LOGICAL_OR logical_and_expression. {
164  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_OR, 2);
165}
166
167logical_and_expression ::= bitwise_or_expression.
168logical_and_expression ::= logical_and_expression LOGICAL_AND bitwise_or_expression. {
169  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_AND, 2);
170}
171logical_and_expression ::= logical_and_expression LOGICAL_AND_NOT bitwise_or_expression. {
172  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_AND_NOT, 2);
173}
174
175bitwise_or_expression ::= bitwise_xor_expression.
176bitwise_or_expression ::= bitwise_or_expression BITWISE_OR bitwise_xor_expression. {
177  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_BITWISE_OR, 2);
178}
179
180bitwise_xor_expression ::= bitwise_and_expression.
181bitwise_xor_expression ::= bitwise_xor_expression BITWISE_XOR bitwise_and_expression. {
182  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_BITWISE_XOR, 2);
183}
184
185bitwise_and_expression ::= equality_expression.
186bitwise_and_expression ::= bitwise_and_expression BITWISE_AND equality_expression. {
187  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_BITWISE_AND, 2);
188}
189
190equality_expression ::= relational_expression.
191equality_expression ::= equality_expression EQUAL relational_expression. {
192  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_EQUAL, 2);
193}
194equality_expression ::= equality_expression NOT_EQUAL relational_expression. {
195  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_NOT_EQUAL, 2);
196}
197
198relational_expression ::= shift_expression.
199relational_expression ::= relational_expression LESS shift_expression. {
200  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_LESS, 2);
201}
202relational_expression ::= relational_expression GREATER shift_expression. {
203  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_GREATER, 2);
204}
205relational_expression ::= relational_expression LESS_EQUAL shift_expression. {
206  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_LESS_EQUAL, 2);
207}
208relational_expression ::= relational_expression GREATER_EQUAL shift_expression. {
209  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_GREATER_EQUAL, 2);
210}
211relational_expression ::= relational_expression IN shift_expression. {
212  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_IN, 2);
213}
214relational_expression ::= relational_expression MATCH shift_expression. {
215  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MATCH, 2);
216}
217relational_expression ::= relational_expression NEAR shift_expression. {
218  {
219    int max_interval;
220    GRN_INT32_POP(&efsi->max_interval_stack, max_interval);
221    grn_expr_append_const_int(efsi->ctx, efsi->e, max_interval,
222                              GRN_OP_PUSH, 1);
223  }
224  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_NEAR, 3);
225}
226relational_expression ::= relational_expression NEAR2 shift_expression. {
227  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_NEAR2, 2);
228}
229relational_expression ::= relational_expression SIMILAR shift_expression. {
230  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SIMILAR, 2);
231}
232relational_expression ::= relational_expression TERM_EXTRACT shift_expression. {
233  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_TERM_EXTRACT, 2);
234}
235relational_expression ::= relational_expression LCP shift_expression. {
236  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_LCP, 2);
237}
238relational_expression ::= relational_expression PREFIX shift_expression. {
239  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PREFIX, 2);
240}
241relational_expression ::= relational_expression SUFFIX shift_expression. {
242  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SUFFIX, 2);
243}
244relational_expression ::= relational_expression REGEXP shift_expression. {
245  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_REGEXP, 2);
246}
247
248shift_expression ::= additive_expression.
249shift_expression ::= shift_expression SHIFTL additive_expression. {
250  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTL, 2);
251}
252shift_expression ::= shift_expression SHIFTR additive_expression. {
253  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTR, 2);
254}
255shift_expression ::= shift_expression SHIFTRR additive_expression. {
256  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTRR, 2);
257}
258
259additive_expression ::= multiplicative_expression.
260additive_expression ::= additive_expression PLUS multiplicative_expression. {
261  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PLUS, 2);
262}
263additive_expression ::= additive_expression MINUS multiplicative_expression. {
264  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MINUS, 2);
265}
266
267multiplicative_expression ::= unary_expression.
268multiplicative_expression ::= multiplicative_expression STAR unary_expression. {
269  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_STAR, 2);
270}
271multiplicative_expression ::= multiplicative_expression SLASH unary_expression. {
272  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SLASH, 2);
273}
274multiplicative_expression ::= multiplicative_expression MOD unary_expression. {
275  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MOD, 2);
276}
277
278unary_expression ::= postfix_expression.
279unary_expression ::= DELETE unary_expression. {
280  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_DELETE, 1);
281}
282unary_expression ::= INCR unary_expression. {
283  grn_ctx *ctx = efsi->ctx;
284  grn_expr *e = (grn_expr *)(efsi->e);
285  grn_expr_dfi *dfi_;
286  unsigned int const_p;
287
288  dfi_ = grn_expr_dfi_pop(e);
289  const_p = CONSTP(dfi_->code->value);
290  grn_expr_dfi_put(ctx, e, dfi_->type, dfi_->domain, dfi_->code);
291  if (const_p) {
292    ERR(GRN_SYNTAX_ERROR,
293        "constant can't be incremented: <%.*s>",
294        (int)(efsi->str_end - efsi->str), efsi->str);
295  } else {
296    grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_INCR, 1);
297  }
298}
299unary_expression ::= DECR unary_expression. {
300  grn_ctx *ctx = efsi->ctx;
301  grn_expr *e = (grn_expr *)(efsi->e);
302  grn_expr_dfi *dfi_;
303  unsigned int const_p;
304
305  dfi_ = grn_expr_dfi_pop(e);
306  const_p = CONSTP(dfi_->code->value);
307  grn_expr_dfi_put(ctx, e, dfi_->type, dfi_->domain, dfi_->code);
308  if (const_p) {
309    ERR(GRN_SYNTAX_ERROR,
310        "constant can't be decremented: <%.*s>",
311        (int)(efsi->str_end - efsi->str), efsi->str);
312  } else {
313    grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_DECR, 1);
314  }
315}
316unary_expression ::= PLUS unary_expression. {
317  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PLUS, 1);
318}
319unary_expression ::= MINUS unary_expression. {
320  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MINUS, 1);
321}
322unary_expression ::= NOT unary_expression. {
323  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_NOT, 1);
324}
325unary_expression ::= BITWISE_NOT unary_expression. {
326  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_BITWISE_NOT, 1);
327}
328unary_expression ::= ADJUST unary_expression. {
329  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_ADJUST, 1);
330}
331unary_expression ::= EXACT unary_expression. {
332  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_EXACT, 1);
333}
334unary_expression ::= PARTIAL unary_expression. {
335  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PARTIAL, 1);
336}
337unary_expression ::= UNSPLIT unary_expression. {
338  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_UNSPLIT, 1);
339}
340
341postfix_expression ::= lefthand_side_expression.
342postfix_expression ::= lefthand_side_expression INCR. {
343  grn_ctx *ctx = efsi->ctx;
344  grn_expr *e = (grn_expr *)(efsi->e);
345  grn_expr_dfi *dfi_;
346  unsigned int const_p;
347
348  dfi_ = grn_expr_dfi_pop(e);
349  const_p = CONSTP(dfi_->code->value);
350  grn_expr_dfi_put(ctx, e, dfi_->type, dfi_->domain, dfi_->code);
351  if (const_p) {
352    ERR(GRN_SYNTAX_ERROR,
353        "constant can't be incremented: <%.*s>",
354        (int)(efsi->str_end - efsi->str), efsi->str);
355  } else {
356    grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_INCR_POST, 1);
357  }
358}
359postfix_expression ::= lefthand_side_expression DECR. {
360  grn_ctx *ctx = efsi->ctx;
361  grn_expr *e = (grn_expr *)(efsi->e);
362  grn_expr_dfi *dfi_;
363  unsigned int const_p;
364
365  dfi_ = grn_expr_dfi_pop(e);
366  const_p = CONSTP(dfi_->code->value);
367  grn_expr_dfi_put(ctx, e, dfi_->type, dfi_->domain, dfi_->code);
368  if (const_p) {
369    ERR(GRN_SYNTAX_ERROR,
370        "constant can't be decremented: <%.*s>",
371        (int)(efsi->str_end - efsi->str), efsi->str);
372  } else {
373    grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_DECR_POST, 1);
374  }
375}
376
377lefthand_side_expression ::= call_expression.
378lefthand_side_expression ::= member_expression.
379
380call_expression ::= member_expression arguments(A). {
381  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_CALL, A);
382}
383
384member_expression ::= primary_expression.
385member_expression ::= member_expression member_expression_part.
386
387primary_expression ::= object_literal.
388primary_expression ::= PARENL expression PARENR.
389primary_expression ::= IDENTIFIER.
390primary_expression ::= array_literal.
391primary_expression ::= DECIMAL.
392primary_expression ::= HEX_INTEGER.
393primary_expression ::= STRING.
394primary_expression ::= BOOLEAN.
395primary_expression ::= NULL.
396
397array_literal ::= BRACKETL elision BRACKETR.
398array_literal ::= BRACKETL element_list elision BRACKETR.
399array_literal ::= BRACKETL element_list BRACKETR.
400
401elision ::= COMMA.
402elision ::= elision COMMA.
403
404element_list ::= assignment_expression.
405element_list ::= elision assignment_expression.
406element_list ::= element_list elision assignment_expression.
407
408object_literal ::= BRACEL property_name_and_value_list BRACER. {
409  grn_ctx *ctx = efsi->ctx;
410  grn_expr_take_obj(ctx, efsi->e, (grn_obj *)(efsi->object_literal));
411  grn_expr_append_obj(ctx, efsi->e, (grn_obj *)(efsi->object_literal),
412                      GRN_OP_PUSH, 1);
413  efsi->object_literal = NULL;
414}
415
416property_name_and_value_list ::= . {
417  grn_ctx *ctx = efsi->ctx;
418
419  efsi->object_literal =
420    grn_hash_create(ctx, NULL, GRN_TABLE_MAX_KEY_SIZE, sizeof(grn_obj),
421                    GRN_OBJ_KEY_VAR_SIZE|GRN_OBJ_TEMPORARY|GRN_HASH_TINY);
422  if (!efsi->object_literal) {
423    ERR(GRN_NO_MEMORY_AVAILABLE,
424        "couldn't create hash table for parsing object literal: <%.*s>",
425        (int)(efsi->str_end - efsi->str), efsi->str);
426  }
427}
428property_name_and_value_list ::= property_name_and_value.
429property_name_and_value_list ::= property_name_and_value_list COMMA property_name_and_value.
430
431property_name_and_value ::= property_name COLON assignment_expression. {
432  grn_ctx *ctx = efsi->ctx;
433  grn_expr *e = (grn_expr *)(efsi->e);
434  grn_obj *property = e->codes[e->codes_curr - 3].value;
435  grn_obj *value = e->codes[e->codes_curr - 1].value;
436
437  if (!efsi->object_literal) {
438     efsi->object_literal =
439       grn_hash_create(ctx, NULL, GRN_TABLE_MAX_KEY_SIZE, sizeof(grn_obj),
440                       GRN_OBJ_KEY_VAR_SIZE|GRN_OBJ_TEMPORARY|GRN_HASH_TINY);
441  }
442
443  if (!efsi->object_literal) {
444    ERR(GRN_NO_MEMORY_AVAILABLE,
445        "couldn't create hash table for parsing object literal: <%.*s>",
446        (int)(efsi->str_end - efsi->str), efsi->str);
447  } else {
448    grn_obj *buf;
449    int added;
450    if (grn_hash_add(ctx, (grn_hash *)efsi->object_literal,
451                     GRN_TEXT_VALUE(property), GRN_TEXT_LEN(property),
452                     (void **)&buf, &added)) {
453      if (added) {
454        GRN_OBJ_INIT(buf, value->header.type, 0, value->header.domain);
455        GRN_TEXT_PUT(ctx, buf, GRN_TEXT_VALUE(value), GRN_TEXT_LEN(value));
456        grn_expr_dfi_pop(e);
457        e->codes_curr -= 3;
458      } else {
459        ERR(GRN_INVALID_ARGUMENT,
460            "duplicated property name: <%.*s>",
461            (int)GRN_TEXT_LEN(property),
462            GRN_TEXT_VALUE(property));
463      }
464    } else {
465      ERR(GRN_NO_MEMORY_AVAILABLE,
466          "failed to add a property to object literal: <%.*s>",
467          (int)GRN_TEXT_LEN(property),
468          GRN_TEXT_VALUE(property));
469    }
470  }
471}
472
473property_name ::= STRING.
474
475member_expression_part ::= BRACKETL expression BRACKETR. {
476  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_GET_MEMBER, 2);
477}
478member_expression_part ::= DOT IDENTIFIER.
479
480arguments(A) ::= PARENL argument_list(B) PARENR. { A = B; }
481argument_list(A) ::= . { A = 0; }
482argument_list(A) ::= assignment_expression. { A = 1; }
483argument_list(A) ::= argument_list(B) COMMA assignment_expression. { A = B + 1; }
484
485output_columns(N_STACKED_COLUMNS) ::= . {
486  N_STACKED_COLUMNS = 0;
487}
488output_columns(N_STACKED_COLUMNS) ::= output_column(SUB_N_STACKED_COLUMNS). {
489  N_STACKED_COLUMNS = SUB_N_STACKED_COLUMNS;
490}
491/* Accept "column1,,,,,,column2" */
492output_columns(N_STACKED_COLUMNS) ::=
493   output_columns(SUB_N_STACKED_COLUMNS) COMMA. {
494  N_STACKED_COLUMNS = SUB_N_STACKED_COLUMNS;
495}
496output_columns(N_STACKED_COLUMNS) ::=
497   output_columns(SUB_N_STACKED_COLUMNS) COMMA
498   output_column(NEW_N_STACKED_COLUMNS). {
499  if (SUB_N_STACKED_COLUMNS == 0) {
500    N_STACKED_COLUMNS = NEW_N_STACKED_COLUMNS;
501  } else if (NEW_N_STACKED_COLUMNS == 0) {
502    N_STACKED_COLUMNS = SUB_N_STACKED_COLUMNS;
503  } else {
504    if (NEW_N_STACKED_COLUMNS == 1) {
505      grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_COMMA, 2);
506    }
507    N_STACKED_COLUMNS = 1;
508  }
509}
510
511output_column(N_STACKED_COLUMNS) ::= STAR. {
512  grn_ctx *ctx = efsi->ctx;
513  grn_obj *expr = efsi->e;
514  grn_obj *variable = grn_expr_get_var_by_offset(ctx, expr, 0);
515  if (variable) {
516    grn_id table_id = GRN_OBJ_GET_DOMAIN(variable);
517    grn_obj *table = grn_ctx_at(ctx, table_id);
518    grn_obj columns_buffer;
519    int n_columns;
520    grn_obj **columns;
521
522    GRN_PTR_INIT(&columns_buffer, GRN_OBJ_VECTOR, GRN_ID_NIL);
523    grn_obj_columns(ctx, table, "*", strlen("*"), &columns_buffer);
524    n_columns = GRN_BULK_VSIZE(&columns_buffer) / sizeof(grn_obj *);
525    columns = (grn_obj **)GRN_BULK_HEAD(&columns_buffer);
526
527    if (n_columns == 0) {
528      /* do nothing */
529    } else if (n_columns == 1) {
530      grn_obj *column = columns[0];
531      grn_expr_append_const(ctx, expr, column, GRN_OP_GET_VALUE, 1);
532      if (column->header.type == GRN_ACCESSOR) {
533        grn_expr_take_obj(ctx, expr, column);
534      }
535    } else {
536      grn_expr *e = (grn_expr *)expr;
537      grn_bool have_column;
538      int i;
539
540      have_column = (e->codes_curr > 0);
541      for (i = 0; i < n_columns; i++) {
542        grn_obj *column = columns[i];
543        grn_expr_append_const(ctx, expr, column, GRN_OP_GET_VALUE, 1);
544        if (have_column || i > 0) {
545          grn_expr_append_op(ctx, expr, GRN_OP_COMMA, 2);
546        }
547        if (column->header.type == GRN_ACCESSOR) {
548          grn_expr_take_obj(ctx, expr, column);
549        }
550      }
551    }
552
553    GRN_OBJ_FIN(ctx, &columns_buffer);
554
555    N_STACKED_COLUMNS = n_columns;
556  } else {
557    /* TODO: report error */
558    N_STACKED_COLUMNS = 0;
559  }
560}
561output_column(N_STACKED_COLUMNS) ::= NONEXISTENT_COLUMN. {
562  N_STACKED_COLUMNS = 0;
563}
564output_column(N_STACKED_COLUMNS) ::= assignment_expression. {
565  N_STACKED_COLUMNS = 1;
566}
567
568adjuster ::= .
569adjuster ::= adjust_expression.
570adjuster ::= adjuster PLUS adjust_expression. {
571  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PLUS, 2);
572}
573
574adjust_expression ::= adjust_match_expression.
575adjust_expression ::= adjust_match_expression STAR DECIMAL. {
576  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_STAR, 2);
577}
578
579adjust_match_expression ::= IDENTIFIER MATCH STRING. {
580  grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MATCH, 2);
581}
582