2 /*-------------------------------------------------------------------------
5 * lexical scanner for POSTGRES
7 * Copyright (c) 1994, Regents of the University of California
11 * $Header: /cvsroot/pgsql/src/backend/parser/scan.l,v 1.37 1998/03/18 16:50:25 thomas Exp $
13 *-------------------------------------------------------------------------
21 #endif /* __linux__ */
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"
33 #include "utils/builtins.h"
35 extern char *parseString;
38 /* some versions of lex define this as a macro */
43 #if defined(FLEX_SCANNER)
44 /* MAX_PARSE_BUFFER is defined in miscadmin.h */
45 #define YYLMAX MAX_PARSE_BUFFER
47 extern int myinput(char* buf, int max);
49 #define YY_INPUT(buf,result,max) {result = myinput(buf,max);}
55 #endif /* FLEX_SCANNER */
57 extern YYSTYPE yylval;
60 char literal[MAX_PARSE_BUFFER];
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.
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.
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
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
99 xbcat {quote}{space}*\n{space}*{quote}
101 /* Hexadecimal number
106 xhcat {quote}{space}*\n{space}*{quote}
109 * xqdouble implements SQL92 embedded quote
110 * xqcat allows strings to cross input lines
115 xqdouble {quote}{quote}
119 xqcat {quote}{space}*\n{space}*{quote}
122 * Allows embedded spaces and other special characters into identifiers.
130 * Ignored by the scanner and parser.
132 xcline [\/][\*].*[\*][\/]{space}*\n*
133 xcstart [\/][\*]{op_and_self}*
134 xcstop {op_and_self}*[\*][\/]({space}*|\n)
140 letter [\200-\377_A-Za-z]
141 letter_or_digit [\200-\377_A-Za-z0-9]
143 identifier {letter}{letter_or_digit}*
147 self [,()\[\].;$\:\+\-\*\/\<\>\=\|]
148 op_and_self [\~\!\@\#\%\^\&\|\`\?\$\:\+\-\*\/\<\>\=]
149 operator {op_and_self}+
153 integer [\-]?{digit}+
154 real [\-]?{digit}+\.{digit}+([Ee][-+]?{digit}+)?
158 comment ("--"|"//").*\n
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
167 * Quoted strings must allow some special characters such as single-quote
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
177 {comment} { /* ignore */ }
179 {xcline} { /* ignore */ }
182 {xcstart} { BEGIN(xc); }
184 <xc>{xcstop} { BEGIN(INITIAL); }
186 <xc>{xcinside} { /* ignore */ }
198 yylval.ival = strtol((char *)literal,&endptr,2);
199 if (*endptr != '\0' || errno == ERANGE)
200 elog(ERROR,"Bad binary integer input '%s'",literal);
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);
224 yylval.ival = strtol((char *)literal,&endptr,16);
225 if (*endptr != '\0' || errno == ERANGE)
226 elog(ERROR,"Bad hexadecimal integer input '%s'",literal);
237 yylval.str = pstrdup(scanstr(literal));
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);
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) = '\'';
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);
272 yylval.str = pstrdup(literal);
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);
283 <xm>{space}* { /* ignore */ }
290 {typecast} { return TYPECAST; }
292 {self}/{space}*-[\.0-9] {
296 {self} { return (yytext[0]); }
297 {operator}/-[\.0-9] {
298 yylval.str = pstrdup((char*)yytext);
302 if (strcmp((char*)yytext,"!=") == 0)
303 yylval.str = pstrdup("<>"); /* compatability */
305 yylval.str = pstrdup((char*)yytext);
309 yylval.ival = atoi((char*)&yytext[1]);
314 {identifier}/{space}*-{number} {
316 ScanKeyword *keyword;
319 for(i = 0; yytext[i]; i++)
320 if (isupper(yytext[i]))
321 yytext[i] = tolower(yytext[i]);
323 keyword = ScanKeywordLookup((char*)yytext);
324 if (keyword != NULL) {
325 return (keyword->value);
329 yylval.str = pstrdup((char*)yytext);
333 {integer}/{space}*-{number} {
338 yylval.ival = strtol((char *)yytext,&endptr,10);
339 if (*endptr != '\0' || errno == ERANGE)
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);
351 {real}/{space}*-{number} {
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);
366 yylval.ival = strtol((char *)yytext,&endptr,10);
367 if (*endptr != '\0' || errno == ERANGE)
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);
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);
393 ScanKeyword *keyword;
395 for(i = 0; yytext[i]; i++)
396 if (isupper(yytext[i]))
397 yytext[i] = tolower(yytext[i]);
399 keyword = ScanKeywordLookup((char*)yytext);
400 if (keyword != NULL) {
401 return (keyword->value);
405 yylval.str = pstrdup((char*)yytext);
409 {space} { /* ignore */ }
411 {other} { return (yytext[0]); }
415 void yyerror(char message[])
417 elog(ERROR, "parser: %s at or near \"%s\"", message, yytext);
427 called by postgres before any actual parsing is done
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 */
436 #if defined(FLEX_SCANNER)
437 if (YY_CURRENT_BUFFER)
438 yy_flush_buffer(YY_CURRENT_BUFFER);
439 #endif /* FLEX_SCANNER */
443 #if !defined(FLEX_SCANNER)
444 /* get lex input from a string instead of from stdin */
450 parseCh = parseString;
453 else if (*parseCh == '\0')
459 /* undo lex input from a string instead of from stdin */
464 elog(FATAL, "Unput() failed.\n");
468 #endif /* !defined(FLEX_SCANNER) */
471 /* input routine for flex to read input from a string instead of a file */
473 myinput(char* buf, int max)
479 len = strlen(parseString);
485 memcpy(buf, parseString, copylen);
487 parseCh = parseString;
491 return 0; /* end of string */
493 #endif /* FLEX_SCANNER */