Line data Source code
1 : %{
2 : /* contrib/seg/segparse.y */
3 :
4 : #include "postgres.h"
5 :
6 : #include <float.h>
7 : #include <math.h>
8 :
9 : #include "fmgr.h"
10 : #include "nodes/miscnodes.h"
11 : #include "utils/builtins.h"
12 : #include "utils/float.h"
13 :
14 : #include "segdata.h"
15 :
16 : /*
17 : * Bison doesn't allocate anything that needs to live across parser calls,
18 : * so we can easily have it use palloc instead of malloc. This prevents
19 : * memory leaks if we error out during parsing.
20 : */
21 : #define YYMALLOC palloc
22 : #define YYFREE pfree
23 :
24 : static bool seg_atof(char *value, float *result, struct Node *escontext);
25 :
26 : static int sig_digits(const char *value);
27 :
28 : static char strbuf[25] = {
29 : '0', '0', '0', '0', '0',
30 : '0', '0', '0', '0', '0',
31 : '0', '0', '0', '0', '0',
32 : '0', '0', '0', '0', '0',
33 : '0', '0', '0', '0', '\0'
34 : };
35 :
36 : %}
37 :
38 : /* BISON Declarations */
39 : %parse-param {SEG *result}
40 : %parse-param {struct Node *escontext}
41 : %expect 0
42 : %name-prefix="seg_yy"
43 :
44 : %union
45 : {
46 : struct BND
47 : {
48 : float val;
49 : char ext;
50 : char sigd;
51 : } bnd;
52 : char *text;
53 : }
54 : %token <text> SEGFLOAT
55 : %token <text> RANGE
56 : %token <text> PLUMIN
57 : %token <text> EXTENSION
58 : %type <bnd> boundary
59 : %type <bnd> deviation
60 : %start range
61 :
62 : /* Grammar follows */
63 : %%
64 :
65 :
66 : range: boundary PLUMIN deviation
67 : {
68 14 : result->lower = $1.val - $3.val;
69 14 : result->upper = $1.val + $3.val;
70 14 : sprintf(strbuf, "%g", result->lower);
71 14 : result->l_sigd = Max(sig_digits(strbuf), Max($1.sigd, $3.sigd));
72 14 : sprintf(strbuf, "%g", result->upper);
73 14 : result->u_sigd = Max(sig_digits(strbuf), Max($1.sigd, $3.sigd));
74 14 : result->l_ext = '\0';
75 14 : result->u_ext = '\0';
76 : }
77 :
78 : | boundary RANGE boundary
79 : {
80 4702 : result->lower = $1.val;
81 4702 : result->upper = $3.val;
82 4702 : if ( result->lower > result->upper ) {
83 0 : errsave(escontext,
84 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
85 : errmsg("swapped boundaries: %g is greater than %g",
86 : result->lower, result->upper)));
87 :
88 0 : YYERROR;
89 : }
90 4702 : result->l_sigd = $1.sigd;
91 4702 : result->u_sigd = $3.sigd;
92 4702 : result->l_ext = ( $1.ext ? $1.ext : '\0' );
93 4702 : result->u_ext = ( $3.ext ? $3.ext : '\0' );
94 : }
95 :
96 : | boundary RANGE
97 : {
98 92 : result->lower = $1.val;
99 92 : result->upper = HUGE_VAL;
100 92 : result->l_sigd = $1.sigd;
101 92 : result->u_sigd = 0;
102 92 : result->l_ext = ( $1.ext ? $1.ext : '\0' );
103 92 : result->u_ext = '-';
104 : }
105 :
106 : | RANGE boundary
107 : {
108 98 : result->lower = -HUGE_VAL;
109 98 : result->upper = $2.val;
110 98 : result->l_sigd = 0;
111 98 : result->u_sigd = $2.sigd;
112 98 : result->l_ext = '-';
113 98 : result->u_ext = ( $2.ext ? $2.ext : '\0' );
114 : }
115 :
116 : | boundary
117 : {
118 720 : result->lower = result->upper = $1.val;
119 720 : result->l_sigd = result->u_sigd = $1.sigd;
120 720 : result->l_ext = result->u_ext = ( $1.ext ? $1.ext : '\0' );
121 : }
122 : ;
123 :
124 : boundary: SEGFLOAT
125 : {
126 : /* temp variable avoids a gcc 3.3.x bug on Sparc64 */
127 : float val;
128 :
129 7900 : if (!seg_atof($1, &val, escontext))
130 4 : YYABORT;
131 :
132 7894 : $$.ext = '\0';
133 7894 : $$.sigd = sig_digits($1);
134 7894 : $$.val = val;
135 : }
136 : | EXTENSION SEGFLOAT
137 : {
138 : /* temp variable avoids a gcc 3.3.x bug on Sparc64 */
139 : float val;
140 :
141 2434 : if (!seg_atof($2, &val, escontext))
142 0 : YYABORT;
143 :
144 2434 : $$.ext = $1[0];
145 2434 : $$.sigd = sig_digits($2);
146 2434 : $$.val = val;
147 : }
148 : ;
149 :
150 : deviation: SEGFLOAT
151 : {
152 : /* temp variable avoids a gcc 3.3.x bug on Sparc64 */
153 : float val;
154 :
155 14 : if (!seg_atof($1, &val, escontext))
156 0 : YYABORT;
157 :
158 14 : $$.ext = '\0';
159 14 : $$.sigd = sig_digits($1);
160 14 : $$.val = val;
161 : }
162 : ;
163 :
164 : %%
165 :
166 :
167 : static bool
168 10348 : seg_atof(char *value, float *result, struct Node *escontext)
169 : {
170 10348 : *result = float4in_internal(value, NULL, "seg", value, escontext);
171 10346 : if (SOFT_ERROR_OCCURRED(escontext))
172 4 : return false;
173 10342 : return true;
174 : }
175 :
176 : static int
177 10374 : sig_digits(const char *value)
178 : {
179 10374 : int n = significant_digits(value);
180 :
181 : /* Clamp, to ensure value will fit in sigd fields */
182 10374 : return Min(n, FLT_DIG);
183 : }
|