OSDN Git Service

Remove no-longer-needed inclusions to improve backward compatibility
[pg-rex/syncrep.git] / src / pl / plpgsql / src / scan.l
1 %{
2 /**********************************************************************
3  * scan.l               - Scanner for the PL/pgSQL
4  *                        procedural language
5  *
6  * IDENTIFICATION
7  *    $Header: /cvsroot/pgsql/src/pl/plpgsql/src/Attic/scan.l,v 1.24 2002/11/07 06:06:17 tgl Exp $
8  *
9  *    This software is copyrighted by Jan Wieck - Hamburg.
10  *
11  *    The author hereby grants permission  to  use,  copy,  modify,
12  *    distribute,  and  license this software and its documentation
13  *    for any purpose, provided that existing copyright notices are
14  *    retained  in  all  copies  and  that  this notice is included
15  *    verbatim in any distributions. No written agreement, license,
16  *    or  royalty  fee  is required for any of the authorized uses.
17  *    Modifications to this software may be  copyrighted  by  their
18  *    author  and  need  not  follow  the licensing terms described
19  *    here, provided that the new terms are  clearly  indicated  on
20  *    the first page of each file where they apply.
21  *
22  *    IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
23  *    PARTY  FOR  DIRECT,   INDIRECT,   SPECIAL,   INCIDENTAL,   OR
24  *    CONSEQUENTIAL   DAMAGES  ARISING  OUT  OF  THE  USE  OF  THIS
25  *    SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
26  *    IF  THE  AUTHOR  HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
27  *    DAMAGE.
28  *
29  *    THE  AUTHOR  AND  DISTRIBUTORS  SPECIFICALLY   DISCLAIM   ANY
30  *    WARRANTIES,  INCLUDING,  BUT  NOT  LIMITED  TO,  THE  IMPLIED
31  *    WARRANTIES  OF  MERCHANTABILITY,  FITNESS  FOR  A  PARTICULAR
32  *    PURPOSE,  AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON
33  *    AN "AS IS" BASIS, AND THE AUTHOR  AND  DISTRIBUTORS  HAVE  NO
34  *    OBLIGATION   TO   PROVIDE   MAINTENANCE,   SUPPORT,  UPDATES,
35  *    ENHANCEMENTS, OR MODIFICATIONS.
36  *
37  **********************************************************************/
38
39 #include "plpgsql.h"
40
41
42 static char     *plpgsql_source;
43 static int      plpgsql_bytes_left;
44 static int      scanner_functype;
45 static int      scanner_typereported;
46 static int      pushback_token;
47 static bool have_pushback_token;
48 static int      lookahead_token;        
49 static bool have_lookahead_token;
50
51 int     plpgsql_SpaceScanned = 0;
52
53 static void plpgsql_input(char *buf, int *result, int max);
54
55 #define YY_INPUT(buf,res,max)   plpgsql_input(buf, &res, max)
56 %}
57
58 %option 8bit
59 %option never-interactive
60 %option nounput
61 %option noyywrap
62
63 %option yylineno
64 %option case-insensitive
65
66
67 %x      IN_STRING IN_COMMENT
68
69 digit                   [0-9]
70 letter                  [\200-\377_A-Za-z]
71 letter_or_digit [\200-\377_A-Za-z0-9]
72
73 quoted_ident    (\"[^\"]*\")+
74
75 identifier              ({letter}{letter_or_digit}*|{quoted_ident})
76
77 space                   [ \t\n\r\f]
78
79 %%
80     /* ----------
81      * Local variable in scanner to remember where
82      * a string or comment started
83      * ----------
84      */
85     int start_lineno = 0;
86
87     /* ----------
88      * Reset the state when entering the scanner
89      * ----------
90      */
91     BEGIN INITIAL;
92     plpgsql_SpaceScanned = 0;
93
94     /* ----------
95      * On the first call to a new source report the
96      * functions type (T_FUNCTION or T_TRIGGER)
97      * ----------
98      */
99         if (!scanner_typereported)
100         {
101                 scanner_typereported = 1;
102                 return scanner_functype;
103         }
104
105     /* ----------
106      * The keyword rules
107      * ----------
108      */
109 :=                              { return K_ASSIGN;                      }
110 =                               { return K_ASSIGN;                      }
111 \.\.                    { return K_DOTDOT;                      }
112 alias                   { return K_ALIAS;                       }
113 begin                   { return K_BEGIN;                       }
114 close                   { return K_CLOSE;                       }
115 constant                { return K_CONSTANT;            }
116 cursor                  { return K_CURSOR;                      }
117 debug                   { return K_DEBUG;                       }
118 declare                 { return K_DECLARE;                     }
119 default                 { return K_DEFAULT;                     }
120 diagnostics             { return K_DIAGNOSTICS;         }
121 else                    { return K_ELSE;                        }
122 elsif           { return K_ELSIF;           }
123 end                             { return K_END;                         }
124 exception               { return K_EXCEPTION;           }
125 execute                 { return K_EXECUTE;                     }
126 exit                    { return K_EXIT;                        }
127 fetch                   { return K_FETCH;                       }
128 for                             { return K_FOR;                         }
129 from                    { return K_FROM;                        }
130 get                             { return K_GET;                         }
131 if                              { return K_IF;                          }
132 in                              { return K_IN;                          }
133 info                    { return K_INFO;                        }
134 into                    { return K_INTO;                        }
135 is                              { return K_IS;                          }
136 log                             { return K_LOG;                         }
137 loop                    { return K_LOOP;                        }
138 next                    { return K_NEXT;                        }
139 not                             { return K_NOT;                         }
140 notice                  { return K_NOTICE;                      }
141 null                    { return K_NULL;                        }
142 open                    { return K_OPEN;                        }
143 perform                 { return K_PERFORM;                     }
144 raise                   { return K_RAISE;                       }
145 record                  { return K_RECORD;                      }
146 rename                  { return K_RENAME;                      }
147 result_oid              { return K_RESULT_OID;          }
148 return                  { return K_RETURN;                      }
149 reverse                 { return K_REVERSE;                     }
150 row_count               { return K_ROW_COUNT;           }
151 select                  { return K_SELECT;                      }
152 then                    { return K_THEN;                        }
153 to                              { return K_TO;                          }
154 type                    { return K_TYPE;                        }
155 warning                 { return K_WARNING;                     }
156 when                    { return K_WHEN;                        }
157 while                   { return K_WHILE;                       }
158
159 ^#option                { return O_OPTION;                      }
160 dump                    { return O_DUMP;                        }
161
162
163     /* ----------
164      * Special word rules
165      * ----------
166      */
167 {identifier}                                    { return plpgsql_parse_word(yytext);    }
168 {identifier}{space}*\.{space}*{identifier}      { return plpgsql_parse_dblword(yytext); }
169 {identifier}{space}*\.{space}*{identifier}{space}*\.{space}*{identifier}        { return plpgsql_parse_tripword(yytext); }
170 {identifier}{space}*%TYPE               { return plpgsql_parse_wordtype(yytext);        }
171 {identifier}{space}*\.{space}*{identifier}{space}*%TYPE { return plpgsql_parse_dblwordtype(yytext); }
172 {identifier}{space}*\.{space}*{identifier}{space}*\.{space}*{identifier}{space}*%TYPE   { return plpgsql_parse_tripwordtype(yytext); }
173 {identifier}{space}*%ROWTYPE    { return plpgsql_parse_wordrowtype(yytext);     }
174 {identifier}{space}*\.{space}*{identifier}{space}*%ROWTYPE      { return plpgsql_parse_dblwordrowtype(yytext);  }
175
176 \${digit}+                                              { return plpgsql_parse_word(yytext);    }
177 \${digit}+{space}*\.{space}*{identifier}        { return plpgsql_parse_dblword(yytext); }
178 \${digit}+{space}*\.{space}*{identifier}{space}*\.{space}*{identifier}  { return plpgsql_parse_tripword(yytext); }
179 \${digit}+{space}*%TYPE                 { return plpgsql_parse_wordtype(yytext);        }
180 \${digit}+{space}*\.{space}*{identifier}{space}*%TYPE   { return plpgsql_parse_dblwordtype(yytext); }
181 \${digit}+{space}*\.{space}*{identifier}{space}*\.{space}*{identifier}{space}*%TYPE     { return plpgsql_parse_tripwordtype(yytext); }
182 \${digit}+{space}*%ROWTYPE              { return plpgsql_parse_wordrowtype(yytext);     }
183 \${digit}+{space}*\.{space}*{identifier}{space}*%ROWTYPE        { return plpgsql_parse_dblwordrowtype(yytext);  }
184
185 {digit}+                { return T_NUMBER;                      }
186
187 \".                             {
188                                 plpgsql_error_lineno = yylineno;
189                                 elog(ERROR, "unterminated quoted identifier");
190                         }
191
192     /* ----------
193      * Ignore whitespaces but remember this happened
194      * ----------
195      */
196 {space}+                { plpgsql_SpaceScanned = 1;             }
197
198     /* ----------
199      * Eat up comments
200      * ----------
201      */
202 --[^\r\n]*              ;
203
204 \/\*                    { start_lineno = yylineno;
205                           BEGIN IN_COMMENT;
206                         }
207 <IN_COMMENT>\*\/        { BEGIN INITIAL; plpgsql_SpaceScanned = 1; }
208 <IN_COMMENT>\n          ;
209 <IN_COMMENT>.           ;
210 <IN_COMMENT><<EOF>>     {
211                                 plpgsql_error_lineno = start_lineno;
212                                 elog(ERROR, "unterminated comment");
213                         }
214
215     /* ----------
216      * Collect anything inside of ''s and return one STRING
217      * ----------
218      */
219 '                       { start_lineno = yylineno;
220                           BEGIN IN_STRING;
221                           yymore();
222                         }
223 <IN_STRING>\\.          |
224 <IN_STRING>''           { yymore();                             }
225 <IN_STRING>'            { BEGIN INITIAL;
226                           return T_STRING;
227                         }
228 <IN_STRING><<EOF>>      {
229                                 plpgsql_error_lineno = start_lineno;
230                                 elog(ERROR, "unterminated string");
231                         }
232 <IN_STRING>[^'\\]*      { yymore();                             }
233
234     /* ----------
235      * Any unmatched character is returned as is
236      * ----------
237      */
238 .                       { return yytext[0];                     }
239
240 %%
241
242
243 static void
244 plpgsql_input(char *buf, int *result, int max)
245 {
246     int         n = max;
247
248     if (n > plpgsql_bytes_left)
249         n = plpgsql_bytes_left;
250
251     if (n == 0)
252         {
253         *result = YY_NULL;
254                 return;
255     }
256
257     *result = n;
258     memcpy(buf, plpgsql_source, n);
259     plpgsql_source += n;
260     plpgsql_bytes_left -= n;
261 }
262
263 /*
264  * This is the yylex routine called from outside. It exists to provide
265  * a pushback facility, as well as to allow us to parse syntax that
266  * requires more than one token of lookahead.
267  */
268 int
269 plpgsql_yylex(void)
270 {
271         int cur_token;
272
273         if (have_pushback_token)
274         {
275                 have_pushback_token = false;
276                 cur_token = pushback_token;
277         }
278         else if (have_lookahead_token)
279         {
280                 have_lookahead_token = false;
281                 cur_token = lookahead_token;
282         }
283         else
284                 cur_token = yylex();
285
286         /* Do we need to look ahead for a possible multiword token? */
287         switch (cur_token)
288         {
289                 /* RETURN NEXT must be reduced to a single token */
290                 case K_RETURN:
291                         if (!have_lookahead_token)
292                         {
293                                 lookahead_token = yylex();
294                                 have_lookahead_token = true;
295                         }
296                         if (lookahead_token == K_NEXT)
297                         {
298                                 have_lookahead_token = false;
299                                 cur_token = K_RETURN_NEXT;
300                         }
301                         break;
302
303                 default:
304                         break;
305         }
306
307         return cur_token;
308 }
309
310 /*
311  * Push back a single token to be re-read by next plpgsql_yylex() call.
312  */
313 void
314 plpgsql_push_back_token(int token)
315 {
316         if (have_pushback_token)
317                 elog(ERROR, "plpgsql_push_back_token: can't push back multiple tokens");
318         pushback_token = token;
319         have_pushback_token = true;
320 }
321
322
323 /*
324  * Initialize the scanner for new input.
325  */
326 void
327 plpgsql_setinput(char *source, int functype)
328 {
329     yyrestart(NULL);
330     yylineno = 1;
331
332     plpgsql_source = source;
333
334         /*----------
335          * Hack: skip any initial newline, so that in the common coding layout
336          *              CREATE FUNCTION ... AS '
337          *                      code body
338          *              ' LANGUAGE 'plpgsql';
339          * we will think "line 1" is what the programmer thinks of as line 1.
340          *----------
341          */
342     if (*plpgsql_source == '\r')
343         plpgsql_source++;
344     if (*plpgsql_source == '\n')
345         plpgsql_source++;
346
347     plpgsql_bytes_left = strlen(plpgsql_source);
348
349     scanner_functype     = functype;
350     scanner_typereported = 0;
351
352         have_pushback_token = false;
353         have_lookahead_token = false;
354 }