2 /* contrib/cube/cubeparse.y */
4 /* NdBox = [(lowerleft),(upperright)] */
5 /* [(xLL(1)...xLL(N)),(xUR(1)...xUR(n))] */
10 #include "nodes/miscnodes.h"
11 #include "utils/float.h"
14 /* All grammar constructs return strings */
15 #define YYSTYPE char *
18 * Bison doesn't allocate anything that needs to live across parser calls,
19 * so we can easily have it use palloc instead of malloc. This prevents
20 * memory leaks if we error out during parsing.
22 #define YYMALLOC palloc
25 static int item_count
(const char *s
, char delim
);
26 static bool write_box
(int dim
, char *str1
, char *str2
,
27 NDBOX
**result
, struct Node
*escontext
);
28 static bool write_point_as_box
(int dim
, char *str
,
29 NDBOX
**result
, struct Node
*escontext
);
33 /* BISON Declarations */
34 %parse
-param
{NDBOX
**result
}
35 %parse
-param
{Size scanbuflen
}
36 %parse
-param
{struct Node
*escontext
}
38 %name
-prefix
="cube_yy"
40 %token CUBEFLOAT O_PAREN C_PAREN O_BRACKET C_BRACKET COMMA
46 box: O_BRACKET paren_list COMMA paren_list C_BRACKET
50 dim
= item_count
($2, ',');
51 if
(item_count
($4, ',') != dim
)
54 (errcode
(ERRCODE_INVALID_TEXT_REPRESENTATION
),
55 errmsg
("invalid input syntax for cube"),
56 errdetail
("Different point dimensions in (%s) and (%s).",
60 if
(dim
> CUBE_MAX_DIM
)
63 (errcode
(ERRCODE_INVALID_TEXT_REPRESENTATION
),
64 errmsg
("invalid input syntax for cube"),
65 errdetail
("A cube cannot have more than %d dimensions.",
70 if
(!write_box
(dim
, $2, $4, result
, escontext
))
74 | paren_list COMMA paren_list
78 dim
= item_count
($1, ',');
79 if
(item_count
($3, ',') != dim
)
82 (errcode
(ERRCODE_INVALID_TEXT_REPRESENTATION
),
83 errmsg
("invalid input syntax for cube"),
84 errdetail
("Different point dimensions in (%s) and (%s).",
88 if
(dim
> CUBE_MAX_DIM
)
91 (errcode
(ERRCODE_INVALID_TEXT_REPRESENTATION
),
92 errmsg
("invalid input syntax for cube"),
93 errdetail
("A cube cannot have more than %d dimensions.",
98 if
(!write_box
(dim
, $1, $3, result
, escontext
))
106 dim
= item_count
($1, ',');
107 if
(dim
> CUBE_MAX_DIM
)
110 (errcode
(ERRCODE_INVALID_TEXT_REPRESENTATION
),
111 errmsg
("invalid input syntax for cube"),
112 errdetail
("A cube cannot have more than %d dimensions.",
117 if
(!write_point_as_box
(dim
, $1, result
, escontext
))
125 dim
= item_count
($1, ',');
126 if
(dim
> CUBE_MAX_DIM
)
129 (errcode
(ERRCODE_INVALID_TEXT_REPRESENTATION
),
130 errmsg
("invalid input syntax for cube"),
131 errdetail
("A cube cannot have more than %d dimensions.",
136 if
(!write_point_as_box
(dim
, $1, result
, escontext
))
141 paren_list: O_PAREN list C_PAREN
153 /* alloc enough space to be sure whole list will fit */
154 $$
= palloc
(scanbuflen
+ 1);
157 | list COMMA CUBEFLOAT
167 /* This assumes the string has been normalized by productions above */
169 item_count
(const char *s
, char delim
)
176 while
((s
= strchr
(s
, delim
)) != NULL
)
186 write_box
(int dim
, char *str1
, char *str2
,
187 NDBOX
**result
, struct Node
*escontext
)
193 int size
= CUBE_SIZE
(dim
);
197 SET_VARSIZE
(bp
, size
);
204 bp
->x
[i
++] = float8in_internal
(s
, &endptr
, "cube", str1
, escontext
);
205 if
(SOFT_ERROR_OCCURRED
(escontext
))
208 while
((s
= strchr
(s
, ',')) != NULL
)
211 bp
->x
[i
++] = float8in_internal
(s
, &endptr
, "cube", str1
, escontext
);
212 if
(SOFT_ERROR_OCCURRED
(escontext
))
220 bp
->x
[i
] = float8in_internal
(s
, &endptr
, "cube", str2
, escontext
);
221 if
(SOFT_ERROR_OCCURRED
(escontext
))
223 /* code this way to do right thing with NaN */
224 point
&= (bp
->x
[i
] == bp
->x
[0]);
227 while
((s
= strchr
(s
, ',')) != NULL
)
230 bp
->x
[i
] = float8in_internal
(s
, &endptr
, "cube", str2
, escontext
);
231 if
(SOFT_ERROR_OCCURRED
(escontext
))
233 point
&= (bp
->x
[i
] == bp
->x
[i
- dim
]);
236 Assert
(i
== dim
* 2);
241 * The value turned out to be a point, ie. all the upper-right
242 * coordinates were equal to the lower-left coordinates. Resize the
243 * cube we constructed. Note: we don't bother to repalloc() it
244 * smaller, as it's unlikely that the tiny amount of memory freed
245 * that way would be useful, and the output is always short-lived.
247 size
= POINT_SIZE
(dim
);
248 SET_VARSIZE
(bp
, size
);
257 write_point_as_box
(int dim
, char *str
,
258 NDBOX
**result
, struct Node
*escontext
)
266 size
= POINT_SIZE
(dim
);
268 SET_VARSIZE
(bp
, size
);
276 bp
->x
[i
++] = float8in_internal
(s
, &endptr
, "cube", str
, escontext
);
277 if
(SOFT_ERROR_OCCURRED
(escontext
))
280 while
((s
= strchr
(s
, ',')) != NULL
)
283 bp
->x
[i
++] = float8in_internal
(s
, &endptr
, "cube", str
, escontext
);
284 if
(SOFT_ERROR_OCCURRED
(escontext
))