mirror of
https://github.com/postgres/postgres.git
synced 2025-04-24 10:47:04 +03:00
Align ECPG lexer more closely with the core and psql lexers.
Make a bunch of basically-cosmetic changes to reduce the diffs between the flex rules in scan.l, psqlscan.l, and pgc.l. Reorder some code, adjust a lot of whitespace, sync some comments, make use of flex start condition scopes to do that. There are a few non-cosmetic changes in the ECPG lexer: * Bring over the decimalfail rule (and support function process_integer_literal) so that ECPG will lex "1..10" into the same tokens as the backend would. I'm not sure this makes any visible difference to users, but I'm not sure it doesn't, either. * <xdc><<EOF>> gets its own rule so as to produce a more on-point error message. * Remove duplicate <SQL>{xdstart} rule. John Naylor, with a few additional changes by me Discussion: https://postgr.es/m/CAJVSVGWGqY9YBs2EwtRUkbNv=hXkN8yRPOoD1wxE6COgvvrz5g@mail.gmail.com
This commit is contained in:
parent
d20dceaf50
commit
ec937d0805
@ -6,7 +6,8 @@
|
|||||||
*
|
*
|
||||||
* NOTE NOTE NOTE:
|
* NOTE NOTE NOTE:
|
||||||
*
|
*
|
||||||
* The rules in this file must be kept in sync with src/fe_utils/psqlscan.l!
|
* The rules in this file must be kept in sync with src/fe_utils/psqlscan.l
|
||||||
|
* and src/interfaces/ecpg/preproc/pgc.l!
|
||||||
*
|
*
|
||||||
* The rules are designed so that the scanner never has to backtrack,
|
* The rules are designed so that the scanner never has to backtrack,
|
||||||
* in the sense that there is always a rule that can match the input
|
* in the sense that there is always a rule that can match the input
|
||||||
@ -168,8 +169,8 @@ extern void core_yyset_column(int column_no, yyscan_t yyscanner);
|
|||||||
%x xc
|
%x xc
|
||||||
%x xd
|
%x xd
|
||||||
%x xh
|
%x xh
|
||||||
%x xe
|
|
||||||
%x xq
|
%x xq
|
||||||
|
%x xe
|
||||||
%x xdolq
|
%x xdolq
|
||||||
%x xui
|
%x xui
|
||||||
%x xuiend
|
%x xuiend
|
||||||
@ -192,7 +193,7 @@ extern void core_yyset_column(int column_no, yyscan_t yyscanner);
|
|||||||
* XXX perhaps \f (formfeed) should be treated as a newline as well?
|
* XXX perhaps \f (formfeed) should be treated as a newline as well?
|
||||||
*
|
*
|
||||||
* XXX if you change the set of whitespace characters, fix scanner_isspace()
|
* XXX if you change the set of whitespace characters, fix scanner_isspace()
|
||||||
* to agree, and see also the plpgsql lexer.
|
* to agree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
space [ \t\n\r\f]
|
space [ \t\n\r\f]
|
||||||
@ -417,32 +418,36 @@ other .
|
|||||||
yyless(2);
|
yyless(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
<xc>{xcstart} {
|
<xc>{
|
||||||
|
{xcstart} {
|
||||||
(yyextra->xcdepth)++;
|
(yyextra->xcdepth)++;
|
||||||
/* Put back any characters past slash-star; see above */
|
/* Put back any characters past slash-star; see above */
|
||||||
yyless(2);
|
yyless(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
<xc>{xcstop} {
|
{xcstop} {
|
||||||
if (yyextra->xcdepth <= 0)
|
if (yyextra->xcdepth <= 0)
|
||||||
BEGIN(INITIAL);
|
BEGIN(INITIAL);
|
||||||
else
|
else
|
||||||
(yyextra->xcdepth)--;
|
(yyextra->xcdepth)--;
|
||||||
}
|
}
|
||||||
|
|
||||||
<xc>{xcinside} {
|
{xcinside} {
|
||||||
/* ignore */
|
/* ignore */
|
||||||
}
|
}
|
||||||
|
|
||||||
<xc>{op_chars} {
|
{op_chars} {
|
||||||
/* ignore */
|
/* ignore */
|
||||||
}
|
}
|
||||||
|
|
||||||
<xc>\*+ {
|
\*+ {
|
||||||
/* ignore */
|
/* ignore */
|
||||||
}
|
}
|
||||||
|
|
||||||
<xc><<EOF>> { yyerror("unterminated /* comment"); }
|
<<EOF>> {
|
||||||
|
yyerror("unterminated /* comment");
|
||||||
|
}
|
||||||
|
} /* <xc> */
|
||||||
|
|
||||||
{xbstart} {
|
{xbstart} {
|
||||||
/* Binary bit type.
|
/* Binary bit type.
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
*
|
*
|
||||||
* See psqlscan_int.h for additional commentary.
|
* See psqlscan_int.h for additional commentary.
|
||||||
*
|
*
|
||||||
|
*
|
||||||
* Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
@ -39,6 +40,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
%{
|
%{
|
||||||
|
|
||||||
|
/* LCOV_EXCL_START */
|
||||||
|
|
||||||
#include "fe_utils/psqlscan_int.h"
|
#include "fe_utils/psqlscan_int.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -71,8 +75,6 @@ typedef int YYSTYPE;
|
|||||||
extern int psql_yyget_column(yyscan_t yyscanner);
|
extern int psql_yyget_column(yyscan_t yyscanner);
|
||||||
extern void psql_yyset_column(int column_no, yyscan_t yyscanner);
|
extern void psql_yyset_column(int column_no, yyscan_t yyscanner);
|
||||||
|
|
||||||
/* LCOV_EXCL_START */
|
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%option reentrant
|
%option reentrant
|
||||||
@ -128,8 +130,8 @@ extern void psql_yyset_column(int column_no, yyscan_t yyscanner);
|
|||||||
%x xc
|
%x xc
|
||||||
%x xd
|
%x xd
|
||||||
%x xh
|
%x xh
|
||||||
%x xe
|
|
||||||
%x xq
|
%x xq
|
||||||
|
%x xe
|
||||||
%x xdolq
|
%x xdolq
|
||||||
%x xui
|
%x xui
|
||||||
%x xuiend
|
%x xuiend
|
||||||
@ -151,7 +153,7 @@ extern void psql_yyset_column(int column_no, yyscan_t yyscanner);
|
|||||||
* XXX perhaps \f (formfeed) should be treated as a newline as well?
|
* XXX perhaps \f (formfeed) should be treated as a newline as well?
|
||||||
*
|
*
|
||||||
* XXX if you change the set of whitespace characters, fix scanner_isspace()
|
* XXX if you change the set of whitespace characters, fix scanner_isspace()
|
||||||
* to agree, and see also the plpgsql lexer.
|
* to agree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
space [ \t\n\r\f]
|
space [ \t\n\r\f]
|
||||||
@ -402,14 +404,15 @@ other .
|
|||||||
ECHO;
|
ECHO;
|
||||||
}
|
}
|
||||||
|
|
||||||
<xc>{xcstart} {
|
<xc>{
|
||||||
|
{xcstart} {
|
||||||
cur_state->xcdepth++;
|
cur_state->xcdepth++;
|
||||||
/* Put back any characters past slash-star; see above */
|
/* Put back any characters past slash-star; see above */
|
||||||
yyless(2);
|
yyless(2);
|
||||||
ECHO;
|
ECHO;
|
||||||
}
|
}
|
||||||
|
|
||||||
<xc>{xcstop} {
|
{xcstop} {
|
||||||
if (cur_state->xcdepth <= 0)
|
if (cur_state->xcdepth <= 0)
|
||||||
BEGIN(INITIAL);
|
BEGIN(INITIAL);
|
||||||
else
|
else
|
||||||
@ -417,17 +420,18 @@ other .
|
|||||||
ECHO;
|
ECHO;
|
||||||
}
|
}
|
||||||
|
|
||||||
<xc>{xcinside} {
|
{xcinside} {
|
||||||
ECHO;
|
ECHO;
|
||||||
}
|
}
|
||||||
|
|
||||||
<xc>{op_chars} {
|
{op_chars} {
|
||||||
ECHO;
|
ECHO;
|
||||||
}
|
}
|
||||||
|
|
||||||
<xc>\*+ {
|
\*+ {
|
||||||
ECHO;
|
ECHO;
|
||||||
}
|
}
|
||||||
|
} /* <xc> */
|
||||||
|
|
||||||
{xbstart} {
|
{xbstart} {
|
||||||
BEGIN(xb);
|
BEGIN(xb);
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
* Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* src/interfaces/ecpg/preproc/pgc.l
|
* src/interfaces/ecpg/preproc/pgc.l
|
||||||
*
|
*
|
||||||
@ -28,6 +27,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
%{
|
%{
|
||||||
|
|
||||||
|
/* LCOV_EXCL_START */
|
||||||
|
|
||||||
extern YYSTYPE base_yylval;
|
extern YYSTYPE base_yylval;
|
||||||
|
|
||||||
static int xcdepth = 0; /* depth of nesting in slash-star comments */
|
static int xcdepth = 0; /* depth of nesting in slash-star comments */
|
||||||
@ -53,8 +55,9 @@ static bool include_next;
|
|||||||
|
|
||||||
#define startlit() (literalbuf[0] = '\0', literallen = 0)
|
#define startlit() (literalbuf[0] = '\0', literallen = 0)
|
||||||
static void addlit(char *ytext, int yleng);
|
static void addlit(char *ytext, int yleng);
|
||||||
static void addlitchar (unsigned char);
|
static void addlitchar(unsigned char);
|
||||||
static void parse_include (void);
|
static int process_integer_literal(const char *token, YYSTYPE *lval);
|
||||||
|
static void parse_include(void);
|
||||||
static bool ecpg_isspace(char ch);
|
static bool ecpg_isspace(char ch);
|
||||||
static bool isdefine(void);
|
static bool isdefine(void);
|
||||||
static bool isinformixdefine(void);
|
static bool isinformixdefine(void);
|
||||||
@ -81,8 +84,6 @@ static struct _if_value
|
|||||||
short else_branch;
|
short else_branch;
|
||||||
} stacked_if_value[MAX_NESTED_IF];
|
} stacked_if_value[MAX_NESTED_IF];
|
||||||
|
|
||||||
/* LCOV_EXCL_START */
|
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%option 8bit
|
%option 8bit
|
||||||
@ -91,11 +92,8 @@ static struct _if_value
|
|||||||
%option noinput
|
%option noinput
|
||||||
%option noyywrap
|
%option noyywrap
|
||||||
%option warn
|
%option warn
|
||||||
%option prefix="base_yy"
|
|
||||||
|
|
||||||
%option yylineno
|
%option yylineno
|
||||||
|
%option prefix="base_yy"
|
||||||
%x C SQL incl def def_ident undef
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* OK, here is a short description of lex/flex rules behavior.
|
* OK, here is a short description of lex/flex rules behavior.
|
||||||
@ -111,15 +109,21 @@ static struct _if_value
|
|||||||
* <xb> bit string literal
|
* <xb> bit string literal
|
||||||
* <xcc> extended C-style comments in C
|
* <xcc> extended C-style comments in C
|
||||||
* <xcsql> extended C-style comments in SQL
|
* <xcsql> extended C-style comments in SQL
|
||||||
* <xd> delimited identifiers (double-quoted identifiers) - thomas 1997-10-27
|
* <xd> delimited identifiers (double-quoted identifiers)
|
||||||
* <xh> hexadecimal numeric string - thomas 1997-11-16
|
* <xdc> double-quoted strings in C
|
||||||
* <xq> standard quoted strings - thomas 1997-07-30
|
* <xh> hexadecimal numeric string
|
||||||
* <xqc> standard quoted strings in C - michael
|
|
||||||
* <xe> extended quoted strings (support backslash escape sequences)
|
|
||||||
* <xn> national character quoted strings
|
* <xn> national character quoted strings
|
||||||
|
* <xq> standard quoted strings
|
||||||
|
* <xe> extended quoted strings (support backslash escape sequences)
|
||||||
|
* <xqc> single-quoted strings in C
|
||||||
* <xdolq> $foo$ quoted strings
|
* <xdolq> $foo$ quoted strings
|
||||||
* <xui> quoted identifier with Unicode escapes
|
* <xui> quoted identifier with Unicode escapes
|
||||||
* <xus> quoted string with Unicode escapes
|
* <xus> quoted string with Unicode escapes
|
||||||
|
* <xcond> condition of an EXEC SQL IFDEF construct
|
||||||
|
* <xskip> skipping the inactive part of an EXEC SQL IFDEF construct
|
||||||
|
*
|
||||||
|
* Remember to add an <<EOF>> case whenever you add a new exclusive state!
|
||||||
|
* The default one is probably not the right thing.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
%x xb
|
%x xb
|
||||||
@ -128,15 +132,60 @@ static struct _if_value
|
|||||||
%x xd
|
%x xd
|
||||||
%x xdc
|
%x xdc
|
||||||
%x xh
|
%x xh
|
||||||
%x xe
|
|
||||||
%x xn
|
%x xn
|
||||||
%x xq
|
%x xq
|
||||||
|
%x xe
|
||||||
%x xqc
|
%x xqc
|
||||||
%x xdolq
|
%x xdolq
|
||||||
%x xcond
|
|
||||||
%x xskip
|
|
||||||
%x xui
|
%x xui
|
||||||
%x xus
|
%x xus
|
||||||
|
%x xcond
|
||||||
|
%x xskip
|
||||||
|
|
||||||
|
/* Additional exclusive states that are specific to ECPG */
|
||||||
|
%x C SQL incl def def_ident undef
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In order to make the world safe for Windows and Mac clients as well as
|
||||||
|
* Unix ones, we accept either \n or \r as a newline. A DOS-style \r\n
|
||||||
|
* sequence will be seen as two successive newlines, but that doesn't cause
|
||||||
|
* any problems. SQL-style comments, which start with -- and extend to the
|
||||||
|
* next newline, are treated as equivalent to a single whitespace character.
|
||||||
|
*
|
||||||
|
* NOTE a fine point: if there is no newline following --, we will absorb
|
||||||
|
* everything to the end of the input as a comment. This is correct. Older
|
||||||
|
* versions of Postgres failed to recognize -- as a comment if the input
|
||||||
|
* did not end with a newline.
|
||||||
|
*
|
||||||
|
* XXX perhaps \f (formfeed) should be treated as a newline as well?
|
||||||
|
*
|
||||||
|
* XXX if you change the set of whitespace characters, fix ecpg_isspace()
|
||||||
|
* to agree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
space [ \t\n\r\f]
|
||||||
|
horiz_space [ \t\f]
|
||||||
|
newline [\n\r]
|
||||||
|
non_newline [^\n\r]
|
||||||
|
|
||||||
|
comment ("--"{non_newline}*)
|
||||||
|
|
||||||
|
whitespace ({space}+|{comment})
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SQL requires at least one newline in the whitespace separating
|
||||||
|
* string literals that are to be concatenated. Silly, but who are we
|
||||||
|
* to argue? Note that {whitespace_with_newline} should not have * after
|
||||||
|
* it, whereas {whitespace} should generally have a * after it...
|
||||||
|
*/
|
||||||
|
|
||||||
|
horiz_whitespace ({horiz_space}|{comment})
|
||||||
|
whitespace_with_newline ({horiz_whitespace}*{newline}{whitespace}*)
|
||||||
|
|
||||||
|
quote '
|
||||||
|
quotestop {quote}{whitespace}*
|
||||||
|
quotecontinue {quote}{whitespace_with_newline}{quote}
|
||||||
|
quotefail {quote}{whitespace}*"-"
|
||||||
|
|
||||||
/* Bit string
|
/* Bit string
|
||||||
*/
|
*/
|
||||||
@ -158,9 +207,6 @@ xeoctesc [\\][0-7]{1,3}
|
|||||||
xehexesc [\\]x[0-9A-Fa-f]{1,2}
|
xehexesc [\\]x[0-9A-Fa-f]{1,2}
|
||||||
xeunicode [\\](u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})
|
xeunicode [\\](u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})
|
||||||
|
|
||||||
/* C version of hex number */
|
|
||||||
xch 0[xX][0-9A-Fa-f]*
|
|
||||||
|
|
||||||
/* Extended quote
|
/* Extended quote
|
||||||
* xqdouble implements embedded quote, ''''
|
* xqdouble implements embedded quote, ''''
|
||||||
*/
|
*/
|
||||||
@ -194,7 +240,9 @@ xddouble {dquote}{dquote}
|
|||||||
xdinside [^"]+
|
xdinside [^"]+
|
||||||
|
|
||||||
/* Unicode escapes */
|
/* Unicode escapes */
|
||||||
/* (The ecpg scanner is not backup-free, so the fail rules in scan.l are not needed here, but could be added if desired.) */
|
/* (The ecpg scanner is not backup-free, so the fail rules in scan.l are
|
||||||
|
* not needed here, but could be added if desired.)
|
||||||
|
*/
|
||||||
uescape [uU][eE][sS][cC][aA][pP][eE]{whitespace}*{quote}[^']{quote}
|
uescape [uU][eE][sS][cC][aA][pP][eE]{whitespace}*{quote}[^']{quote}
|
||||||
|
|
||||||
/* Quoted identifier with Unicode escapes */
|
/* Quoted identifier with Unicode escapes */
|
||||||
@ -211,6 +259,7 @@ xdcqdq \\\"
|
|||||||
xdcother [^"]
|
xdcother [^"]
|
||||||
xdcinside ({xdcqq}|{xdcqdq}|{xdcother})
|
xdcinside ({xdcqq}|{xdcqdq}|{xdcother})
|
||||||
|
|
||||||
|
|
||||||
/* C-style comments
|
/* C-style comments
|
||||||
*
|
*
|
||||||
* The "extended comment" syntax closely resembles allowable operator syntax.
|
* The "extended comment" syntax closely resembles allowable operator syntax.
|
||||||
@ -278,68 +327,40 @@ operator {op_chars}+
|
|||||||
* instead we pass it separately to parser. there it gets
|
* instead we pass it separately to parser. there it gets
|
||||||
* coerced via doNegate() -- Leon aug 20 1999
|
* coerced via doNegate() -- Leon aug 20 1999
|
||||||
*
|
*
|
||||||
|
* {decimalfail} is used because we would like "1..10" to lex as 1, dot_dot, 10.
|
||||||
|
*
|
||||||
* {realfail1} and {realfail2} are added to prevent the need for scanner
|
* {realfail1} and {realfail2} are added to prevent the need for scanner
|
||||||
* backup when the {real} rule fails to match completely.
|
* backup when the {real} rule fails to match completely.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
integer {digit}+
|
integer {digit}+
|
||||||
decimal (({digit}*\.{digit}+)|({digit}+\.{digit}*))
|
decimal (({digit}*\.{digit}+)|({digit}+\.{digit}*))
|
||||||
|
decimalfail {digit}+\.\.
|
||||||
real ({integer}|{decimal})[Ee][-+]?{digit}+
|
real ({integer}|{decimal})[Ee][-+]?{digit}+
|
||||||
realfail1 ({integer}|{decimal})[Ee]
|
realfail1 ({integer}|{decimal})[Ee]
|
||||||
realfail2 ({integer}|{decimal})[Ee][-+]
|
realfail2 ({integer}|{decimal})[Ee][-+]
|
||||||
|
|
||||||
param \${integer}
|
param \${integer}
|
||||||
|
|
||||||
/*
|
|
||||||
* In order to make the world safe for Windows and Mac clients as well as
|
|
||||||
* Unix ones, we accept either \n or \r as a newline. A DOS-style \r\n
|
|
||||||
* sequence will be seen as two successive newlines, but that doesn't cause
|
|
||||||
* any problems. SQL-style comments, which start with -- and extend to the
|
|
||||||
* next newline, are treated as equivalent to a single whitespace character.
|
|
||||||
*
|
|
||||||
* NOTE a fine point: if there is no newline following --, we will absorb
|
|
||||||
* everything to the end of the input as a comment. This is correct. Older
|
|
||||||
* versions of Postgres failed to recognize -- as a comment if the input
|
|
||||||
* did not end with a newline.
|
|
||||||
*
|
|
||||||
* XXX perhaps \f (formfeed) should be treated as a newline as well?
|
|
||||||
*
|
|
||||||
* XXX if you change the set of whitespace characters, fix ecpg_isspace()
|
|
||||||
* to agree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
ccomment "//".*\n
|
|
||||||
|
|
||||||
space [ \t\n\r\f]
|
|
||||||
horiz_space [ \t\f]
|
|
||||||
newline [\n\r]
|
|
||||||
non_newline [^\n\r]
|
|
||||||
|
|
||||||
comment ("--"{non_newline}*)
|
|
||||||
|
|
||||||
whitespace ({space}+|{comment})
|
|
||||||
|
|
||||||
/*
|
|
||||||
* SQL requires at least one newline in the whitespace separating
|
|
||||||
* string literals that are to be concatenated. Silly, but who are we
|
|
||||||
* to argue? Note that {whitespace_with_newline} should not have * after
|
|
||||||
* it, whereas {whitespace} should generally have a * after it...
|
|
||||||
*/
|
|
||||||
|
|
||||||
horiz_whitespace ({horiz_space}|{comment})
|
|
||||||
whitespace_with_newline ({horiz_whitespace}*{newline}{whitespace}*)
|
|
||||||
|
|
||||||
quote '
|
|
||||||
quotestop {quote}{whitespace}*
|
|
||||||
quotecontinue {quote}{whitespace_with_newline}{quote}
|
|
||||||
quotefail {quote}{whitespace}*"-"
|
|
||||||
|
|
||||||
/* special characters for other dbms */
|
/* special characters for other dbms */
|
||||||
/* we have to react differently in compat mode */
|
/* we have to react differently in compat mode */
|
||||||
informix_special [\$]
|
informix_special [\$]
|
||||||
|
|
||||||
other .
|
other .
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dollar quoted strings are totally opaque, and no escaping is done on them.
|
||||||
|
* Other quoted strings must allow some special characters such as single-quote
|
||||||
|
* and newline.
|
||||||
|
* Embedded single-quotes are implemented both in the SQL standard
|
||||||
|
* style of two adjacent single quotes "''" and in the Postgres/Java style
|
||||||
|
* of escaped-quote "\'".
|
||||||
|
* Other embedded escaped characters are matched explicitly and the leading
|
||||||
|
* backslash is dropped from the string.
|
||||||
|
* Note that xcstart must appear before operator, as explained above!
|
||||||
|
* Also whitespace (comment) must appear before operator.
|
||||||
|
*/
|
||||||
|
|
||||||
/* some stuff needed for ecpg */
|
/* some stuff needed for ecpg */
|
||||||
exec [eE][xX][eE][cC]
|
exec [eE][xX][eE][cC]
|
||||||
sql [sS][qQ][lL]
|
sql [sS][qQ][lL]
|
||||||
@ -349,6 +370,11 @@ include_next [iI][nN][cC][lL][uU][dD][eE]_[nN][eE][xX][tT]
|
|||||||
import [iI][mM][pP][oO][rR][tT]
|
import [iI][mM][pP][oO][rR][tT]
|
||||||
undef [uU][nN][dD][eE][fF]
|
undef [uU][nN][dD][eE][fF]
|
||||||
|
|
||||||
|
/* C version of hex number */
|
||||||
|
xch 0[xX][0-9A-Fa-f]*
|
||||||
|
|
||||||
|
ccomment "//".*\n
|
||||||
|
|
||||||
if [iI][fF]
|
if [iI][fF]
|
||||||
ifdef [iI][fF][dD][eE][fF]
|
ifdef [iI][fF][dD][eE][fF]
|
||||||
ifndef [iI][fF][nN][dD][eE][fF]
|
ifndef [iI][fF][nN][dD][eE][fF]
|
||||||
@ -366,24 +392,12 @@ ip {ipdigit}\.{ipdigit}\.{ipdigit}\.{ipdigit}
|
|||||||
cppinclude {space}*#{include}{space}*
|
cppinclude {space}*#{include}{space}*
|
||||||
cppinclude_next {space}*#{include_next}{space}*
|
cppinclude_next {space}*#{include_next}{space}*
|
||||||
|
|
||||||
/* take care of cpp lines, they may also be continuated */
|
/* take care of cpp lines, they may also be continued */
|
||||||
/* first a general line for all commands not starting with "i" */
|
/* first a general line for all commands not starting with "i" */
|
||||||
/* and then the other commands starting with "i", we have to add these
|
/* and then the other commands starting with "i", we have to add these
|
||||||
* separately because the cppline production would match on "include" too */
|
* separately because the cppline production would match on "include" too
|
||||||
cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+\/)|.|\\{space}*{newline})*{newline}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Dollar quoted strings are totally opaque, and no escaping is done on them.
|
|
||||||
* Other quoted strings must allow some special characters such as single-quote
|
|
||||||
* and newline.
|
|
||||||
* Embedded single-quotes are implemented both in the SQL standard
|
|
||||||
* style of two adjacent single quotes "''" and in the Postgres/Java style
|
|
||||||
* of escaped-quote "\'".
|
|
||||||
* Other embedded escaped characters are matched explicitly and the leading
|
|
||||||
* backslash is dropped from the string. - thomas 1997-09-24
|
|
||||||
* Note that xcstart must appear before operator, as explained above!
|
|
||||||
* Also whitespace (comment) must appear before operator.
|
|
||||||
*/
|
*/
|
||||||
|
cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+\/)|.|\\{space}*{newline})*{newline}
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
@ -392,7 +406,21 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
|
|||||||
token_start = NULL;
|
token_start = NULL;
|
||||||
%}
|
%}
|
||||||
|
|
||||||
<SQL>{whitespace} { /* ignore */ }
|
<SQL>{
|
||||||
|
{whitespace} {
|
||||||
|
/* ignore */
|
||||||
|
}
|
||||||
|
|
||||||
|
{xcstart} {
|
||||||
|
token_start = yytext;
|
||||||
|
state_before = YYSTATE;
|
||||||
|
xcdepth = 0;
|
||||||
|
BEGIN(xcsql);
|
||||||
|
/* Put back any characters past slash-star; see above */
|
||||||
|
yyless(2);
|
||||||
|
fputs("/*", yyout);
|
||||||
|
}
|
||||||
|
} /* <SQL> */
|
||||||
|
|
||||||
<C>{xcstart} {
|
<C>{xcstart} {
|
||||||
token_start = yytext;
|
token_start = yytext;
|
||||||
@ -403,15 +431,6 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
|
|||||||
yyless(2);
|
yyless(2);
|
||||||
fputs("/*", yyout);
|
fputs("/*", yyout);
|
||||||
}
|
}
|
||||||
<SQL>{xcstart} {
|
|
||||||
token_start = yytext;
|
|
||||||
state_before = YYSTATE;
|
|
||||||
xcdepth = 0;
|
|
||||||
BEGIN(xcsql);
|
|
||||||
/* Put back any characters past slash-star; see above */
|
|
||||||
yyless(2);
|
|
||||||
fputs("/*", yyout);
|
|
||||||
}
|
|
||||||
<xcc>{xcstart} { ECHO; }
|
<xcc>{xcstart} { ECHO; }
|
||||||
<xcsql>{xcstart} {
|
<xcsql>{xcstart} {
|
||||||
xcdepth++;
|
xcdepth++;
|
||||||
@ -437,18 +456,34 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
|
|||||||
BEGIN(state_before);
|
BEGIN(state_before);
|
||||||
token_start = NULL;
|
token_start = NULL;
|
||||||
}
|
}
|
||||||
<xcc,xcsql>{xcinside} { ECHO; }
|
|
||||||
<xcc,xcsql>{op_chars} { ECHO; }
|
|
||||||
<xcc,xcsql>\*+ { ECHO; }
|
|
||||||
|
|
||||||
<xcc,xcsql><<EOF>> { mmfatal(PARSE_ERROR, "unterminated /* comment"); }
|
<xcc,xcsql>{
|
||||||
|
{xcinside} {
|
||||||
|
ECHO;
|
||||||
|
}
|
||||||
|
|
||||||
<SQL>{xbstart} {
|
{op_chars} {
|
||||||
|
ECHO;
|
||||||
|
}
|
||||||
|
|
||||||
|
\*+ {
|
||||||
|
ECHO;
|
||||||
|
}
|
||||||
|
|
||||||
|
<<EOF>> {
|
||||||
|
mmfatal(PARSE_ERROR, "unterminated /* comment");
|
||||||
|
}
|
||||||
|
} /* <xcc,xcsql> */
|
||||||
|
|
||||||
|
<SQL>{
|
||||||
|
{xbstart} {
|
||||||
token_start = yytext;
|
token_start = yytext;
|
||||||
BEGIN(xb);
|
BEGIN(xb);
|
||||||
startlit();
|
startlit();
|
||||||
addlitchar('b');
|
addlitchar('b');
|
||||||
}
|
}
|
||||||
|
} /* <SQL> */
|
||||||
|
|
||||||
<xb>{quotestop} |
|
<xb>{quotestop} |
|
||||||
<xb>{quotefail} {
|
<xb>{quotefail} {
|
||||||
yyless(1);
|
yyless(1);
|
||||||
@ -458,11 +493,14 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
|
|||||||
base_yylval.str = mm_strdup(literalbuf);
|
base_yylval.str = mm_strdup(literalbuf);
|
||||||
return BCONST;
|
return BCONST;
|
||||||
}
|
}
|
||||||
|
|
||||||
<xh>{xhinside} |
|
<xh>{xhinside} |
|
||||||
<xb>{xbinside} { addlit(yytext, yyleng); }
|
<xb>{xbinside} {
|
||||||
|
addlit(yytext, yyleng);
|
||||||
|
}
|
||||||
<xh>{quotecontinue} |
|
<xh>{quotecontinue} |
|
||||||
<xb>{quotecontinue} { /* ignore */ }
|
<xb>{quotecontinue} {
|
||||||
|
/* ignore */
|
||||||
|
}
|
||||||
<xb><<EOF>> { mmfatal(PARSE_ERROR, "unterminated bit string literal"); }
|
<xb><<EOF>> { mmfatal(PARSE_ERROR, "unterminated bit string literal"); }
|
||||||
|
|
||||||
<SQL>{xhstart} {
|
<SQL>{xhstart} {
|
||||||
@ -480,7 +518,16 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
|
|||||||
}
|
}
|
||||||
|
|
||||||
<xh><<EOF>> { mmfatal(PARSE_ERROR, "unterminated hexadecimal string literal"); }
|
<xh><<EOF>> { mmfatal(PARSE_ERROR, "unterminated hexadecimal string literal"); }
|
||||||
<SQL>{xnstart} {
|
|
||||||
|
<C>{xqstart} {
|
||||||
|
token_start = yytext;
|
||||||
|
state_before = YYSTATE;
|
||||||
|
BEGIN(xqc);
|
||||||
|
startlit();
|
||||||
|
}
|
||||||
|
|
||||||
|
<SQL>{
|
||||||
|
{xnstart} {
|
||||||
/* National character.
|
/* National character.
|
||||||
* Transfer it as-is to the backend.
|
* Transfer it as-is to the backend.
|
||||||
*/
|
*/
|
||||||
@ -489,31 +536,28 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
|
|||||||
BEGIN(xn);
|
BEGIN(xn);
|
||||||
startlit();
|
startlit();
|
||||||
}
|
}
|
||||||
<C>{xqstart} {
|
|
||||||
token_start = yytext;
|
{xqstart} {
|
||||||
state_before = YYSTATE;
|
|
||||||
BEGIN(xqc);
|
|
||||||
startlit();
|
|
||||||
}
|
|
||||||
<SQL>{xqstart} {
|
|
||||||
token_start = yytext;
|
token_start = yytext;
|
||||||
state_before = YYSTATE;
|
state_before = YYSTATE;
|
||||||
BEGIN(xq);
|
BEGIN(xq);
|
||||||
startlit();
|
startlit();
|
||||||
}
|
}
|
||||||
<SQL>{xestart} {
|
{xestart} {
|
||||||
token_start = yytext;
|
token_start = yytext;
|
||||||
state_before = YYSTATE;
|
state_before = YYSTATE;
|
||||||
BEGIN(xe);
|
BEGIN(xe);
|
||||||
startlit();
|
startlit();
|
||||||
}
|
}
|
||||||
<SQL>{xusstart} {
|
{xusstart} {
|
||||||
token_start = yytext;
|
token_start = yytext;
|
||||||
state_before = YYSTATE;
|
state_before = YYSTATE;
|
||||||
BEGIN(xus);
|
BEGIN(xus);
|
||||||
startlit();
|
startlit();
|
||||||
addlit(yytext, yyleng);
|
addlit(yytext, yyleng);
|
||||||
}
|
}
|
||||||
|
} /* <SQL> */
|
||||||
|
|
||||||
<xq,xqc>{quotestop} |
|
<xq,xqc>{quotestop} |
|
||||||
<xq,xqc>{quotefail} {
|
<xq,xqc>{quotefail} {
|
||||||
yyless(1);
|
yyless(1);
|
||||||
@ -547,24 +591,32 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
|
|||||||
addlitchar('\'');
|
addlitchar('\'');
|
||||||
}
|
}
|
||||||
<xq,xqc,xn,xus>{xqinside} { addlit(yytext, yyleng); }
|
<xq,xqc,xn,xus>{xqinside} { addlit(yytext, yyleng); }
|
||||||
<xe>{xeinside} { addlit(yytext, yyleng); }
|
<xe>{xeinside} {
|
||||||
<xe>{xeunicode} { addlit(yytext, yyleng); }
|
addlit(yytext, yyleng);
|
||||||
<xe>{xeescape} { addlit(yytext, yyleng); }
|
}
|
||||||
<xe>{xeoctesc} { addlit(yytext, yyleng); }
|
<xe>{xeunicode} {
|
||||||
<xe>{xehexesc} { addlit(yytext, yyleng); }
|
addlit(yytext, yyleng);
|
||||||
<xq,xqc,xe,xn,xus>{quotecontinue} { /* ignore */ }
|
}
|
||||||
|
<xe>{xeescape} {
|
||||||
|
addlit(yytext, yyleng);
|
||||||
|
}
|
||||||
|
<xe>{xeoctesc} {
|
||||||
|
addlit(yytext, yyleng);
|
||||||
|
}
|
||||||
|
<xe>{xehexesc} {
|
||||||
|
addlit(yytext, yyleng);
|
||||||
|
}
|
||||||
|
<xq,xqc,xe,xn,xus>{quotecontinue} {
|
||||||
|
/* ignore */
|
||||||
|
}
|
||||||
<xe>. {
|
<xe>. {
|
||||||
/* This is only needed for \ just before EOF */
|
/* This is only needed for \ just before EOF */
|
||||||
addlitchar(yytext[0]);
|
addlitchar(yytext[0]);
|
||||||
}
|
}
|
||||||
<xq,xqc,xe,xn,xus><<EOF>> { mmfatal(PARSE_ERROR, "unterminated quoted string"); }
|
<xq,xqc,xe,xn,xus><<EOF>> { mmfatal(PARSE_ERROR, "unterminated quoted string"); }
|
||||||
<SQL>{dolqfailed} {
|
|
||||||
/* throw back all but the initial "$" */
|
<SQL>{
|
||||||
yyless(1);
|
{dolqdelim} {
|
||||||
/* and treat it as {other} */
|
|
||||||
return yytext[0];
|
|
||||||
}
|
|
||||||
<SQL>{dolqdelim} {
|
|
||||||
token_start = yytext;
|
token_start = yytext;
|
||||||
if (dolqstart)
|
if (dolqstart)
|
||||||
free(dolqstart);
|
free(dolqstart);
|
||||||
@ -573,6 +625,14 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
|
|||||||
startlit();
|
startlit();
|
||||||
addlit(yytext, yyleng);
|
addlit(yytext, yyleng);
|
||||||
}
|
}
|
||||||
|
{dolqfailed} {
|
||||||
|
/* throw back all but the initial "$" */
|
||||||
|
yyless(1);
|
||||||
|
/* and treat it as {other} */
|
||||||
|
return yytext[0];
|
||||||
|
}
|
||||||
|
} /* <SQL> */
|
||||||
|
|
||||||
<xdolq>{dolqdelim} {
|
<xdolq>{dolqdelim} {
|
||||||
if (strcmp(yytext, dolqstart) == 0)
|
if (strcmp(yytext, dolqstart) == 0)
|
||||||
{
|
{
|
||||||
@ -590,28 +650,36 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
|
|||||||
* the $... part to the output, but put back the final
|
* the $... part to the output, but put back the final
|
||||||
* $ for rescanning. Consider $delim$...$junk$delim$
|
* $ for rescanning. Consider $delim$...$junk$delim$
|
||||||
*/
|
*/
|
||||||
addlit(yytext, yyleng-1);
|
addlit(yytext, yyleng - 1);
|
||||||
yyless(yyleng-1);
|
yyless(yyleng - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
<xdolq>{dolqinside} { addlit(yytext, yyleng); }
|
<xdolq>{dolqinside} {
|
||||||
<xdolq>{dolqfailed} { addlit(yytext, yyleng); }
|
addlit(yytext, yyleng);
|
||||||
<xdolq>{other} {
|
}
|
||||||
|
<xdolq>{dolqfailed} {
|
||||||
|
addlit(yytext, yyleng);
|
||||||
|
}
|
||||||
|
<xdolq>. {
|
||||||
/* single quote or dollar sign */
|
/* single quote or dollar sign */
|
||||||
addlitchar(yytext[0]);
|
addlitchar(yytext[0]);
|
||||||
}
|
}
|
||||||
<xdolq><<EOF>> { base_yyerror("unterminated dollar-quoted string"); }
|
<xdolq><<EOF>> { mmfatal(PARSE_ERROR, "unterminated dollar-quoted string"); }
|
||||||
<SQL>{xdstart} {
|
|
||||||
|
<SQL>{
|
||||||
|
{xdstart} {
|
||||||
state_before = YYSTATE;
|
state_before = YYSTATE;
|
||||||
BEGIN(xd);
|
BEGIN(xd);
|
||||||
startlit();
|
startlit();
|
||||||
}
|
}
|
||||||
<SQL>{xuistart} {
|
{xuistart} {
|
||||||
state_before = YYSTATE;
|
state_before = YYSTATE;
|
||||||
BEGIN(xui);
|
BEGIN(xui);
|
||||||
startlit();
|
startlit();
|
||||||
addlit(yytext, yyleng);
|
addlit(yytext, yyleng);
|
||||||
}
|
}
|
||||||
|
} /* <SQL> */
|
||||||
|
|
||||||
<xd>{xdstop} {
|
<xd>{xdstop} {
|
||||||
BEGIN(state_before);
|
BEGIN(state_before);
|
||||||
if (literallen == 0)
|
if (literallen == 0)
|
||||||
@ -634,24 +702,59 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
|
|||||||
base_yylval.str = mm_strdup(literalbuf);
|
base_yylval.str = mm_strdup(literalbuf);
|
||||||
return UIDENT;
|
return UIDENT;
|
||||||
}
|
}
|
||||||
<xd,xui>{xddouble} { addlitchar('"'); }
|
<xd,xui>{xddouble} {
|
||||||
<xd,xui>{xdinside} { addlit(yytext, yyleng); }
|
addlitchar('"');
|
||||||
<xd,xdc,xui><<EOF>> { mmfatal(PARSE_ERROR, "unterminated quoted identifier"); }
|
}
|
||||||
<C,SQL>{xdstart} {
|
<xd,xui>{xdinside} {
|
||||||
|
addlit(yytext, yyleng);
|
||||||
|
}
|
||||||
|
<xd,xui><<EOF>> { mmfatal(PARSE_ERROR, "unterminated quoted identifier"); }
|
||||||
|
<C>{xdstart} {
|
||||||
state_before = YYSTATE;
|
state_before = YYSTATE;
|
||||||
BEGIN(xdc);
|
BEGIN(xdc);
|
||||||
startlit();
|
startlit();
|
||||||
}
|
}
|
||||||
<xdc>{xdcinside} { addlit(yytext, yyleng); }
|
<xdc>{xdcinside} {
|
||||||
<SQL>{typecast} { return TYPECAST; }
|
addlit(yytext, yyleng);
|
||||||
<SQL>{dot_dot} { return DOT_DOT; }
|
}
|
||||||
<SQL>{colon_equals} { return COLON_EQUALS; }
|
<xdc><<EOF>> { mmfatal(PARSE_ERROR, "unterminated quoted string"); }
|
||||||
<SQL>{equals_greater} { return EQUALS_GREATER; }
|
|
||||||
<SQL>{less_equals} { return LESS_EQUALS; }
|
<SQL>{
|
||||||
<SQL>{greater_equals} { return GREATER_EQUALS; }
|
{typecast} {
|
||||||
<SQL>{less_greater} { return NOT_EQUALS; }
|
return TYPECAST;
|
||||||
<SQL>{not_equals} { return NOT_EQUALS; }
|
}
|
||||||
<SQL>{informix_special} {
|
|
||||||
|
{dot_dot} {
|
||||||
|
return DOT_DOT;
|
||||||
|
}
|
||||||
|
|
||||||
|
{colon_equals} {
|
||||||
|
return COLON_EQUALS;
|
||||||
|
}
|
||||||
|
|
||||||
|
{equals_greater} {
|
||||||
|
return EQUALS_GREATER;
|
||||||
|
}
|
||||||
|
|
||||||
|
{less_equals} {
|
||||||
|
return LESS_EQUALS;
|
||||||
|
}
|
||||||
|
|
||||||
|
{greater_equals} {
|
||||||
|
return GREATER_EQUALS;
|
||||||
|
}
|
||||||
|
|
||||||
|
{less_greater} {
|
||||||
|
/* We accept both "<>" and "!=" as meaning NOT_EQUALS */
|
||||||
|
return NOT_EQUALS;
|
||||||
|
}
|
||||||
|
|
||||||
|
{not_equals} {
|
||||||
|
/* We accept both "<>" and "!=" as meaning NOT_EQUALS */
|
||||||
|
return NOT_EQUALS;
|
||||||
|
}
|
||||||
|
|
||||||
|
{informix_special} {
|
||||||
/* are we simulating Informix? */
|
/* are we simulating Informix? */
|
||||||
if (INFORMIX_MODE)
|
if (INFORMIX_MODE)
|
||||||
{
|
{
|
||||||
@ -660,7 +763,9 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
|
|||||||
else
|
else
|
||||||
return yytext[0];
|
return yytext[0];
|
||||||
}
|
}
|
||||||
<SQL>{self} { /*
|
|
||||||
|
{self} {
|
||||||
|
/*
|
||||||
* We may find a ';' inside a structure
|
* We may find a ';' inside a structure
|
||||||
* definition in a TYPE or VAR statement.
|
* definition in a TYPE or VAR statement.
|
||||||
* This is not an EOL marker.
|
* This is not an EOL marker.
|
||||||
@ -669,7 +774,8 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
|
|||||||
BEGIN(C);
|
BEGIN(C);
|
||||||
return yytext[0];
|
return yytext[0];
|
||||||
}
|
}
|
||||||
<SQL>{operator} {
|
|
||||||
|
{operator} {
|
||||||
/*
|
/*
|
||||||
* Check for embedded slash-star or dash-dash; those
|
* Check for embedded slash-star or dash-dash; those
|
||||||
* are comment starts, so operator must stop there.
|
* are comment starts, so operator must stop there.
|
||||||
@ -765,52 +871,61 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
|
|||||||
base_yylval.str = mm_strdup(yytext);
|
base_yylval.str = mm_strdup(yytext);
|
||||||
return Op;
|
return Op;
|
||||||
}
|
}
|
||||||
<SQL>{param} {
|
|
||||||
|
{param} {
|
||||||
base_yylval.ival = atol(yytext+1);
|
base_yylval.ival = atol(yytext+1);
|
||||||
return PARAM;
|
return PARAM;
|
||||||
}
|
}
|
||||||
<C,SQL>{integer} {
|
|
||||||
int val;
|
|
||||||
char* endptr;
|
|
||||||
|
|
||||||
errno = 0;
|
{ip} {
|
||||||
val = strtoint(yytext, &endptr, 10);
|
|
||||||
if (*endptr != '\0' || errno == ERANGE)
|
|
||||||
{
|
|
||||||
errno = 0;
|
|
||||||
base_yylval.str = mm_strdup(yytext);
|
|
||||||
return FCONST;
|
|
||||||
}
|
|
||||||
base_yylval.ival = val;
|
|
||||||
return ICONST;
|
|
||||||
}
|
|
||||||
<SQL>{ip} {
|
|
||||||
base_yylval.str = mm_strdup(yytext);
|
base_yylval.str = mm_strdup(yytext);
|
||||||
return IP;
|
return IP;
|
||||||
}
|
}
|
||||||
<C,SQL>{decimal} {
|
} /* <SQL> */
|
||||||
|
|
||||||
|
<C,SQL>{
|
||||||
|
{integer} {
|
||||||
|
return process_integer_literal(yytext, &base_yylval);
|
||||||
|
}
|
||||||
|
{decimal} {
|
||||||
base_yylval.str = mm_strdup(yytext);
|
base_yylval.str = mm_strdup(yytext);
|
||||||
return FCONST;
|
return FCONST;
|
||||||
}
|
}
|
||||||
<C,SQL>{real} {
|
{decimalfail} {
|
||||||
|
/* throw back the .., and treat as integer */
|
||||||
|
yyless(yyleng - 2);
|
||||||
|
return process_integer_literal(yytext, &base_yylval);
|
||||||
|
}
|
||||||
|
{real} {
|
||||||
base_yylval.str = mm_strdup(yytext);
|
base_yylval.str = mm_strdup(yytext);
|
||||||
return FCONST;
|
return FCONST;
|
||||||
}
|
}
|
||||||
<SQL>{realfail1} {
|
{realfail1} {
|
||||||
yyless(yyleng-1);
|
/*
|
||||||
|
* throw back the [Ee], and treat as {decimal}. Note
|
||||||
|
* that it is possible the input is actually {integer},
|
||||||
|
* but since this case will almost certainly lead to a
|
||||||
|
* syntax error anyway, we don't bother to distinguish.
|
||||||
|
*/
|
||||||
|
yyless(yyleng - 1);
|
||||||
base_yylval.str = mm_strdup(yytext);
|
base_yylval.str = mm_strdup(yytext);
|
||||||
return FCONST;
|
return FCONST;
|
||||||
}
|
}
|
||||||
<SQL>{realfail2} {
|
{realfail2} {
|
||||||
yyless(yyleng-2);
|
/* throw back the [Ee][+-], and proceed as above */
|
||||||
|
yyless(yyleng - 2);
|
||||||
base_yylval.str = mm_strdup(yytext);
|
base_yylval.str = mm_strdup(yytext);
|
||||||
return FCONST;
|
return FCONST;
|
||||||
}
|
}
|
||||||
<SQL>:{identifier}((("->"|\.){identifier})|(\[{array}\]))* {
|
} /* <C,SQL> */
|
||||||
|
|
||||||
|
<SQL>{
|
||||||
|
:{identifier}((("->"|\.){identifier})|(\[{array}\]))* {
|
||||||
base_yylval.str = mm_strdup(yytext+1);
|
base_yylval.str = mm_strdup(yytext+1);
|
||||||
return CVARIABLE;
|
return CVARIABLE;
|
||||||
}
|
}
|
||||||
<SQL>{identifier} {
|
|
||||||
|
{identifier} {
|
||||||
const ScanKeyword *keyword;
|
const ScanKeyword *keyword;
|
||||||
|
|
||||||
if (!isdefine())
|
if (!isdefine())
|
||||||
@ -837,7 +952,16 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
|
|||||||
return IDENT;
|
return IDENT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
<SQL>{other} { return yytext[0]; }
|
|
||||||
|
{other} {
|
||||||
|
return yytext[0];
|
||||||
|
}
|
||||||
|
} /* <SQL> */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Begin ECPG-specific rules
|
||||||
|
*/
|
||||||
|
|
||||||
<C>{exec_sql} { BEGIN(SQL); return SQL_START; }
|
<C>{exec_sql} { BEGIN(SQL); return SQL_START; }
|
||||||
<C>{informix_special} {
|
<C>{informix_special} {
|
||||||
/* are we simulating Informix? */
|
/* are we simulating Informix? */
|
||||||
@ -1288,6 +1412,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
<INITIAL>{other}|\n { mmfatal(PARSE_ERROR, "internal error: unreachable state; please report this to <pgsql-bugs@postgresql.org>"); }
|
<INITIAL>{other}|\n { mmfatal(PARSE_ERROR, "internal error: unreachable state; please report this to <pgsql-bugs@postgresql.org>"); }
|
||||||
|
|
||||||
%%
|
%%
|
||||||
@ -1350,6 +1475,24 @@ addlitchar(unsigned char ychar)
|
|||||||
literalbuf[literallen] = '\0';
|
literalbuf[literallen] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
process_integer_literal(const char *token, YYSTYPE *lval)
|
||||||
|
{
|
||||||
|
int val;
|
||||||
|
char *endptr;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
val = strtoint(token, &endptr, 10);
|
||||||
|
if (*endptr != '\0' || errno == ERANGE)
|
||||||
|
{
|
||||||
|
/* integer too large, treat it as a float */
|
||||||
|
lval->str = mm_strdup(token);
|
||||||
|
return FCONST;
|
||||||
|
}
|
||||||
|
lval->ival = val;
|
||||||
|
return ICONST;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
parse_include(void)
|
parse_include(void)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user