summaryrefslogtreecommitdiff
path: root/contrib/cube/cubeparse.y
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/cube/cubeparse.y')
-rw-r--r--contrib/cube/cubeparse.y252
1 files changed, 252 insertions, 0 deletions
diff --git a/contrib/cube/cubeparse.y b/contrib/cube/cubeparse.y
new file mode 100644
index 00000000000..33b7c1ef6b0
--- /dev/null
+++ b/contrib/cube/cubeparse.y
@@ -0,0 +1,252 @@
+%{
+/* 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);
+}
+