summaryrefslogtreecommitdiff
path: root/contrib/pgbench/exprscan.l
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/pgbench/exprscan.l')
-rw-r--r--contrib/pgbench/exprscan.l105
1 files changed, 105 insertions, 0 deletions
diff --git a/contrib/pgbench/exprscan.l b/contrib/pgbench/exprscan.l
new file mode 100644
index 00000000000..4c9229cd9cf
--- /dev/null
+++ b/contrib/pgbench/exprscan.l
@@ -0,0 +1,105 @@
+%{
+/*-------------------------------------------------------------------------
+ *
+ * exprscan.l
+ * a lexical scanner for a simple expression syntax
+ *
+ * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/* line and column number for error reporting */
+static int yyline = 0, yycol = 0;
+
+/* Handles to the buffer that the lexer uses internally */
+static YY_BUFFER_STATE scanbufhandle;
+static char *scanbuf;
+static int scanbuflen;
+
+/* flex 2.5.4 doesn't bother with a decl for this */
+int expr_yylex(void);
+
+%}
+
+%option 8bit
+%option never-interactive
+%option nodefault
+%option noinput
+%option nounput
+%option noyywrap
+%option warn
+%option prefix="expr_yy"
+
+non_newline [^\n\r]
+space [ \t\r\f]
+
+%%
+
+"+" { yycol += yyleng; return '+'; }
+"-" { yycol += yyleng; return '-'; }
+"*" { yycol += yyleng; return '*'; }
+"/" { yycol += yyleng; return '/'; }
+"%" { yycol += yyleng; return '%'; }
+"(" { yycol += yyleng; return '('; }
+")" { yycol += yyleng; return ')'; }
+:[a-zA-Z0-9_]+ { yycol += yyleng; yylval.str = pg_strdup(yytext + 1); return VARIABLE; }
+[0-9]+ { yycol += yyleng; yylval.ival = strtoint64(yytext); return INTEGER; }
+
+[\n] { yycol = 0; yyline++; }
+{space} { yycol += yyleng; /* ignore */ }
+
+. {
+ yycol += yyleng;
+ fprintf(stderr, "unexpected character '%s'\n", yytext);
+ return CHAR_ERROR;
+ }
+%%
+
+void
+yyerror(const char *message)
+{
+ /* yyline is always 1 as pgbench calls the parser for each line...
+ * so the interesting location information is the column number */
+ fprintf(stderr, "%s at column %d\n", message, yycol);
+ /* go on to raise the error from pgbench with more information */
+ /* exit(1); */
+}
+
+/*
+ * Called before any actual parsing is done
+ */
+void
+expr_scanner_init(const char *str)
+{
+ Size slen = strlen(str);
+
+ /*
+ * Might be left over after error
+ */
+ if (YY_CURRENT_BUFFER)
+ yy_delete_buffer(YY_CURRENT_BUFFER);
+
+ /*
+ * Make a scan buffer with special termination needed by flex.
+ */
+ scanbuflen = slen;
+ scanbuf = pg_malloc(slen + 2);
+ memcpy(scanbuf, str, slen);
+ scanbuf[slen] = scanbuf[slen + 1] = YY_END_OF_BUFFER_CHAR;
+ scanbufhandle = yy_scan_buffer(scanbuf, slen + 2);
+
+ BEGIN(INITIAL);
+}
+
+
+/*
+ * Called after parsing is done to clean up after seg_scanner_init()
+ */
+void
+expr_scanner_finish(void)
+{
+ yy_delete_buffer(scanbufhandle);
+ pg_free(scanbuf);
+}