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 : /*
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.
21 : */
22 : #define YYMALLOC palloc
23 : #define YYFREE pfree
24 :
25 : static bool seg_atof(char *value, float *result, struct Node *escontext);
26 :
27 : static int sig_digits(const char *value);
28 :
29 : %}
30 :
31 : /* BISON Declarations */
32 : %parse-param {SEG *result}
33 : %parse-param {struct Node *escontext}
34 : %parse-param {yyscan_t yyscanner}
35 : %lex-param {yyscan_t yyscanner}
36 : %pure-parser
37 : %expect 0
38 : %name-prefix="seg_yy"
39 :
40 : %union
41 : {
42 : struct BND
43 : {
44 : float val;
45 : char ext;
46 : char sigd;
47 : } bnd;
48 : char *text;
49 : }
50 : %token <text> SEGFLOAT
51 : %token <text> RANGE
52 : %token <text> PLUMIN
53 : %token <text> EXTENSION
54 : %type <bnd> boundary
55 : %type <bnd> deviation
56 : %start range
57 :
58 : /* Grammar follows */
59 : %%
60 :
61 :
62 : range: boundary PLUMIN deviation
63 : {
64 : char strbuf[25];
65 :
66 : result->lower = $1.val - $3.val;
67 : result->upper = $1.val + $3.val;
68 : snprintf(strbuf, sizeof(strbuf), "%g", result->lower);
69 : result->l_sigd = Max(sig_digits(strbuf), Max($1.sigd, $3.sigd));
70 : snprintf(strbuf, sizeof(strbuf), "%g", result->upper);
71 : result->u_sigd = Max(sig_digits(strbuf), Max($1.sigd, $3.sigd));
72 : result->l_ext = '\0';
73 : result->u_ext = '\0';
74 :
75 : (void) yynerrs; /* suppress compiler warning */
76 : }
77 :
78 : | boundary RANGE boundary
79 : {
80 : result->lower = $1.val;
81 : result->upper = $3.val;
82 : if ( result->lower > result->upper ) {
83 : errsave(escontext,
84 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
85 : errmsg("swapped boundaries: %g is greater than %g",
86 : result->lower, result->upper)));
87 :
88 : YYERROR;
89 : }
90 : result->l_sigd = $1.sigd;
91 : result->u_sigd = $3.sigd;
92 : result->l_ext = ( $1.ext ? $1.ext : '\0' );
93 : result->u_ext = ( $3.ext ? $3.ext : '\0' );
94 : }
95 :
96 : | boundary RANGE
97 : {
98 : result->lower = $1.val;
99 : result->upper = HUGE_VAL;
100 : result->l_sigd = $1.sigd;
101 : result->u_sigd = 0;
102 : result->l_ext = ( $1.ext ? $1.ext : '\0' );
103 : result->u_ext = '-';
104 : }
105 :
106 : | RANGE boundary
107 : {
108 : result->lower = -HUGE_VAL;
109 : result->upper = $2.val;
110 : result->l_sigd = 0;
111 : result->u_sigd = $2.sigd;
112 : result->l_ext = '-';
113 : result->u_ext = ( $2.ext ? $2.ext : '\0' );
114 : }
115 :
116 : | boundary
117 : {
118 : result->lower = result->upper = $1.val;
119 : result->l_sigd = result->u_sigd = $1.sigd;
120 : 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 : if (!seg_atof($1, &val, escontext))
130 : YYABORT;
131 :
132 : $$.ext = '\0';
133 : $$.sigd = sig_digits($1);
134 : $$.val = val;
135 : }
136 : | EXTENSION SEGFLOAT
137 : {
138 : /* temp variable avoids a gcc 3.3.x bug on Sparc64 */
139 : float val;
140 :
141 : if (!seg_atof($2, &val, escontext))
142 : YYABORT;
143 :
144 : $$.ext = $1[0];
145 : $$.sigd = sig_digits($2);
146 : $$.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 : if (!seg_atof($1, &val, escontext))
156 : YYABORT;
157 :
158 : $$.ext = '\0';
159 : $$.sigd = sig_digits($1);
160 : $$.val = val;
161 : }
162 : ;
163 :
164 : %%
165 :
166 :
167 : static bool
168 0 : seg_atof(char *value, float *result, struct Node *escontext)
169 : {
170 0 : *result = float4in_internal(value, NULL, "seg", value, escontext);
171 0 : if (SOFT_ERROR_OCCURRED(escontext))
172 0 : return false;
173 0 : return true;
174 0 : }
175 :
176 : static int
177 0 : sig_digits(const char *value)
178 : {
179 0 : int n = significant_digits(value);
180 :
181 : /* Clamp, to ensure value will fit in sigd fields */
182 0 : return Min(n, FLT_DIG);
183 0 : }
|