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