/* * Peek one token ahead in the input stream. Only the token code is * made available, not any of the auxiliary info such as location. * * NB: no variable or unreserved keyword lookup is performed here, they will * be returned as IDENT. Reserved keywords are resolved as usual. */ int plpgsql_peek(void) { int tok1; TokenAuxData aux1; tok1 = internal_yylex(&aux1); push_back_token(tok1, &aux1); return tok1; }
/* * Peek two tokens ahead in the input stream. The first token and its * location in the query are returned in *tok1_p and *tok1_loc, second token * and its location in *tok2_p and *tok2_loc. * * NB: no variable or unreserved keyword lookup is performed here, they will * be returned as IDENT. Reserved keywords are resolved as usual. */ void plpgsql_peek2(int *tok1_p, int *tok2_p, int *tok1_loc, int *tok2_loc) { int tok1, tok2; TokenAuxData aux1, aux2; tok1 = internal_yylex(&aux1); tok2 = internal_yylex(&aux2); *tok1_p = tok1; if (tok1_loc) *tok1_loc = aux1.lloc; *tok2_p = tok2; if (tok2_loc) *tok2_loc = aux2.lloc; push_back_token(tok2, &aux2); push_back_token(tok1, &aux1); }
/* * This is the yylex routine called from the PL/pgSQL grammar. * It is a wrapper around the core lexer, with the ability to recognize * PL/pgSQL variables and return them as special T_DATUM tokens. If a * word or compound word does not match any variable name, or if matching * is turned off by plpgsql_IdentifierLookup, it is returned as * T_WORD or T_CWORD respectively, or as an unreserved keyword if it * matches one of those. */ int plpgsql_yylex(void) { int tok1; TokenAuxData aux1; const ScanKeyword *kw; tok1 = internal_yylex(&aux1); if (tok1 == IDENT || tok1 == PARAM) { int tok2; TokenAuxData aux2; tok2 = internal_yylex(&aux2); if (tok2 == '.') { int tok3; TokenAuxData aux3; tok3 = internal_yylex(&aux3); if (tok3 == IDENT) { int tok4; TokenAuxData aux4; tok4 = internal_yylex(&aux4); if (tok4 == '.') { int tok5; TokenAuxData aux5; tok5 = internal_yylex(&aux5); if (tok5 == IDENT) { if (plpgsql_parse_tripword(aux1.lval.str, aux3.lval.str, aux5.lval.str, &aux1.lval.wdatum, &aux1.lval.cword)) tok1 = T_DATUM; else tok1 = T_CWORD; } else { /* not A.B.C, so just process A.B */ push_back_token(tok5, &aux5); push_back_token(tok4, &aux4); if (plpgsql_parse_dblword(aux1.lval.str, aux3.lval.str, &aux1.lval.wdatum, &aux1.lval.cword)) tok1 = T_DATUM; else tok1 = T_CWORD; } } else { /* not A.B.C, so just process A.B */ push_back_token(tok4, &aux4); if (plpgsql_parse_dblword(aux1.lval.str, aux3.lval.str, &aux1.lval.wdatum, &aux1.lval.cword)) tok1 = T_DATUM; else tok1 = T_CWORD; } } else { /* not A.B, so just process A */ push_back_token(tok3, &aux3); push_back_token(tok2, &aux2); if (plpgsql_parse_word(aux1.lval.str, core_yy.scanbuf + aux1.lloc, &aux1.lval.wdatum, &aux1.lval.word)) tok1 = T_DATUM; else if (!aux1.lval.word.quoted && (kw = ScanKeywordLookup(aux1.lval.word.ident, unreserved_keywords, num_unreserved_keywords))) { aux1.lval.keyword = kw->name; tok1 = kw->value; } else tok1 = T_WORD; } } else { /* not A.B, so just process A */ push_back_token(tok2, &aux2); /* * If we are at start of statement, prefer unreserved keywords * over variable names, unless the next token is assignment or * '[', in which case prefer variable names. (Note we need not * consider '.' as the next token; that case was handled above, * and we always prefer variable names in that case.) If we are * not at start of statement, always prefer variable names over * unreserved keywords. */ if (AT_STMT_START(plpgsql_yytoken) && !(tok2 == '=' || tok2 == COLON_EQUALS || tok2 == '[')) { /* try for unreserved keyword, then for variable name */ if (core_yy.scanbuf[aux1.lloc] != '"' && (kw = ScanKeywordLookup(aux1.lval.str, unreserved_keywords, num_unreserved_keywords))) { aux1.lval.keyword = kw->name; tok1 = kw->value; } else if (plpgsql_parse_word(aux1.lval.str, core_yy.scanbuf + aux1.lloc, &aux1.lval.wdatum, &aux1.lval.word)) tok1 = T_DATUM; else tok1 = T_WORD; } else { /* try for variable name, then for unreserved keyword */ if (plpgsql_parse_word(aux1.lval.str, core_yy.scanbuf + aux1.lloc, &aux1.lval.wdatum, &aux1.lval.word)) tok1 = T_DATUM; else if (!aux1.lval.word.quoted && (kw = ScanKeywordLookup(aux1.lval.word.ident, unreserved_keywords, num_unreserved_keywords))) { aux1.lval.keyword = kw->name; tok1 = kw->value; } else tok1 = T_WORD; } } } else { /* * Not a potential plpgsql variable name, just return the data. * * Note that we also come through here if the grammar pushed back a * T_DATUM, T_CWORD, T_WORD, or unreserved-keyword token returned by a * previous lookup cycle; thus, pushbacks do not incur extra lookup * work, since we'll never do the above code twice for the same token. * This property also makes it safe to rely on the old value of * plpgsql_yytoken in the is-this-start-of-statement test above. */ } plpgsql_yylval = aux1.lval; plpgsql_yylloc = aux1.lloc; plpgsql_yyleng = aux1.leng; plpgsql_yytoken = tok1; return tok1; }
/* * This is the yylex routine called from the PL/pgSQL grammar. * It is a wrapper around the core lexer, with the ability to recognize * PL/pgSQL variables and return them as special T_DATUM tokens. If a * word or compound word does not match any variable name, or if matching * is turned off by plpgsql_IdentifierLookup, it is returned as * T_WORD or T_CWORD respectively, or as an unreserved keyword if it * matches one of those. */ int plpgsql_yylex(void) { int tok1; TokenAuxData aux1; const ScanKeyword *kw; tok1 = internal_yylex(&aux1); if (tok1 == IDENT || tok1 == PARAM) { int tok2; TokenAuxData aux2; tok2 = internal_yylex(&aux2); if (tok2 == '.') { int tok3; TokenAuxData aux3; tok3 = internal_yylex(&aux3); if (tok3 == IDENT) { int tok4; TokenAuxData aux4; tok4 = internal_yylex(&aux4); if (tok4 == '.') { int tok5; TokenAuxData aux5; tok5 = internal_yylex(&aux5); if (tok5 == IDENT) { if (plpgsql_parse_tripword(aux1.lval.str, aux3.lval.str, aux5.lval.str, &aux1.lval.wdatum, &aux1.lval.cword)) tok1 = T_DATUM; else tok1 = T_CWORD; } else { /* not A.B.C, so just process A.B */ push_back_token(tok5, &aux5); push_back_token(tok4, &aux4); if (plpgsql_parse_dblword(aux1.lval.str, aux3.lval.str, &aux1.lval.wdatum, &aux1.lval.cword)) tok1 = T_DATUM; else tok1 = T_CWORD; } } else { /* not A.B.C, so just process A.B */ push_back_token(tok4, &aux4); if (plpgsql_parse_dblword(aux1.lval.str, aux3.lval.str, &aux1.lval.wdatum, &aux1.lval.cword)) tok1 = T_DATUM; else tok1 = T_CWORD; } } else { /* not A.B, so just process A */ push_back_token(tok3, &aux3); push_back_token(tok2, &aux2); if (plpgsql_parse_word(aux1.lval.str, core_yy.scanbuf + aux1.lloc, &aux1.lval.wdatum, &aux1.lval.word)) tok1 = T_DATUM; else if (!aux1.lval.word.quoted && (kw = ScanKeywordLookup(aux1.lval.word.ident, unreserved_keywords, num_unreserved_keywords))) { aux1.lval.keyword = kw->name; tok1 = kw->value; } else tok1 = T_WORD; } } else { /* not A.B, so just process A */ push_back_token(tok2, &aux2); if (plpgsql_parse_word(aux1.lval.str, core_yy.scanbuf + aux1.lloc, &aux1.lval.wdatum, &aux1.lval.word)) tok1 = T_DATUM; else if (!aux1.lval.word.quoted && (kw = ScanKeywordLookup(aux1.lval.word.ident, unreserved_keywords, num_unreserved_keywords))) { aux1.lval.keyword = kw->name; tok1 = kw->value; } else tok1 = T_WORD; } } else { /* Not a potential plpgsql variable name, just return the data */ } plpgsql_yylval = aux1.lval; plpgsql_yylloc = aux1.lloc; plpgsql_yyleng = aux1.leng; return tok1; }