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)
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; }
75 1 : permutation { return PERMUTATION; }
76 1159 : session { return SESSION; }
77 CBC 1159 : setup { return SETUP; }
78 GIC 320 : step { return STEP; }
79 CBC 331 : teardown { return TEARDOWN; }
80 1320 :
81 GIC 145 : /* Whitespace and comments */
82 : [\n] { yyline++; }
83 6701 : {comment} { /* ignore */ }
84 6701 : {space} { /* ignore */ }
85 CBC 1426 :
86 15335 : /* Plain identifiers */
87 ECB : {identifier} {
88 GNC 9249 : spec_yylval.str = pg_strdup(yytext);
89 CBC 9249 : return(identifier);
90 9249 : }
91 ECB :
92 : /* Quoted identifiers: "foo" */
93 : \" {
94 CBC 1062 : litbufpos = 0;
95 1062 : BEGIN(qident);
96 1062 : }
97 : <qident>\"\" { addlitchar(yytext[0]); }
98 1062 : <qident>\" {
99 LBC 0 : litbuf[litbufpos] = '\0';
100 GNC 1062 : spec_yylval.str = pg_strdup(litbuf);
101 GIC 1062 : BEGIN(INITIAL);
102 1062 : return(identifier);
103 1062 : }
104 ECB : <qident>. { addlitchar(yytext[0]); }
105 GNC 9255 : <qident>\n { spec_yyerror("unexpected newline in quoted identifier"); }
106 9255 : <qident><<EOF>> { spec_yyerror("unterminated quoted identifier"); }
107 UIC 0 :
108 LBC 0 : /* SQL blocks: { UPDATE ... } */
109 EUB : /* We trim leading/trailing whitespace, otherwise they're unprocessed */
110 ECB : "{"{space}* {
111 CBC 1796 :
112 ECB : litbufpos = 0;
113 CBC 1796 : BEGIN(sql);
114 GIC 1796 : }
115 ECB : <sql>{space}*"}" {
116 CBC 1796 : litbuf[litbufpos] = '\0';
117 GNC 1796 : spec_yylval.str = pg_strdup(litbuf);
118 GBC 1796 : BEGIN(INITIAL);
119 GIC 1796 : return(sqlblock);
120 1796 : }
121 ECB : <sql>. {
122 : addlitchar(yytext[0]);
123 CBC 112314 : }
124 ECB : <sql>\n {
125 GIC 112314 : yyline++;
126 CBC 2149 : addlitchar(yytext[0]);
127 2149 : }
128 ECB : <sql><<EOF>> {
129 GNC 2149 : spec_yyerror("unterminated sql block");
130 LBC 0 : }
131 :
132 UIC 0 : /* Numbers and punctuation */
133 ECB : {digit}+ {
134 GNC 1 : spec_yylval.integer = atoi(yytext);
135 CBC 1 : return INTEGER;
136 1 : }
137 ECB :
138 : {self} { return yytext[0]; }
139 CBC 107 :
140 EUB : /* Anything else is an error */
141 : . {
142 UBC 0 : fprintf(stderr, "syntax error at line %d: unexpected character \"%s\"\n", yyline, yytext);
143 UIC 0 : exit(1);
144 LBC 0 : }
145 ECB : %%
146 LBC 0 :
147 UIC 0 : /* LCOV_EXCL_STOP */
148 :
149 ECB : static void
150 : addlitchar(char c)
151 GIC 123718 : {
152 EUB : /* We must always leave room to add a trailing \0 */
153 : if (litbufpos >= litbufsize - 1)
154 GBC 123718 : {
155 : /* Double the size of litbuf if it gets full */
156 EUB : litbufsize += litbufsize;
157 GBC 7 : litbuf = pg_realloc(litbuf, litbufsize);
158 GIC 7 : }
159 : litbuf[litbufpos++] = c;
160 123718 : }
161 CBC 123718 :
162 : void
163 : spec_yyerror(const char *message)
164 LBC 0 : {
165 : fprintf(stderr, "%s at line %d\n", message, yyline);
166 UIC 0 : exit(1);
167 LBC 0 : }
|