Age Owner TLA Line data Source code
1 : %top{
2 : /*-------------------------------------------------------------------------
3 : *
4 : * specscanner.l
5 : * a lexical scanner for an isolation test specification
6 : *
7 : * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
8 : * Portions Copyright (c) 1994, Regents of the University of California
9 : *
10 : *-------------------------------------------------------------------------
11 : */
12 : #include "postgres_fe.h"
13 :
14 : /*
15 : * NB: include specparse.h only AFTER including isolationtester.h, because
16 : * isolationtester.h includes node definitions needed for YYSTYPE.
17 : */
18 : #include "isolationtester.h"
19 : #include "specparse.h"
20 : }
21 :
22 : %{
23 : static int yyline = 1; /* line number for error reporting */
24 :
25 : #define LITBUF_INIT 1024 /* initial size of litbuf */
26 : static char *litbuf = NULL;
27 : static size_t litbufsize = 0;
28 : static size_t litbufpos = 0;
29 :
30 : static void addlitchar(char c);
31 :
32 : /* LCOV_EXCL_START */
33 :
34 : %}
35 :
36 : %option 8bit
37 : %option never-interactive
38 : %option nodefault
39 : %option noinput
40 : %option nounput
41 : %option noyywrap
42 : %option warn
43 : %option prefix="spec_yy"
44 :
45 :
46 : %x sql
47 : %x qident
48 :
49 : non_newline [^\n\r]
50 : space [ \t\r\f]
51 :
52 : comment ("#"{non_newline}*)
53 :
54 : digit [0-9]
55 : ident_start [A-Za-z\200-\377_]
56 : ident_cont [A-Za-z\200-\377_0-9\$]
57 :
58 : identifier {ident_start}{ident_cont}*
59 :
60 : self [,()*]
61 :
62 : %%
63 :
64 : %{
65 : /* Allocate litbuf in first call of yylex() */
66 : if (litbuf == NULL)
651 tgl 67 GIC 15622 : {
68 : litbuf = pg_malloc(LITBUF_INIT);
69 131 : litbufsize = LITBUF_INIT;
70 131 : }
71 : %}
72 :
73 : /* Keywords (must appear before the {identifier} rule!) */
74 : notices { return NOTICES; }
2061 peter_e 75 1 : permutation { return PERMUTATION; }
76 1159 : session { return SESSION; }
2061 peter_e 77 CBC 1159 : setup { return SETUP; }
2061 peter_e 78 GIC 320 : step { return STEP; }
2061 peter_e 79 CBC 331 : teardown { return TEARDOWN; }
4444 heikki.linnakangas 80 1320 :
655 tgl 81 GIC 145 : /* Whitespace and comments */
82 : [\n] { yyline++; }
4413 heikki.linnakangas 83 6701 : {comment} { /* ignore */ }
84 6701 : {space} { /* ignore */ }
4444 heikki.linnakangas 85 CBC 1426 :
655 tgl 86 15335 : /* Plain identifiers */
655 tgl 87 ECB : {identifier} {
217 john.naylor 88 GNC 9249 : spec_yylval.str = pg_strdup(yytext);
655 tgl 89 CBC 9249 : return(identifier);
90 9249 : }
655 tgl 91 ECB :
92 : /* Quoted identifiers: "foo" */
4444 heikki.linnakangas 93 : \" {
4444 heikki.linnakangas 94 CBC 1062 : litbufpos = 0;
655 tgl 95 1062 : BEGIN(qident);
4444 heikki.linnakangas 96 1062 : }
97 : <qident>\"\" { addlitchar(yytext[0]); }
655 tgl 98 1062 : <qident>\" {
4444 heikki.linnakangas 99 LBC 0 : litbuf[litbufpos] = '\0';
217 john.naylor 100 GNC 1062 : spec_yylval.str = pg_strdup(litbuf);
4444 heikki.linnakangas 101 GIC 1062 : BEGIN(INITIAL);
655 tgl 102 1062 : return(identifier);
4444 heikki.linnakangas 103 1062 : }
655 tgl 104 ECB : <qident>. { addlitchar(yytext[0]); }
217 john.naylor 105 GNC 9255 : <qident>\n { spec_yyerror("unexpected newline in quoted identifier"); }
106 9255 : <qident><<EOF>> { spec_yyerror("unterminated quoted identifier"); }
4444 heikki.linnakangas 107 UIC 0 :
4413 heikki.linnakangas 108 LBC 0 : /* SQL blocks: { UPDATE ... } */
655 tgl 109 EUB : /* We trim leading/trailing whitespace, otherwise they're unprocessed */
4252 heikki.linnakangas 110 ECB : "{"{space}* {
4444 heikki.linnakangas 111 CBC 1796 :
4444 heikki.linnakangas 112 ECB : litbufpos = 0;
4444 heikki.linnakangas 113 CBC 1796 : BEGIN(sql);
4444 heikki.linnakangas 114 GIC 1796 : }
4252 heikki.linnakangas 115 ECB : <sql>{space}*"}" {
4444 heikki.linnakangas 116 CBC 1796 : litbuf[litbufpos] = '\0';
217 john.naylor 117 GNC 1796 : spec_yylval.str = pg_strdup(litbuf);
4444 heikki.linnakangas 118 GBC 1796 : BEGIN(INITIAL);
4444 heikki.linnakangas 119 GIC 1796 : return(sqlblock);
120 1796 : }
4413 heikki.linnakangas 121 ECB : <sql>. {
122 : addlitchar(yytext[0]);
4413 heikki.linnakangas 123 CBC 112314 : }
4413 heikki.linnakangas 124 ECB : <sql>\n {
4413 heikki.linnakangas 125 GIC 112314 : yyline++;
4413 heikki.linnakangas 126 CBC 2149 : addlitchar(yytext[0]);
127 2149 : }
4413 heikki.linnakangas 128 ECB : <sql><<EOF>> {
217 john.naylor 129 GNC 2149 : spec_yyerror("unterminated sql block");
4413 heikki.linnakangas 130 LBC 0 : }
131 :
655 tgl 132 UIC 0 : /* Numbers and punctuation */
655 tgl 133 ECB : {digit}+ {
217 john.naylor 134 GNC 1 : spec_yylval.integer = atoi(yytext);
655 tgl 135 CBC 1 : return INTEGER;
136 1 : }
655 tgl 137 ECB :
138 : {self} { return yytext[0]; }
655 tgl 139 CBC 107 :
655 tgl 140 EUB : /* Anything else is an error */
141 : . {
4444 heikki.linnakangas 142 UBC 0 : fprintf(stderr, "syntax error at line %d: unexpected character \"%s\"\n", yyline, yytext);
4444 heikki.linnakangas 143 UIC 0 : exit(1);
4444 heikki.linnakangas 144 LBC 0 : }
4444 heikki.linnakangas 145 ECB : %%
4444 heikki.linnakangas 146 LBC 0 :
2068 peter_e 147 UIC 0 : /* LCOV_EXCL_STOP */
148 :
4444 heikki.linnakangas 149 ECB : static void
150 : addlitchar(char c)
4444 heikki.linnakangas 151 GIC 123718 : {
1866 tgl 152 EUB : /* We must always leave room to add a trailing \0 */
153 : if (litbufpos >= litbufsize - 1)
4177 peter_e 154 GBC 123718 : {
155 : /* Double the size of litbuf if it gets full */
1866 tgl 156 EUB : litbufsize += litbufsize;
1866 tgl 157 GBC 7 : litbuf = pg_realloc(litbuf, litbufsize);
4177 peter_e 158 GIC 7 : }
159 : litbuf[litbufpos++] = c;
4444 heikki.linnakangas 160 123718 : }
4444 heikki.linnakangas 161 CBC 123718 :
162 : void
163 : spec_yyerror(const char *message)
4444 heikki.linnakangas 164 LBC 0 : {
165 : fprintf(stderr, "%s at line %d\n", message, yyline);
4444 heikki.linnakangas 166 UIC 0 : exit(1);
4444 heikki.linnakangas 167 LBC 0 : }
|