]> granicus.if.org Git - postgresql/blob - src/backend/parser/scan.l
Allow parsing expressions with ") -" (scan.l, scan.c only).
[postgresql] / src / backend / parser / scan.l
1 %{
2 /*-------------------------------------------------------------------------
3  *
4  * scan.l--
5  *        lexical scanner for POSTGRES
6  *
7  * Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $Header: /cvsroot/pgsql/src/backend/parser/scan.l,v 1.37 1998/03/18 16:50:25 thomas Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include <ctype.h>
16 #include <unistd.h>
17 #ifndef __linux__
18 #include <math.h>
19 #else
20 #include <stdlib.h>
21 #endif /* __linux__ */
22 #include <string.h>
23 #include <errno.h>
24
25 #include "postgres.h"
26 #include "miscadmin.h"
27 #include "nodes/pg_list.h"
28 #include "nodes/parsenodes.h"
29 #include "parser/gramparse.h"
30 #include "parser/keywords.h"
31 #include "parser/scansup.h"
32 #include "parse.h"
33 #include "utils/builtins.h"
34
35 extern char *parseString;
36 static char *parseCh;
37
38 /* some versions of lex define this as a macro */
39 #if defined(yywrap)
40 #undef yywrap
41 #endif /* yywrap */
42
43 #if defined(FLEX_SCANNER)
44 /* MAX_PARSE_BUFFER is defined in miscadmin.h */
45 #define YYLMAX MAX_PARSE_BUFFER
46 #define YY_NO_UNPUT
47 extern int myinput(char* buf, int max);
48 #undef YY_INPUT
49 #define YY_INPUT(buf,result,max) {result = myinput(buf,max);}
50 #else
51 #undef input
52 int input();
53 #undef unput
54 void unput(char);
55 #endif /* FLEX_SCANNER */
56
57 extern YYSTYPE yylval;
58
59 int llen;
60 char literal[MAX_PARSE_BUFFER];
61
62 %}
63 /* OK, here is a short description of lex/flex rules behavior.
64  * The longest pattern which matches an input string is always chosen.
65  * For equal-length patterns, the first occurring in the rules list is chosen.
66  * INITIAL is the starting condition, to which all non-conditional rules apply.
67  * When in an exclusive condition, only those rules defined for that condition apply.
68  *
69  * Exclusive states change parsing rules while the state is active.
70  * There are exclusive states for quoted strings, extended comments,
71  *  and to eliminate parsing troubles for numeric strings.
72  * Exclusive states:
73  *  <xb> binary numeric string - thomas 1997-11-16
74  *  <xc> extended C-style comments - tgl 1997-07-12
75  *  <xd> delimited identifiers (double-quoted identifiers) - tgl 1997-10-27
76  *  <xh> hexadecimal numeric string - thomas 1997-11-16
77  *  <xm> numeric strings with embedded minus sign - tgl 1997-09-05
78  *  <xq> quoted strings - tgl 1997-07-30
79  *
80  * The "extended comment" syntax closely resembles allowable operator syntax.
81  * So, when in condition <xc>, only strings which would terminate the
82  *  "extended comment" trigger any action other than "ignore".
83  * Be sure to match _any_ candidate comment, including those with appended
84  *      operator-like symbols. - thomas 1997-07-14
85  */
86
87 %x xb
88 %x xc
89 %x xd
90 %x xh
91 %x xm
92 %x xq
93
94 /* Binary number
95  */
96 xbstart                 [bB]{quote}
97 xbstop                  {quote}
98 xbinside                [^']*
99 xbcat                   {quote}{space}*\n{space}*{quote}
100
101 /* Hexadecimal number
102  */
103 xhstart                 [xX]{quote}
104 xhstop                  {quote}
105 xhinside                [^']*
106 xhcat                   {quote}{space}*\n{space}*{quote}
107
108 /* Extended quote
109  * xqdouble implements SQL92 embedded quote
110  * xqcat allows strings to cross input lines
111  */
112 quote                   '
113 xqstart                 {quote}
114 xqstop                  {quote}
115 xqdouble                {quote}{quote}
116 xqinside                [^\\']*
117 xqembedded              "\\'"
118 xqliteral               [\\](.|\n)
119 xqcat                   {quote}{space}*\n{space}*{quote}
120
121 /* Delimited quote
122  * Allows embedded spaces and other special characters into identifiers.
123  */
124 dquote                  \"
125 xdstart                 {dquote}
126 xdstop                  {dquote}
127 xdinside                [^"]*
128
129 /* Comments
130  * Ignored by the scanner and parser.
131  */
132 xcline                  [\/][\*].*[\*][\/]{space}*\n*
133 xcstart                 [\/][\*]{op_and_self}*
134 xcstop                  {op_and_self}*[\*][\/]({space}*|\n)
135 xcinside                [^*]*
136 xcstar                  [^/]
137
138 digit                   [0-9]
139 number                  [-+.0-9Ee]
140 letter                  [\200-\377_A-Za-z]
141 letter_or_digit [\200-\377_A-Za-z0-9]
142
143 identifier              {letter}{letter_or_digit}*
144
145 typecast                "::"
146
147 self                    [,()\[\].;$\:\+\-\*\/\<\>\=\|]
148 op_and_self             [\~\!\@\#\%\^\&\|\`\?\$\:\+\-\*\/\<\>\=]
149 operator                {op_and_self}+
150
151 xmstop                  -
152
153 integer                 [\-]?{digit}+
154 real                    [\-]?{digit}+\.{digit}+([Ee][-+]?{digit}+)?
155
156 param                   \${integer}
157
158 comment                 ("--"|"//").*\n
159
160 space                   [ \t\n\f]
161 other                   .
162
163 /* DO NOT PUT ANY COMMENTS IN THE FOLLOWING SECTION.
164  * AT&T lex does not properly handle C-style comments in this second lex block.
165  * So, put comments here. tgl - 1997-09-08
166  *
167  * Quoted strings must allow some special characters such as single-quote
168  *  and newline.
169  * Embedded single-quotes are implemented both in the SQL/92-standard
170  *  style of two adjacent single quotes "''" and in the Postgres/Java style
171  *  of escaped-quote "\'".
172  * Other embedded escaped characters are matched explicitly and the leading
173  *  backslash is dropped from the string. - thomas 1997-09-24
174  */
175
176 %%
177 {comment}               { /* ignore */ }
178
179 {xcline}                { /* ignore */ }
180
181 <xc>{xcstar}    |
182 {xcstart}               { BEGIN(xc); }
183
184 <xc>{xcstop}    { BEGIN(INITIAL); }
185
186 <xc>{xcinside}  { /* ignore */ }
187
188 {xbstart}               {
189                                         BEGIN(xb);
190                                         llen = 0;
191                                         *literal = '\0';
192                                 }
193 <xb>{xbstop}    {
194                                         char* endptr;
195
196                                         BEGIN(INITIAL);
197                                         errno = 0;
198                                         yylval.ival = strtol((char *)literal,&endptr,2);
199                                         if (*endptr != '\0' || errno == ERANGE)
200                                                 elog(ERROR,"Bad binary integer input '%s'",literal);
201                                         return (ICONST);
202                                 }
203 <xh>{xhinside}  |
204 <xb>{xbinside}  {
205                                         if ((llen+yyleng) > (MAX_PARSE_BUFFER - 1))
206                                                 elog(ERROR,"quoted string parse buffer of %d chars exceeded",MAX_PARSE_BUFFER);
207                                         memcpy(literal+llen, yytext, yyleng+1);
208                                         llen += yyleng;
209                                 }
210 <xh>{xhcat}             |
211 <xb>{xbcat}             {
212                                 }
213
214 {xhstart}               {
215                                         BEGIN(xh);
216                                         llen = 0;
217                                         *literal = '\0';
218                                 }
219 <xh>{xhstop}    {
220                                         char* endptr;
221
222                                         BEGIN(INITIAL);
223                                         errno = 0;
224                                         yylval.ival = strtol((char *)literal,&endptr,16);
225                                         if (*endptr != '\0' || errno == ERANGE)
226                                                 elog(ERROR,"Bad hexadecimal integer input '%s'",literal);
227                                         return (ICONST);
228                                 }
229
230 {xqstart}               {
231                                         BEGIN(xq);
232                                         llen = 0;
233                                         *literal = '\0';
234                                 }
235 <xq>{xqstop}    {
236                                         BEGIN(INITIAL);
237                                         yylval.str = pstrdup(scanstr(literal));
238                                         return (SCONST);
239                                 }
240 <xq>{xqdouble}  |
241 <xq>{xqinside}  {
242                                         if ((llen+yyleng) > (MAX_PARSE_BUFFER - 1))
243                                                 elog(ERROR,"quoted string parse buffer of %d chars exceeded",MAX_PARSE_BUFFER);
244                                         memcpy(literal+llen, yytext, yyleng+1);
245                                         llen += yyleng;
246                                 }
247 <xq>{xqembedded} {
248                                         if ((llen+yyleng-1) > (MAX_PARSE_BUFFER - 1))
249                                                 elog(ERROR,"quoted string parse buffer of %d chars exceeded",MAX_PARSE_BUFFER);
250                                         memcpy(literal+llen, yytext, yyleng+1);
251                                         *(literal+llen) = '\'';
252                                         llen += yyleng;
253                                 }
254
255 <xq>{xqliteral} {
256                                         if ((llen+yyleng-1) > (MAX_PARSE_BUFFER - 1))
257                                                 elog(ERROR,"quoted string parse buffer of %d chars exceeded",MAX_PARSE_BUFFER);
258                                         memcpy(literal+llen, yytext, yyleng+1);
259                                         llen += yyleng;
260                                 }
261 <xq>{xqcat}             {
262                                 }
263
264
265 {xdstart}               {
266                                         BEGIN(xd);
267                                         llen = 0;
268                                         *literal = '\0';
269                                 }
270 <xd>{xdstop}    {
271                                         BEGIN(INITIAL);
272                                         yylval.str = pstrdup(literal);
273                                         return (IDENT);
274                                 }
275 <xd>{xdinside}  {
276                                         if ((llen+yyleng) > (MAX_PARSE_BUFFER - 1))
277                                                 elog(ERROR,"quoted string parse buffer of %d chars exceeded",MAX_PARSE_BUFFER);
278                                         memcpy(literal+llen, yytext, yyleng+1);
279                                         llen += yyleng;
280                                 }
281
282
283 <xm>{space}*    { /* ignore */ }
284 <xm>{xmstop}    {
285                                         BEGIN(INITIAL);
286                                         return (yytext[0]);
287                                 }
288
289
290 {typecast}              { return TYPECAST; }
291
292 {self}/{space}*-[\.0-9] {
293                                         BEGIN(xm);
294                                         return (yytext[0]);
295                                 }
296 {self}                  {       return (yytext[0]); }
297 {operator}/-[\.0-9]     {
298                                         yylval.str = pstrdup((char*)yytext);
299                                         return (Op);
300                                 }
301 {operator}              {
302                                         if (strcmp((char*)yytext,"!=") == 0)
303                                                 yylval.str = pstrdup("<>"); /* compatability */
304                                         else
305                                                 yylval.str = pstrdup((char*)yytext);
306                                         return (Op);
307                                 }
308 {param}                 {
309                                         yylval.ival = atoi((char*)&yytext[1]);
310                                         return (PARAM);
311                                 }
312
313
314 {identifier}/{space}*-{number}  {
315                                         int i;
316                                         ScanKeyword             *keyword;
317
318                                         BEGIN(xm);
319                                         for(i = 0; yytext[i]; i++)
320                                                 if (isupper(yytext[i]))
321                                                         yytext[i] = tolower(yytext[i]);
322
323                                         keyword = ScanKeywordLookup((char*)yytext);
324                                         if (keyword != NULL) {
325                                                 return (keyword->value);
326                                         }
327                                         else
328                                         {
329                                                 yylval.str = pstrdup((char*)yytext);
330                                                 return (IDENT);
331                                         }
332                                 }
333 {integer}/{space}*-{number}     {
334                                         char* endptr;
335
336                                         BEGIN(xm);
337                                         errno = 0;
338                                         yylval.ival = strtol((char *)yytext,&endptr,10);
339                                         if (*endptr != '\0' || errno == ERANGE)
340                                         {
341                                                 errno = 0;
342                                                 yylval.dval = strtod(((char *)yytext),&endptr);
343                                                 if (*endptr != '\0' || errno == ERANGE)
344                                                         elog(ERROR,"Bad integer input '%s'",yytext);
345                                                 CheckFloat8Val(yylval.dval);
346                                                 elog(NOTICE,"Integer input '%s' is out of range; promoted to float", yytext);
347                                                 return (FCONST);
348                                         }
349                                         return (ICONST);
350                                 }
351 {real}/{space}*-{number} {
352                                         char* endptr;
353
354                                         BEGIN(xm);
355                                         errno = 0;
356                                         yylval.dval = strtod(((char *)yytext),&endptr);
357                                         if (*endptr != '\0' || errno == ERANGE)
358                                                 elog(ERROR,"Bad float8 input '%s'",yytext);
359                                         CheckFloat8Val(yylval.dval);
360                                         return (FCONST);
361                                 }
362 {integer}               {
363                                         char* endptr;
364
365                                         errno = 0;
366                                         yylval.ival = strtol((char *)yytext,&endptr,10);
367                                         if (*endptr != '\0' || errno == ERANGE)
368                                         {
369                                                 errno = 0;
370                                                 yylval.dval = strtod(((char *)yytext),&endptr);
371                                                 if (*endptr != '\0' || errno == ERANGE)
372                                                         elog(ERROR,"Bad integer input '%s'",yytext);
373                                                 CheckFloat8Val(yylval.dval);
374                                                 elog(NOTICE,"Integer input '%s' is out of range; promoted to float", yytext);
375                                                 return (FCONST);
376                                         }
377                                         return (ICONST);
378                                 }
379 {real}                  {
380                                         char* endptr;
381
382                                         errno = 0;
383                                         yylval.dval = strtod((char *)yytext,&endptr);
384                                         if (*endptr != '\0' || errno == ERANGE)
385                                                 elog(ERROR,"Bad float input '%s'",yytext);
386                                         CheckFloat8Val(yylval.dval);
387                                         return (FCONST);
388                                 }
389
390
391 {identifier}    {
392                                         int i;
393                                         ScanKeyword             *keyword;
394
395                                         for(i = 0; yytext[i]; i++)
396                                                 if (isupper(yytext[i]))
397                                                         yytext[i] = tolower(yytext[i]);
398
399                                         keyword = ScanKeywordLookup((char*)yytext);
400                                         if (keyword != NULL) {
401                                                 return (keyword->value);
402                                         }
403                                         else
404                                         {
405                                                 yylval.str = pstrdup((char*)yytext);
406                                                 return (IDENT);
407                                         }
408                                 }
409 {space}                 { /* ignore */ }
410
411 {other}                 { return (yytext[0]); }
412
413 %%
414
415 void yyerror(char message[])
416 {
417         elog(ERROR, "parser: %s at or near \"%s\"", message, yytext);
418 }
419
420 int yywrap()
421 {
422         return(1);
423 }
424
425 /*
426  init_io:
427         called by postgres before any actual parsing is done
428 */
429 void
430 init_io()
431 {
432         /* it's important to set this to NULL
433            because input()/myinput() checks the non-nullness of parseCh
434            to know when to pass the string to lex/flex */
435         parseCh = NULL;
436 #if defined(FLEX_SCANNER)
437         if (YY_CURRENT_BUFFER)
438                 yy_flush_buffer(YY_CURRENT_BUFFER);
439 #endif /* FLEX_SCANNER */
440         BEGIN INITIAL;
441 }
442
443 #if !defined(FLEX_SCANNER)
444 /* get lex input from a string instead of from stdin */
445 int
446 input()
447 {
448         if (parseCh == NULL)
449         {
450                 parseCh = parseString;
451                 return(*parseCh++);
452         }
453         else if (*parseCh == '\0')
454                 return(0);
455         else
456                 return(*parseCh++);
457 }
458
459 /* undo lex input from a string instead of from stdin */
460 void
461 unput(char c)
462 {
463         if (parseCh == NULL)
464                 elog(FATAL, "Unput() failed.\n");
465         else if (c != 0)
466                 *--parseCh = c;
467 }
468 #endif /* !defined(FLEX_SCANNER) */
469
470 #ifdef FLEX_SCANNER
471 /* input routine for flex to read input from a string instead of a file */
472 int
473 myinput(char* buf, int max)
474 {
475         int len, copylen;
476
477         if (parseCh == NULL)
478         {
479                 len = strlen(parseString);
480                 if (len >= max)
481                         copylen = max - 1;
482                 else
483                         copylen = len;
484                 if (copylen > 0)
485                         memcpy(buf, parseString, copylen);
486                 buf[copylen] = '\0';
487                 parseCh = parseString;
488                 return copylen;
489         }
490         else
491                 return 0; /* end of string */
492 }
493 #endif /* FLEX_SCANNER */
494