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