TLA 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 CBC 7 : result->lower = $1.val - $3.val;
69 7 : result->upper = $1.val + $3.val;
70 7 : sprintf(strbuf, "%g", result->lower);
71 7 : result->l_sigd = Max(sig_digits(strbuf), Max($1.sigd, $3.sigd));
72 7 : sprintf(strbuf, "%g", result->upper);
73 7 : result->u_sigd = Max(sig_digits(strbuf), Max($1.sigd, $3.sigd));
74 7 : result->l_ext = '\0';
75 7 : result->u_ext = '\0';
76 : }
77 :
78 : | boundary RANGE boundary
79 : {
80 2351 : result->lower = $1.val;
81 2351 : result->upper = $3.val;
82 2351 : if ( result->lower > result->upper ) {
83 UNC 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 UBC 0 : YYERROR;
89 : }
90 CBC 2351 : result->l_sigd = $1.sigd;
91 2351 : result->u_sigd = $3.sigd;
92 2351 : result->l_ext = ( $1.ext ? $1.ext : '\0' );
93 2351 : result->u_ext = ( $3.ext ? $3.ext : '\0' );
94 : }
95 :
96 : | boundary RANGE
97 : {
98 46 : result->lower = $1.val;
99 46 : result->upper = HUGE_VAL;
100 46 : result->l_sigd = $1.sigd;
101 46 : result->u_sigd = 0;
102 46 : result->l_ext = ( $1.ext ? $1.ext : '\0' );
103 46 : result->u_ext = '-';
104 : }
105 :
106 : | RANGE boundary
107 : {
108 49 : result->lower = -HUGE_VAL;
109 49 : result->upper = $2.val;
110 49 : result->l_sigd = 0;
111 49 : result->u_sigd = $2.sigd;
112 49 : result->l_ext = '-';
113 49 : result->u_ext = ( $2.ext ? $2.ext : '\0' );
114 : }
115 :
116 : | boundary
117 : {
118 360 : result->lower = result->upper = $1.val;
119 360 : result->l_sigd = result->u_sigd = $1.sigd;
120 360 : 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 GNC 3950 : if (!seg_atof($1, &val, escontext))
130 2 : YYABORT;
131 :
132 CBC 3947 : $$.ext = '\0';
133 3947 : $$.sigd = sig_digits($1);
134 GIC 3947 : $$.val = val;
135 ECB : }
136 : | EXTENSION SEGFLOAT
137 : {
138 : /* temp variable avoids a gcc 3.3.x bug on Sparc64 */
139 : float val;
140 :
141 GNC 1217 : if (!seg_atof($2, &val, escontext))
142 UNC 0 : YYABORT;
143 :
144 GIC 1217 : $$.ext = $1[0];
145 1217 : $$.sigd = sig_digits($2);
146 1217 : $$.val = val;
147 ECB : }
148 EUB : ;
149 :
150 ECB : deviation: SEGFLOAT
151 : {
152 : /* temp variable avoids a gcc 3.3.x bug on Sparc64 */
153 : float val;
154 :
155 GNC 7 : if (!seg_atof($1, &val, escontext))
156 UNC 0 : YYABORT;
157 :
158 GIC 7 : $$.ext = '\0';
159 7 : $$.sigd = sig_digits($1);
160 7 : $$.val = val;
161 : }
162 : ;
163 :
164 ECB : %%
165 EUB :
166 :
167 : static bool
168 GNC 5174 : seg_atof(char *value, float *result, struct Node *escontext)
169 ECB : {
170 GNC 5174 : *result = float4in_internal(value, NULL, "seg", value, escontext);
171 5173 : if (SOFT_ERROR_OCCURRED(escontext))
172 2 : return false;
173 5171 : return true;
174 : }
175 :
176 : static int
177 CBC 5187 : sig_digits(const char *value)
178 : {
179 5187 : int n = significant_digits(value);
180 ECB :
181 : /* Clamp, to ensure value will fit in sigd fields */
182 CBC 5187 : return Min(n, FLT_DIG);
183 : }
|