summaryrefslogtreecommitdiffstats
path: root/contrib/seg/segparse.y
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 13:44:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 13:44:03 +0000
commit293913568e6a7a86fd1479e1cff8e2ecb58d6568 (patch)
treefc3b469a3ec5ab71b36ea97cc7aaddb838423a0c /contrib/seg/segparse.y
parentInitial commit. (diff)
downloadpostgresql-16-293913568e6a7a86fd1479e1cff8e2ecb58d6568.tar.xz
postgresql-16-293913568e6a7a86fd1479e1cff8e2ecb58d6568.zip
Adding upstream version 16.2.upstream/16.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'contrib/seg/segparse.y')
-rw-r--r--contrib/seg/segparse.y183
1 files changed, 183 insertions, 0 deletions
diff --git a/contrib/seg/segparse.y b/contrib/seg/segparse.y
new file mode 100644
index 0000000..bf759db
--- /dev/null
+++ b/contrib/seg/segparse.y
@@ -0,0 +1,183 @@
+%{
+/* contrib/seg/segparse.y */
+
+#include "postgres.h"
+
+#include <float.h>
+#include <math.h>
+
+#include "fmgr.h"
+#include "nodes/miscnodes.h"
+#include "utils/builtins.h"
+#include "utils/float.h"
+
+#include "segdata.h"
+
+/*
+ * Bison doesn't allocate anything that needs to live across parser calls,
+ * so we can easily have it use palloc instead of malloc. This prevents
+ * memory leaks if we error out during parsing.
+ */
+#define YYMALLOC palloc
+#define YYFREE pfree
+
+static bool seg_atof(char *value, float *result, struct Node *escontext);
+
+static int sig_digits(const char *value);
+
+static char strbuf[25] = {
+ '0', '0', '0', '0', '0',
+ '0', '0', '0', '0', '0',
+ '0', '0', '0', '0', '0',
+ '0', '0', '0', '0', '0',
+ '0', '0', '0', '0', '\0'
+};
+
+%}
+
+/* BISON Declarations */
+%parse-param {SEG *result}
+%parse-param {struct Node *escontext}
+%expect 0
+%name-prefix="seg_yy"
+
+%union
+{
+ struct BND
+ {
+ float val;
+ char ext;
+ char sigd;
+ } bnd;
+ char *text;
+}
+%token <text> SEGFLOAT
+%token <text> RANGE
+%token <text> PLUMIN
+%token <text> EXTENSION
+%type <bnd> boundary
+%type <bnd> deviation
+%start range
+
+/* Grammar follows */
+%%
+
+
+range: boundary PLUMIN deviation
+ {
+ result->lower = $1.val - $3.val;
+ result->upper = $1.val + $3.val;
+ sprintf(strbuf, "%g", result->lower);
+ result->l_sigd = Max(sig_digits(strbuf), Max($1.sigd, $3.sigd));
+ sprintf(strbuf, "%g", result->upper);
+ result->u_sigd = Max(sig_digits(strbuf), Max($1.sigd, $3.sigd));
+ result->l_ext = '\0';
+ result->u_ext = '\0';
+ }
+
+ | boundary RANGE boundary
+ {
+ result->lower = $1.val;
+ result->upper = $3.val;
+ if ( result->lower > result->upper ) {
+ errsave(escontext,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("swapped boundaries: %g is greater than %g",
+ result->lower, result->upper)));
+
+ YYERROR;
+ }
+ result->l_sigd = $1.sigd;
+ result->u_sigd = $3.sigd;
+ result->l_ext = ( $1.ext ? $1.ext : '\0' );
+ result->u_ext = ( $3.ext ? $3.ext : '\0' );
+ }
+
+ | boundary RANGE
+ {
+ result->lower = $1.val;
+ result->upper = HUGE_VAL;
+ result->l_sigd = $1.sigd;
+ result->u_sigd = 0;
+ result->l_ext = ( $1.ext ? $1.ext : '\0' );
+ result->u_ext = '-';
+ }
+
+ | RANGE boundary
+ {
+ result->lower = -HUGE_VAL;
+ result->upper = $2.val;
+ result->l_sigd = 0;
+ result->u_sigd = $2.sigd;
+ result->l_ext = '-';
+ result->u_ext = ( $2.ext ? $2.ext : '\0' );
+ }
+
+ | boundary
+ {
+ result->lower = result->upper = $1.val;
+ result->l_sigd = result->u_sigd = $1.sigd;
+ result->l_ext = result->u_ext = ( $1.ext ? $1.ext : '\0' );
+ }
+ ;
+
+boundary: SEGFLOAT
+ {
+ /* temp variable avoids a gcc 3.3.x bug on Sparc64 */
+ float val;
+
+ if (!seg_atof($1, &val, escontext))
+ YYABORT;
+
+ $$.ext = '\0';
+ $$.sigd = sig_digits($1);
+ $$.val = val;
+ }
+ | EXTENSION SEGFLOAT
+ {
+ /* temp variable avoids a gcc 3.3.x bug on Sparc64 */
+ float val;
+
+ if (!seg_atof($2, &val, escontext))
+ YYABORT;
+
+ $$.ext = $1[0];
+ $$.sigd = sig_digits($2);
+ $$.val = val;
+ }
+ ;
+
+deviation: SEGFLOAT
+ {
+ /* temp variable avoids a gcc 3.3.x bug on Sparc64 */
+ float val;
+
+ if (!seg_atof($1, &val, escontext))
+ YYABORT;
+
+ $$.ext = '\0';
+ $$.sigd = sig_digits($1);
+ $$.val = val;
+ }
+ ;
+
+%%
+
+
+static bool
+seg_atof(char *value, float *result, struct Node *escontext)
+{
+ *result = float4in_internal(value, NULL, "seg", value, escontext);
+ if (SOFT_ERROR_OCCURRED(escontext))
+ return false;
+ return true;
+}
+
+static int
+sig_digits(const char *value)
+{
+ int n = significant_digits(value);
+
+ /* Clamp, to ensure value will fit in sigd fields */
+ return Min(n, FLT_DIG);
+}