
This adds extern declarations for some global variables produced by Bison that are not already declared in its generated header file. This is a workaround to be able to add -Wmissing-variable-declarations to the global set of warning options in the near future. Another longer-term solution would be to convert these grammars to "pure" parsers in Bison, to avoid global variables altogether. Note that the core grammar is already pure, so this patch did not need to touch it. Reviewed-by: Andres Freund <andres@anarazel.de> Discussion: https://www.postgresql.org/message-id/flat/e0a62134-83da-4ba4-8cdb-ceb0111c95ce@eisentraut.org
188 lines
3.6 KiB
Plaintext
188 lines
3.6 KiB
Plaintext
%{
|
|
/* 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"
|
|
|
|
/* silence -Wmissing-variable-declarations */
|
|
extern int seg_yychar;
|
|
extern int seg_yynerrs;
|
|
|
|
/*
|
|
* 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);
|
|
}
|