%{ /* contrib/seg/segparse.y */ #include "postgres.h" #include #include "fmgr.h" #include "utils/builtins.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 float seg_atof(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} %expect 0 %name-prefix="seg_yy" %union { struct BND { float val; char ext; char sigd; } bnd; char *text; } %token SEGFLOAT %token RANGE %token PLUMIN %token EXTENSION %type boundary %type 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(Min(6, significant_digits(strbuf)), Max($1.sigd, $3.sigd)); sprintf(strbuf, "%g", result->upper); result->u_sigd = Max(Min(6, significant_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 ) { ereport(ERROR, (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 = seg_atof($1); $$.ext = '\0'; $$.sigd = significant_digits($1); $$.val = val; } | EXTENSION SEGFLOAT { /* temp variable avoids a gcc 3.3.x bug on Sparc64 */ float val = seg_atof($2); $$.ext = $1[0]; $$.sigd = significant_digits($2); $$.val = val; } ; deviation: SEGFLOAT { /* temp variable avoids a gcc 3.3.x bug on Sparc64 */ float val = seg_atof($1); $$.ext = '\0'; $$.sigd = significant_digits($1); $$.val = val; } ; %% static float seg_atof(const char *value) { Datum datum; datum = DirectFunctionCall1(float4in, CStringGetDatum(value)); return DatumGetFloat4(datum); }