mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-03 08:00:21 +08:00
253 lines
5.7 KiB
Plaintext
253 lines
5.7 KiB
Plaintext
|
%{
|
||
|
/* NdBox = [(lowerleft),(upperright)] */
|
||
|
/* [(xLL(1)...xLL(N)),(xUR(1)...xUR(n))] */
|
||
|
|
||
|
#define YYERROR_VERBOSE
|
||
|
#define YYPARSE_PARAM result /* need this to pass a pointer (void *) to yyparse */
|
||
|
#define YYSTYPE char *
|
||
|
#define YYDEBUG 1
|
||
|
|
||
|
#include <string.h>
|
||
|
#include "cubedata.h"
|
||
|
#include "buffer.h"
|
||
|
|
||
|
#include "postgres.h"
|
||
|
#include "utils/palloc.h"
|
||
|
#include "utils/elog.h"
|
||
|
|
||
|
#undef yylex /* falure to redefine yylex will result in a call to the */
|
||
|
#define yylex cube_yylex /* wrong scanner when running inside the postgres backend */
|
||
|
|
||
|
extern int yylex(); /* defined as cube_yylex in cubescan.c */
|
||
|
extern int errno;
|
||
|
|
||
|
int cube_yyerror( char *msg );
|
||
|
int cube_yyparse(void *result);
|
||
|
|
||
|
static int delim_count(char *s, char delim);
|
||
|
static NDBOX * write_box(unsigned int dim, char *str1, char *str2);
|
||
|
static NDBOX * write_point_as_box(char *s);
|
||
|
|
||
|
%}
|
||
|
|
||
|
/* BISON Declarations */
|
||
|
%token FLOAT O_PAREN C_PAREN O_BRACKET C_BRACKET COMMA
|
||
|
%start box
|
||
|
|
||
|
/* Grammar follows */
|
||
|
%%
|
||
|
|
||
|
box:
|
||
|
O_BRACKET paren_list COMMA paren_list C_BRACKET {
|
||
|
|
||
|
int dim;
|
||
|
int c = parse_buffer_curr_char();
|
||
|
int pos = parse_buffer_pos();
|
||
|
|
||
|
/* We can't let the parser recognize more than one valid expression:
|
||
|
the job is done and memory is allocated. */
|
||
|
if ( c != '\0' ) {
|
||
|
/* Not at EOF */
|
||
|
reset_parse_buffer();
|
||
|
elog(ERROR, "(0) bad cube representation; garbage at or before char %d, ('%c', \\%03o)\n", pos, c, c );
|
||
|
YYERROR;
|
||
|
}
|
||
|
|
||
|
dim = delim_count($2, ',') + 1;
|
||
|
if ( (delim_count($4, ',') + 1) != dim ) {
|
||
|
reset_parse_buffer();
|
||
|
elog(ERROR, "(1) bad cube representation; different point dimensions in (%s) and (%s)\n", $2, $4);
|
||
|
YYABORT;
|
||
|
}
|
||
|
|
||
|
*((void **)result) = write_box( dim, $2, $4 );
|
||
|
|
||
|
}
|
||
|
|
|
||
|
paren_list COMMA paren_list {
|
||
|
int dim;
|
||
|
int c = parse_buffer_curr_char();
|
||
|
int pos = parse_buffer_pos();
|
||
|
|
||
|
if ( c != '\0' ) { /* Not at EOF */
|
||
|
reset_parse_buffer();
|
||
|
elog(ERROR, "(2) bad cube representation; garbage at or before char %d, ('%c', \\%03o)\n", pos, c, c );
|
||
|
YYABORT;
|
||
|
}
|
||
|
|
||
|
dim = delim_count($1, ',') + 1;
|
||
|
|
||
|
if ( (delim_count($3, ',') + 1) != dim ) {
|
||
|
reset_parse_buffer();
|
||
|
elog(ERROR, "(3) bad cube representation; different point dimensions in (%s) and (%s)\n", $1, $3);
|
||
|
YYABORT;
|
||
|
}
|
||
|
|
||
|
*((void **)result) = write_box( dim, $1, $3 );
|
||
|
}
|
||
|
|
|
||
|
|
||
|
paren_list {
|
||
|
int c = parse_buffer_curr_char();
|
||
|
int pos = parse_buffer_pos();
|
||
|
|
||
|
if ( c != '\0') { /* Not at EOF */
|
||
|
reset_parse_buffer();
|
||
|
elog(ERROR, "(4) bad cube representation; garbage at or before char %d, ('%c', \\%03o)\n", pos, c, c );
|
||
|
YYABORT;
|
||
|
}
|
||
|
|
||
|
if ( yychar != YYEOF) {
|
||
|
/* There's still a lookahead token to be parsed */
|
||
|
reset_parse_buffer();
|
||
|
elog(ERROR, "(5) bad cube representation; garbage at or before char %d, ('end of input', \\%03o)\n", pos, c);
|
||
|
YYABORT;
|
||
|
}
|
||
|
|
||
|
*((void **)result) = write_point_as_box($1);
|
||
|
}
|
||
|
|
||
|
|
|
||
|
|
||
|
list {
|
||
|
int c = parse_buffer_curr_char();
|
||
|
int pos = parse_buffer_pos();
|
||
|
|
||
|
if ( c != '\0') { /* Not at EOF */
|
||
|
reset_parse_buffer();
|
||
|
elog(ERROR, "(6) bad cube representation; garbage at or before char %d, ('%c', \\%03o)\n", pos, c, c);
|
||
|
YYABORT;
|
||
|
}
|
||
|
|
||
|
if ( yychar != YYEOF) {
|
||
|
/* There's still a lookahead token to be parsed */
|
||
|
reset_parse_buffer();
|
||
|
elog(ERROR, "(7) bad cube representation; garbage at or before char %d, ('end of input', \\%03o)\n", pos, c);
|
||
|
YYABORT;
|
||
|
}
|
||
|
|
||
|
*((void **)result) = write_point_as_box($1);
|
||
|
}
|
||
|
;
|
||
|
|
||
|
paren_list:
|
||
|
O_PAREN list C_PAREN {
|
||
|
$$ = $2;
|
||
|
}
|
||
|
;
|
||
|
|
||
|
list:
|
||
|
FLOAT {
|
||
|
$$ = palloc(strlen(parse_buffer()) + 1);
|
||
|
strcpy($$, $1);
|
||
|
}
|
||
|
|
|
||
|
list COMMA FLOAT {
|
||
|
$$ = $1;
|
||
|
strcat($$, ",");
|
||
|
strcat($$, $3);
|
||
|
}
|
||
|
;
|
||
|
|
||
|
%%
|
||
|
|
||
|
|
||
|
int cube_yyerror ( char *msg ) {
|
||
|
char *buf = (char *) palloc(256);
|
||
|
int position;
|
||
|
|
||
|
yyclearin;
|
||
|
|
||
|
if ( !strcmp(msg, "parse error, expecting `$'") ) {
|
||
|
msg = "expecting end of input";
|
||
|
}
|
||
|
|
||
|
position = parse_buffer_pos() > parse_buffer_size() ? parse_buffer_pos() - 1 : parse_buffer_pos();
|
||
|
|
||
|
sprintf(
|
||
|
buf,
|
||
|
"%s at or before position %d, character ('%c', \\%03o), input: '%s'\n",
|
||
|
msg,
|
||
|
position,
|
||
|
parse_buffer()[position - 1],
|
||
|
parse_buffer()[position - 1],
|
||
|
parse_buffer()
|
||
|
);
|
||
|
|
||
|
reset_parse_buffer();
|
||
|
elog(ERROR, buf);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
delim_count(char *s, char delim)
|
||
|
{
|
||
|
int ndelim = 0;
|
||
|
|
||
|
while ((s = strchr(s, delim)) != NULL)
|
||
|
{
|
||
|
ndelim++;
|
||
|
s++;
|
||
|
}
|
||
|
return (ndelim);
|
||
|
}
|
||
|
|
||
|
static NDBOX *
|
||
|
write_box(unsigned int dim, char *str1, char *str2)
|
||
|
{
|
||
|
NDBOX * bp;
|
||
|
char * s;
|
||
|
int i;
|
||
|
int size = offsetof(NDBOX, x[0]) + sizeof(float) * dim * 2;
|
||
|
|
||
|
bp = palloc(size);
|
||
|
bp->size = size;
|
||
|
bp->dim = dim;
|
||
|
|
||
|
s = str1;
|
||
|
bp->x[i=0] = strtod(s, NULL);
|
||
|
while ((s = strchr(s, ',')) != NULL) {
|
||
|
s++; i++;
|
||
|
bp->x[i] = strtod(s, NULL);
|
||
|
}
|
||
|
|
||
|
s = str2;
|
||
|
bp->x[i=dim] = strtod(s, NULL);
|
||
|
while ((s = strchr(s, ',')) != NULL) {
|
||
|
s++; i++;
|
||
|
bp->x[i] = strtod(s, NULL);
|
||
|
}
|
||
|
|
||
|
return(bp);
|
||
|
}
|
||
|
|
||
|
|
||
|
static NDBOX * write_point_as_box(char *str)
|
||
|
{
|
||
|
NDBOX * bp;
|
||
|
int i, size;
|
||
|
double x;
|
||
|
int dim = delim_count(str, ',') + 1;
|
||
|
char * s = str;
|
||
|
|
||
|
size = offsetof(NDBOX, x[0]) + sizeof(float) * dim * 2;
|
||
|
|
||
|
bp = palloc(size);
|
||
|
bp->size = size;
|
||
|
bp->dim = dim;
|
||
|
|
||
|
i = 0;
|
||
|
x = strtod(s, NULL);
|
||
|
bp->x[0] = x;
|
||
|
bp->x[dim] = x;
|
||
|
while ((s = strchr(s, ',')) != NULL) {
|
||
|
s++; i++;
|
||
|
x = strtod(s, NULL);
|
||
|
bp->x[i] = x;
|
||
|
bp->x[i+dim] = x;
|
||
|
}
|
||
|
|
||
|
return(bp);
|
||
|
}
|
||
|
|