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-2024, 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 0 : /* LCOV_EXCL_STOP */ 148 : 149 : static void 150 : addlitchar(char c) 151 261666 : { 152 : /* We must always leave room to add a trailing \0 */ 153 : if (litbufpos >= litbufsize - 1) 154 261666 : { 155 : /* Double the size of litbuf if it gets full */ 156 : litbufsize += litbufsize; 157 14 : litbuf = pg_realloc(litbuf, litbufsize); 158 14 : } 159 : litbuf[litbufpos++] = c; 160 261666 : } 161 261666 : 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 : }