2 #define YYPARSE_PARAM result /* need this to pass a pointer (void *) to yyparse */
7 #include "utils/builtins.h"
11 * Bison doesn't allocate anything that needs to live across parser calls,
12 * so we can easily have it use palloc instead of malloc. This prevents
13 * memory leaks if we error out during parsing. Note this only works with
14 * bison >= 2.0. However, in bison 1.875 the default is to use alloca()
15 * if possible, so there's not really much problem anyhow, at least if
16 * you're building with gcc.
18 #define YYMALLOC palloc
21 /* Avoid exit() on fatal scanner errors (a bit ugly -- see yy_fatal_error) */
23 #define fprintf(file, fmt, msg) fprintf_to_ereport(fmt, msg)
26 fprintf_to_ereport(const char *fmt, const char *msg)
28 ereport(ERROR, (errmsg_internal("%s", msg)));
31 /* struct string is shared between scan and gram */
32 typedef struct string {
37 #include <hstore_gram.h>
39 /* flex 2.5.4 doesn't bother with a decl for this */
40 int hstore_yylex(YYSTYPE * yylval_param);
41 int hstore_yyparse(void *result);
42 void hstore_yyerror(const char *message);
45 makeHStoreValueString(HStoreValue* v, string *s)
48 v = palloc(sizeof(*v));
53 v->size = sizeof(HEntry);
55 else if (s->len > HENTRY_POSMASK)
57 elog(ERROR, "string is too long");
62 v->string.val = s->val;
63 v->string.len = s->len;
64 v->size = sizeof(HEntry) + s->len;
72 makeHStoreValueNumeric(string *s)
76 MemoryContext ccxt = CurrentMemoryContext;
79 * ignore ERRCODE_INVALID_TEXT_REPRESENTATION in parse: our
80 * test stringIsNumber could be not agree with numeric_in
85 n = DatumGetNumeric(DirectFunctionCall3(numeric_in, CStringGetDatum(s->val), 0, -1));
92 ecxt = MemoryContextSwitchTo(ccxt);
93 errdata = CopyErrorData();
94 if (errdata->sqlerrcode == ERRCODE_INVALID_TEXT_REPRESENTATION)
101 MemoryContextSwitchTo(ecxt);
109 v = palloc(sizeof(*v));
110 v->type = hsvNumeric;
112 v->size = 2*sizeof(HEntry) + VARSIZE_ANY(n);
116 v = makeHStoreValueString(NULL, s);
123 makeHStoreValueBool(bool val) {
124 HStoreValue *v = palloc(sizeof(*v));
128 v->size = sizeof(HEntry);
134 makeHStoreValueArray(List *list)
136 HStoreValue *v = palloc(sizeof(*v));
139 v->array.scalar = false;
140 v->array.nelems = list_length(list);
141 v->size = sizeof(uint32) /* header */ + sizeof(HEntry) /* parent's entry */ + sizeof(HEntry) - 1 /*alignment*/;
143 if (v->array.nelems > 0)
148 v->array.elems = palloc(sizeof(HStoreValue) * v->array.nelems);
152 HStoreValue *s = (HStoreValue*)lfirst(cell);
156 v->array.elems[i++] = *s;
158 if (v->size > HENTRY_POSMASK)
159 elog(ERROR, "array is too long");
164 v->array.elems = NULL;
171 makeHStoreValuePairs(List *list)
173 HStoreValue *v = palloc(sizeof(*v));
176 v->hash.npairs = list_length(list);
177 v->size = sizeof(uint32) /* header */ + sizeof(HEntry) /* parent's entry */ + sizeof(HEntry) - 1 /*alignment*/;
179 if (v->hash.npairs > 0)
184 v->hash.pairs = palloc(sizeof(HStorePair) * v->hash.npairs);
188 HStorePair *s = (HStorePair*)lfirst(cell);
190 v->size += s->key.size + s->value.size;
191 v->hash.pairs[i].order = i;
192 v->hash.pairs[i++] = *s;
194 if (v->size > HENTRY_POSMASK)
195 elog(ERROR, "hstore is too long");
198 uniqueHStoreValue(v);
202 v->hash.pairs = NULL;
209 makeHStorePair(string *key, HStoreValue *value) {
210 HStorePair *v = palloc(sizeof(*v));
212 makeHStoreValueString(&v->key, key);
220 /* BISON Declarations */
223 %name-prefix="hstore_yy"
229 List *elems; /* list of HStoreValue */
230 List *pairs; /* list of HStorePair */
236 %token <str> DELIMITER_P NULL_P STRING_P TRUE_P FALSE_P
239 %type <hvalue> result hstore value scalar_value
244 %type <elems> value_list
245 %type <pairs> pair_list
247 /* Grammar follows */
251 pair_list { *((HStoreValue**)result) = makeHStoreValuePairs($1); }
253 if ($1->type == hsvNull)
254 *((HStoreValue**)result) = NULL;
256 *((HStoreValue**)result) = $1;
259 *((HStoreValue**)result) = makeHStoreValueArray(lappend(NIL, $1));
260 (*((HStoreValue**)result))->array.scalar = true;
262 | /* EMPTY */ { *((HStoreValue**)result) = NULL; }
266 '{' pair_list '}' { $$ = makeHStoreValuePairs($2); }
267 | '{' value_list '}' { $$ = makeHStoreValueArray($2); }
268 | '[' value_list ']' { $$ = makeHStoreValueArray($2); }
269 | '{' value '}' { $$ = makeHStoreValueArray(lappend(NIL, $2)); }
270 | '[' value ']' { $$ = makeHStoreValueArray(lappend(NIL, $2)); }
271 | '{' '}' { $$ = makeHStoreValueString(NULL, NULL); }
272 | '[' ']' { $$ = makeHStoreValueString(NULL, NULL); }
276 NULL_P { $$ = makeHStoreValueString(NULL, NULL); }
277 | STRING_P { $$ = makeHStoreValueString(NULL, &$1); }
278 | TRUE_P { $$ = makeHStoreValueBool(true); }
279 | FALSE_P { $$ = makeHStoreValueBool(false); }
280 | NUMERIC_P { $$ = makeHStoreValueNumeric(&$1); }
284 scalar_value { $$ = $1; }
285 | hstore { $$ = $1; }
289 value ',' value { $$ = lappend(lappend(NIL, $1), $3); }
290 | value_list ',' value { $$ = lappend($1, $3); }
294 * key is always a string, not a bool or numeric
297 STRING_P { $$ = $1; }
298 | TRUE_P { $$ = $1; }
299 | FALSE_P { $$ = $1; }
300 | NUMERIC_P { $$ = $1; }
301 | NULL_P { $$ = $1; }
305 key DELIMITER_P value { $$ = makeHStorePair(&$1, $3); }
309 pair { $$ = lappend(NIL, $1); }
310 | pair_list ',' pair { $$ = lappend($1, $3); }
315 #include "hstore_scan.c"