PostgreSQL Source Code git master
gramparse.h File Reference
#include "nodes/parsenodes.h"
#include "parser/scanner.h"
#include "gram.h"
Include dependency graph for gramparse.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  base_yy_extra_type
 

Macros

#define pg_yyget_extra(yyscanner)   (*((base_yy_extra_type **) (yyscanner)))
 

Typedefs

typedef struct base_yy_extra_type base_yy_extra_type
 

Functions

int base_yylex (YYSTYPE *lvalp, YYLTYPE *llocp, core_yyscan_t yyscanner)
 
void parser_init (base_yy_extra_type *yyext)
 
int base_yyparse (core_yyscan_t yyscanner)
 

Macro Definition Documentation

◆ pg_yyget_extra

#define pg_yyget_extra (   yyscanner)    (*((base_yy_extra_type **) (yyscanner)))

Definition at line 64 of file gramparse.h.

Typedef Documentation

◆ base_yy_extra_type

Function Documentation

◆ base_yylex()

int base_yylex ( YYSTYPE lvalp,
YYLTYPE llocp,
core_yyscan_t  yyscanner 
)

Definition at line 111 of file parser.c.

112{
114 int cur_token;
115 int next_token;
116 int cur_token_length;
117 YYLTYPE cur_yylloc;
118
119 /* Get next token --- we might already have it */
120 if (yyextra->have_lookahead)
121 {
122 cur_token = yyextra->lookahead_token;
123 lvalp->core_yystype = yyextra->lookahead_yylval;
124 *llocp = yyextra->lookahead_yylloc;
125 if (yyextra->lookahead_end)
126 *(yyextra->lookahead_end) = yyextra->lookahead_hold_char;
127 yyextra->have_lookahead = false;
128 }
129 else
130 cur_token = core_yylex(&(lvalp->core_yystype), llocp, yyscanner);
131
132 /*
133 * If this token isn't one that requires lookahead, just return it. If it
134 * does, determine the token length. (We could get that via strlen(), but
135 * since we have such a small set of possibilities, hardwiring seems
136 * feasible and more efficient --- at least for the fixed-length cases.)
137 */
138 switch (cur_token)
139 {
140 case FORMAT:
141 cur_token_length = 6;
142 break;
143 case NOT:
144 cur_token_length = 3;
145 break;
146 case NULLS_P:
147 cur_token_length = 5;
148 break;
149 case WITH:
150 cur_token_length = 4;
151 break;
152 case UIDENT:
153 case USCONST:
154 cur_token_length = strlen(yyextra->core_yy_extra.scanbuf + *llocp);
155 break;
156 case WITHOUT:
157 cur_token_length = 7;
158 break;
159 default:
160 return cur_token;
161 }
162
163 /*
164 * Identify end+1 of current token. core_yylex() has temporarily stored a
165 * '\0' here, and will undo that when we call it again. We need to redo
166 * it to fully revert the lookahead call for error reporting purposes.
167 */
168 yyextra->lookahead_end = yyextra->core_yy_extra.scanbuf +
169 *llocp + cur_token_length;
170 Assert(*(yyextra->lookahead_end) == '\0');
171
172 /*
173 * Save and restore *llocp around the call. It might look like we could
174 * avoid this by just passing &lookahead_yylloc to core_yylex(), but that
175 * does not work because flex actually holds onto the last-passed pointer
176 * internally, and will use that for error reporting. We need any error
177 * reports to point to the current token, not the next one.
178 */
179 cur_yylloc = *llocp;
180
181 /* Get next token, saving outputs into lookahead variables */
182 next_token = core_yylex(&(yyextra->lookahead_yylval), llocp, yyscanner);
183 yyextra->lookahead_token = next_token;
184 yyextra->lookahead_yylloc = *llocp;
185
186 *llocp = cur_yylloc;
187
188 /* Now revert the un-truncation of the current token */
189 yyextra->lookahead_hold_char = *(yyextra->lookahead_end);
190 *(yyextra->lookahead_end) = '\0';
191
192 yyextra->have_lookahead = true;
193
194 /* Replace cur_token if needed, based on lookahead */
195 switch (cur_token)
196 {
197 case FORMAT:
198 /* Replace FORMAT by FORMAT_LA if it's followed by JSON */
199 switch (next_token)
200 {
201 case JSON:
202 cur_token = FORMAT_LA;
203 break;
204 }
205 break;
206
207 case NOT:
208 /* Replace NOT by NOT_LA if it's followed by BETWEEN, IN, etc */
209 switch (next_token)
210 {
211 case BETWEEN:
212 case IN_P:
213 case LIKE:
214 case ILIKE:
215 case SIMILAR:
216 cur_token = NOT_LA;
217 break;
218 }
219 break;
220
221 case NULLS_P:
222 /* Replace NULLS_P by NULLS_LA if it's followed by FIRST or LAST */
223 switch (next_token)
224 {
225 case FIRST_P:
226 case LAST_P:
227 cur_token = NULLS_LA;
228 break;
229 }
230 break;
231
232 case WITH:
233 /* Replace WITH by WITH_LA if it's followed by TIME or ORDINALITY */
234 switch (next_token)
235 {
236 case TIME:
237 case ORDINALITY:
238 cur_token = WITH_LA;
239 break;
240 }
241 break;
242
243 case WITHOUT:
244 /* Replace WITHOUT by WITHOUT_LA if it's followed by TIME */
245 switch (next_token)
246 {
247 case TIME:
248 cur_token = WITHOUT_LA;
249 break;
250 }
251 break;
252
253 case UIDENT:
254 case USCONST:
255 /* Look ahead for UESCAPE */
256 if (next_token == UESCAPE)
257 {
258 /* Yup, so get third token, which had better be SCONST */
259 const char *escstr;
260
261 /* Again save and restore *llocp */
262 cur_yylloc = *llocp;
263
264 /* Un-truncate current token so errors point to third token */
265 *(yyextra->lookahead_end) = yyextra->lookahead_hold_char;
266
267 /* Get third token */
268 next_token = core_yylex(&(yyextra->lookahead_yylval),
269 llocp, yyscanner);
270
271 /* If we throw error here, it will point to third token */
272 if (next_token != SCONST)
273 scanner_yyerror("UESCAPE must be followed by a simple string literal",
274 yyscanner);
275
276 escstr = yyextra->lookahead_yylval.str;
277 if (strlen(escstr) != 1 || !check_uescapechar(escstr[0]))
278 scanner_yyerror("invalid Unicode escape character",
279 yyscanner);
280
281 /* Now restore *llocp; errors will point to first token */
282 *llocp = cur_yylloc;
283
284 /* Apply Unicode conversion */
285 lvalp->core_yystype.str =
286 str_udeescape(lvalp->core_yystype.str,
287 escstr[0],
288 *llocp,
289 yyscanner);
290
291 /*
292 * We don't need to revert the un-truncation of UESCAPE. What
293 * we do want to do is clear have_lookahead, thereby consuming
294 * all three tokens.
295 */
296 yyextra->have_lookahead = false;
297 }
298 else
299 {
300 /* No UESCAPE, so convert using default escape character */
301 lvalp->core_yystype.str =
302 str_udeescape(lvalp->core_yystype.str,
303 '\\',
304 *llocp,
305 yyscanner);
306 }
307
308 if (cur_token == UIDENT)
309 {
310 /* It's an identifier, so truncate as appropriate */
311 truncate_identifier(lvalp->core_yystype.str,
312 strlen(lvalp->core_yystype.str),
313 true);
314 cur_token = IDENT;
315 }
316 else if (cur_token == USCONST)
317 {
318 cur_token = SCONST;
319 }
320 break;
321 }
322
323 return cur_token;
324}
static char * str_udeescape(const char *str, char escape, int position, core_yyscan_t yyscanner)
Definition: parser.c:372
static bool check_uescapechar(unsigned char escape)
Definition: parser.c:352
#define Assert(condition)
Definition: c.h:815
#define pg_yyget_extra(yyscanner)
Definition: gramparse.h:64
static bool next_token(char **lineptr, StringInfo buf, bool *initial_quote, bool *terminating_comma)
Definition: hba.c:185
const char * YYLTYPE
#define yyextra
Definition: scan.l:1118
void scanner_yyerror(const char *message, core_yyscan_t yyscanner)
Definition: scan.l:1222
int core_yylex(core_YYSTYPE *yylval_param, YYLTYPE *yylloc_param, core_yyscan_t yyscanner)
void truncate_identifier(char *ident, int len, bool warn)
Definition: scansup.c:93

References Assert, check_uescapechar(), core_yylex(), next_token(), pg_yyget_extra, scanner_yyerror(), str_udeescape(), truncate_identifier(), and yyextra.

Referenced by base_yylex_location().

◆ base_yyparse()

int base_yyparse ( core_yyscan_t  yyscanner)

Referenced by main(), and raw_parser().

◆ parser_init()

void parser_init ( base_yy_extra_type yyext)

Referenced by raw_parser().