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 14 : result->lower = $1.val - $3.val;
67 14 : result->upper = $1.val + $3.val;
68 14 : snprintf(strbuf, sizeof(strbuf), "%g", result->lower);
69 14 : result->l_sigd = Max(sig_digits(strbuf), Max($1.sigd, $3.sigd));
70 14 : snprintf(strbuf, sizeof(strbuf), "%g", result->upper);
71 14 : result->u_sigd = Max(sig_digits(strbuf), Max($1.sigd, $3.sigd));
72 14 : result->l_ext = '\0';
73 14 : result->u_ext = '\0';
74 :
75 : (void) yynerrs; /* suppress compiler warning */
76 : }
77 :
78 : | boundary RANGE boundary
79 : {
80 4706 : result->lower = $1.val;
81 4706 : result->upper = $3.val;
82 4706 : 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 4706 : result->l_sigd = $1.sigd;
91 4706 : result->u_sigd = $3.sigd;
92 4706 : result->l_ext = ( $1.ext ? $1.ext : '\0' );
93 4706 : 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 7908 : if (!seg_atof($1, &val, escontext))
130 4 : YYABORT;
131 :
132 7902 : $$.ext = '\0';
133 7902 : $$.sigd = sig_digits($1);
134 7902 : $$.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 10356 : seg_atof(char *value, float *result, struct Node *escontext)
169 : {
170 10356 : *result = float4in_internal(value, NULL, "seg", value, escontext);
171 10354 : if (SOFT_ERROR_OCCURRED(escontext))
172 4 : return false;
173 10350 : return true;
174 : }
175 :
176 : static int
177 10382 : sig_digits(const char *value)
178 : {
179 10382 : int n = significant_digits(value);
180 :
181 : /* Clamp, to ensure value will fit in sigd fields */
182 10382 : return Min(n, FLT_DIG);
183 : }
|