LCOV - code coverage report
Current view: top level - src/interfaces/ecpg/preproc - parser.c (source / functions) Hit Total Coverage
Test: PostgreSQL 12beta2 Lines: 44 46 95.7 %
Date: 2019-06-18 07:06:57 Functions: 1 1 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * parser.c
       4             :  *      Main entry point/driver for PostgreSQL grammar
       5             :  *
       6             :  * This should match src/backend/parser/parser.c, except that we do not
       7             :  * need to bother with re-entrant interfaces.
       8             :  *
       9             :  *
      10             :  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
      11             :  * Portions Copyright (c) 1994, Regents of the University of California
      12             :  *
      13             :  * IDENTIFICATION
      14             :  *    src/interfaces/ecpg/preproc/parser.c
      15             :  *
      16             :  *-------------------------------------------------------------------------
      17             :  */
      18             : 
      19             : #include "postgres_fe.h"
      20             : 
      21             : #include "preproc_extern.h"
      22             : #include "preproc.h"
      23             : 
      24             : 
      25             : static bool have_lookahead;     /* is lookahead info valid? */
      26             : static int  lookahead_token;    /* one-token lookahead */
      27             : static YYSTYPE lookahead_yylval;    /* yylval for lookahead token */
      28             : static YYLTYPE lookahead_yylloc;    /* yylloc for lookahead token */
      29             : static char *lookahead_yytext;  /* start current token */
      30             : static char *lookahead_end;     /* end of current token */
      31             : static char lookahead_hold_char;    /* to be put back at *lookahead_end */
      32             : 
      33             : 
      34             : /*
      35             :  * Intermediate filter between parser and base lexer (base_yylex in scan.l).
      36             :  *
      37             :  * This filter is needed because in some cases the standard SQL grammar
      38             :  * requires more than one token lookahead.  We reduce these cases to one-token
      39             :  * lookahead by replacing tokens here, in order to keep the grammar LALR(1).
      40             :  *
      41             :  * Using a filter is simpler than trying to recognize multiword tokens
      42             :  * directly in scan.l, because we'd have to allow for comments between the
      43             :  * words.  Furthermore it's not clear how to do that without re-introducing
      44             :  * scanner backtrack, which would cost more performance than this filter
      45             :  * layer does.
      46             :  */
      47             : int
      48       67632 : filtered_base_yylex(void)
      49             : {
      50             :     int         cur_token;
      51             :     int         next_token;
      52             :     int         cur_token_length;
      53             :     YYSTYPE     cur_yylval;
      54             :     YYLTYPE     cur_yylloc;
      55             :     char       *cur_yytext;
      56             : 
      57             :     /* Get next token --- we might already have it */
      58       67632 :     if (have_lookahead)
      59             :     {
      60          82 :         cur_token = lookahead_token;
      61          82 :         base_yylval = lookahead_yylval;
      62          82 :         base_yylloc = lookahead_yylloc;
      63          82 :         base_yytext = lookahead_yytext;
      64          82 :         *lookahead_end = lookahead_hold_char;
      65          82 :         have_lookahead = false;
      66             :     }
      67             :     else
      68       67550 :         cur_token = base_yylex();
      69             : 
      70             :     /*
      71             :      * If this token isn't one that requires lookahead, just return it.  If it
      72             :      * does, determine the token length.  (We could get that via strlen(), but
      73             :      * since we have such a small set of possibilities, hardwiring seems
      74             :      * feasible and more efficient.)
      75             :      */
      76       67632 :     switch (cur_token)
      77             :     {
      78             :         case NOT:
      79          72 :             cur_token_length = 3;
      80          72 :             break;
      81             :         case NULLS_P:
      82           4 :             cur_token_length = 5;
      83           4 :             break;
      84             :         case WITH:
      85           6 :             cur_token_length = 4;
      86           6 :             break;
      87             :         default:
      88       67550 :             return cur_token;
      89             :     }
      90             : 
      91             :     /*
      92             :      * Identify end+1 of current token.  base_yylex() has temporarily stored a
      93             :      * '\0' here, and will undo that when we call it again.  We need to redo
      94             :      * it to fully revert the lookahead call for error reporting purposes.
      95             :      */
      96          82 :     lookahead_end = base_yytext + cur_token_length;
      97             :     Assert(*lookahead_end == '\0');
      98             : 
      99             :     /* Save and restore lexer output variables around the call */
     100          82 :     cur_yylval = base_yylval;
     101          82 :     cur_yylloc = base_yylloc;
     102          82 :     cur_yytext = base_yytext;
     103             : 
     104             :     /* Get next token, saving outputs into lookahead variables */
     105          82 :     next_token = base_yylex();
     106             : 
     107          82 :     lookahead_token = next_token;
     108          82 :     lookahead_yylval = base_yylval;
     109          82 :     lookahead_yylloc = base_yylloc;
     110          82 :     lookahead_yytext = base_yytext;
     111             : 
     112          82 :     base_yylval = cur_yylval;
     113          82 :     base_yylloc = cur_yylloc;
     114          82 :     base_yytext = cur_yytext;
     115             : 
     116             :     /* Now revert the un-truncation of the current token */
     117          82 :     lookahead_hold_char = *lookahead_end;
     118          82 :     *lookahead_end = '\0';
     119             : 
     120          82 :     have_lookahead = true;
     121             : 
     122             :     /* Replace cur_token if needed, based on lookahead */
     123          82 :     switch (cur_token)
     124             :     {
     125             :         case NOT:
     126             :             /* Replace NOT by NOT_LA if it's followed by BETWEEN, IN, etc */
     127          72 :             switch (next_token)
     128             :             {
     129             :                 case BETWEEN:
     130             :                 case IN_P:
     131             :                 case LIKE:
     132             :                 case ILIKE:
     133             :                 case SIMILAR:
     134           0 :                     cur_token = NOT_LA;
     135           0 :                     break;
     136             :             }
     137          72 :             break;
     138             : 
     139             :         case NULLS_P:
     140             :             /* Replace NULLS_P by NULLS_LA if it's followed by FIRST or LAST */
     141           4 :             switch (next_token)
     142             :             {
     143             :                 case FIRST_P:
     144             :                 case LAST_P:
     145           4 :                     cur_token = NULLS_LA;
     146           4 :                     break;
     147             :             }
     148           4 :             break;
     149             : 
     150             :         case WITH:
     151             :             /* Replace WITH by WITH_LA if it's followed by TIME or ORDINALITY */
     152           6 :             switch (next_token)
     153             :             {
     154             :                 case TIME:
     155             :                 case ORDINALITY:
     156           2 :                     cur_token = WITH_LA;
     157           2 :                     break;
     158             :             }
     159           6 :             break;
     160             :     }
     161             : 
     162          82 :     return cur_token;
     163             : }

Generated by: LCOV version 1.13