PostgreSQL Source Code  git master
gramparse.h File Reference
#include "nodes/parsenodes.h"
#include "parser/scanner.h"
#include "parser/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 NOT:
141  cur_token_length = 3;
142  break;
143  case NULLS_P:
144  cur_token_length = 5;
145  break;
146  case WITH:
147  cur_token_length = 4;
148  break;
149  case UIDENT:
150  case USCONST:
151  cur_token_length = strlen(yyextra->core_yy_extra.scanbuf + *llocp);
152  break;
153  case WITHOUT:
154  cur_token_length = 7;
155  break;
156  default:
157  return cur_token;
158  }
159 
160  /*
161  * Identify end+1 of current token. core_yylex() has temporarily stored a
162  * '\0' here, and will undo that when we call it again. We need to redo
163  * it to fully revert the lookahead call for error reporting purposes.
164  */
165  yyextra->lookahead_end = yyextra->core_yy_extra.scanbuf +
166  *llocp + cur_token_length;
167  Assert(*(yyextra->lookahead_end) == '\0');
168 
169  /*
170  * Save and restore *llocp around the call. It might look like we could
171  * avoid this by just passing &lookahead_yylloc to core_yylex(), but that
172  * does not work because flex actually holds onto the last-passed pointer
173  * internally, and will use that for error reporting. We need any error
174  * reports to point to the current token, not the next one.
175  */
176  cur_yylloc = *llocp;
177 
178  /* Get next token, saving outputs into lookahead variables */
179  next_token = core_yylex(&(yyextra->lookahead_yylval), llocp, yyscanner);
180  yyextra->lookahead_token = next_token;
181  yyextra->lookahead_yylloc = *llocp;
182 
183  *llocp = cur_yylloc;
184 
185  /* Now revert the un-truncation of the current token */
186  yyextra->lookahead_hold_char = *(yyextra->lookahead_end);
187  *(yyextra->lookahead_end) = '\0';
188 
189  yyextra->have_lookahead = true;
190 
191  /* Replace cur_token if needed, based on lookahead */
192  switch (cur_token)
193  {
194  case NOT:
195  /* Replace NOT by NOT_LA if it's followed by BETWEEN, IN, etc */
196  switch (next_token)
197  {
198  case BETWEEN:
199  case IN_P:
200  case LIKE:
201  case ILIKE:
202  case SIMILAR:
203  cur_token = NOT_LA;
204  break;
205  }
206  break;
207 
208  case NULLS_P:
209  /* Replace NULLS_P by NULLS_LA if it's followed by FIRST or LAST */
210  switch (next_token)
211  {
212  case FIRST_P:
213  case LAST_P:
214  cur_token = NULLS_LA;
215  break;
216  }
217  break;
218 
219  case WITH:
220  /* Replace WITH by WITH_LA if it's followed by TIME or ORDINALITY */
221  switch (next_token)
222  {
223  case TIME:
224  case ORDINALITY:
225  cur_token = WITH_LA;
226  break;
227  case UNIQUE:
228  cur_token = WITH_LA_UNIQUE;
229  break;
230  }
231  break;
232 
233  case WITHOUT:
234  /* Replace WITHOUT by WITHOUT_LA if it's followed by TIME */
235  switch (next_token)
236  {
237  case TIME:
238  cur_token = WITHOUT_LA;
239  break;
240  }
241  break;
242 
243  case UIDENT:
244  case USCONST:
245  /* Look ahead for UESCAPE */
246  if (next_token == UESCAPE)
247  {
248  /* Yup, so get third token, which had better be SCONST */
249  const char *escstr;
250 
251  /* Again save and restore *llocp */
252  cur_yylloc = *llocp;
253 
254  /* Un-truncate current token so errors point to third token */
255  *(yyextra->lookahead_end) = yyextra->lookahead_hold_char;
256 
257  /* Get third token */
258  next_token = core_yylex(&(yyextra->lookahead_yylval),
259  llocp, yyscanner);
260 
261  /* If we throw error here, it will point to third token */
262  if (next_token != SCONST)
263  scanner_yyerror("UESCAPE must be followed by a simple string literal",
264  yyscanner);
265 
266  escstr = yyextra->lookahead_yylval.str;
267  if (strlen(escstr) != 1 || !check_uescapechar(escstr[0]))
268  scanner_yyerror("invalid Unicode escape character",
269  yyscanner);
270 
271  /* Now restore *llocp; errors will point to first token */
272  *llocp = cur_yylloc;
273 
274  /* Apply Unicode conversion */
275  lvalp->core_yystype.str =
276  str_udeescape(lvalp->core_yystype.str,
277  escstr[0],
278  *llocp,
279  yyscanner);
280 
281  /*
282  * We don't need to revert the un-truncation of UESCAPE. What
283  * we do want to do is clear have_lookahead, thereby consuming
284  * all three tokens.
285  */
286  yyextra->have_lookahead = false;
287  }
288  else
289  {
290  /* No UESCAPE, so convert using default escape character */
291  lvalp->core_yystype.str =
292  str_udeescape(lvalp->core_yystype.str,
293  '\\',
294  *llocp,
295  yyscanner);
296  }
297 
298  if (cur_token == UIDENT)
299  {
300  /* It's an identifier, so truncate as appropriate */
301  truncate_identifier(lvalp->core_yystype.str,
302  strlen(lvalp->core_yystype.str),
303  true);
304  cur_token = IDENT;
305  }
306  else if (cur_token == USCONST)
307  {
308  cur_token = SCONST;
309  }
310  break;
311  }
312 
313  return cur_token;
314 }
static char * str_udeescape(const char *str, char escape, int position, core_yyscan_t yyscanner)
Definition: parser.c:362
static bool check_uescapechar(unsigned char escape)
Definition: parser.c:342
#define pg_yyget_extra(yyscanner)
Definition: gramparse.h:64
static bool next_token(char **lineptr, char *buf, int bufsz, bool *initial_quote, bool *terminating_comma, int elevel, char **err_msg)
Definition: hba.c:169
Assert(fmt[strlen(fmt) - 1] !='\n')
static core_yyscan_t yyscanner
Definition: pl_scanner.c:106
#define YYLTYPE
Definition: scanner.h:44
int core_yylex(core_YYSTYPE *lvalp, YYLTYPE *llocp, core_yyscan_t yyscanner)
void scanner_yyerror(const char *message, core_yyscan_t yyscanner) pg_attribute_noreturn()
void truncate_identifier(char *ident, int len, bool warn)
Definition: scansup.c:93
YYLTYPE lookahead_yylloc
Definition: gramparse.h:48
char * lookahead_end
Definition: gramparse.h:49
core_yy_extra_type core_yy_extra
Definition: gramparse.h:40
char lookahead_hold_char
Definition: gramparse.h:50
core_YYSTYPE lookahead_yylval
Definition: gramparse.h:47
char * scanbuf
Definition: scanner.h:72
char * str
Definition: scanner.h:32

References Assert(), check_uescapechar(), base_yy_extra_type::core_yy_extra, core_yylex(), base_yy_extra_type::have_lookahead, base_yy_extra_type::lookahead_end, base_yy_extra_type::lookahead_hold_char, base_yy_extra_type::lookahead_token, base_yy_extra_type::lookahead_yylloc, base_yy_extra_type::lookahead_yylval, next_token(), pg_yyget_extra, core_yy_extra_type::scanbuf, scanner_yyerror(), core_YYSTYPE::str, str_udeescape(), truncate_identifier(), YYLTYPE, and yyscanner.

Referenced by filtered_base_yylex().

◆ 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().