summaryrefslogtreecommitdiffstats
path: root/src/test/isolation/specscanner.l
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/isolation/specscanner.l')
-rw-r--r--src/test/isolation/specscanner.l157
1 files changed, 157 insertions, 0 deletions
diff --git a/src/test/isolation/specscanner.l b/src/test/isolation/specscanner.l
new file mode 100644
index 0000000..d9fa6a5
--- /dev/null
+++ b/src/test/isolation/specscanner.l
@@ -0,0 +1,157 @@
+%{
+/*-------------------------------------------------------------------------
+ *
+ * specscanner.l
+ * a lexical scanner for an isolation test specification
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static int yyline = 1; /* line number for error reporting */
+
+#define LITBUF_INIT 1024 /* initial size of litbuf */
+static char *litbuf = NULL;
+static size_t litbufsize = 0;
+static size_t litbufpos = 0;
+
+static void addlitchar(char c);
+
+/* LCOV_EXCL_START */
+
+%}
+
+%option 8bit
+%option never-interactive
+%option nodefault
+%option noinput
+%option nounput
+%option noyywrap
+%option warn
+%option prefix="spec_yy"
+
+
+%x sql
+%x qident
+
+non_newline [^\n\r]
+space [ \t\r\f]
+
+comment ("#"{non_newline}*)
+
+digit [0-9]
+ident_start [A-Za-z\200-\377_]
+ident_cont [A-Za-z\200-\377_0-9\$]
+
+identifier {ident_start}{ident_cont}*
+
+self [,()*]
+
+%%
+
+%{
+ /* Allocate litbuf in first call of yylex() */
+ if (litbuf == NULL)
+ {
+ litbuf = pg_malloc(LITBUF_INIT);
+ litbufsize = LITBUF_INIT;
+ }
+%}
+
+ /* Keywords (must appear before the {identifier} rule!) */
+notices { return NOTICES; }
+permutation { return PERMUTATION; }
+session { return SESSION; }
+setup { return SETUP; }
+step { return STEP; }
+teardown { return TEARDOWN; }
+
+ /* Whitespace and comments */
+[\n] { yyline++; }
+{comment} { /* ignore */ }
+{space} { /* ignore */ }
+
+ /* Plain identifiers */
+{identifier} {
+ yylval.str = pg_strdup(yytext);
+ return(identifier);
+ }
+
+ /* Quoted identifiers: "foo" */
+\" {
+ litbufpos = 0;
+ BEGIN(qident);
+ }
+<qident>\"\" { addlitchar(yytext[0]); }
+<qident>\" {
+ litbuf[litbufpos] = '\0';
+ yylval.str = pg_strdup(litbuf);
+ BEGIN(INITIAL);
+ return(identifier);
+ }
+<qident>. { addlitchar(yytext[0]); }
+<qident>\n { yyerror("unexpected newline in quoted identifier"); }
+<qident><<EOF>> { yyerror("unterminated quoted identifier"); }
+
+ /* SQL blocks: { UPDATE ... } */
+ /* We trim leading/trailing whitespace, otherwise they're unprocessed */
+"{"{space}* {
+
+ litbufpos = 0;
+ BEGIN(sql);
+ }
+<sql>{space}*"}" {
+ litbuf[litbufpos] = '\0';
+ yylval.str = pg_strdup(litbuf);
+ BEGIN(INITIAL);
+ return(sqlblock);
+ }
+<sql>. {
+ addlitchar(yytext[0]);
+ }
+<sql>\n {
+ yyline++;
+ addlitchar(yytext[0]);
+ }
+<sql><<EOF>> {
+ yyerror("unterminated sql block");
+ }
+
+ /* Numbers and punctuation */
+{digit}+ {
+ yylval.integer = atoi(yytext);
+ return INTEGER;
+ }
+
+{self} { return yytext[0]; }
+
+ /* Anything else is an error */
+. {
+ fprintf(stderr, "syntax error at line %d: unexpected character \"%s\"\n", yyline, yytext);
+ exit(1);
+ }
+%%
+
+/* LCOV_EXCL_STOP */
+
+static void
+addlitchar(char c)
+{
+ /* We must always leave room to add a trailing \0 */
+ if (litbufpos >= litbufsize - 1)
+ {
+ /* Double the size of litbuf if it gets full */
+ litbufsize += litbufsize;
+ litbuf = pg_realloc(litbuf, litbufsize);
+ }
+ litbuf[litbufpos++] = c;
+}
+
+void
+yyerror(const char *message)
+{
+ fprintf(stderr, "%s at line %d\n", message, yyline);
+ exit(1);
+}