* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/scan.l,v 1.114 2004/02/21 00:34:52 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/scan.l,v 1.115 2004/02/24 21:45:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
extern YYSTYPE yylval;
static int xcdepth = 0; /* depth of nesting in slash-star comments */
+static char *dolqstart; /* current $foo$ quote start string */
/*
* literalbuf is used to accumulate literal values when multiple rules
%option 8bit
%option never-interactive
+%option nodefault
%option nounput
%option noyywrap
%option prefix="base_yy"
* <xd> delimited identifiers (double-quoted identifiers)
* <xh> hexadecimal numeric string
* <xq> quoted strings
+ * <xdolq> $foo$ quoted strings
*/
%x xb
%x xd
%x xh
%x xq
+%x xdolq
/*
* In order to make the world safe for Windows and Mac clients as well as
xqoctesc [\\][0-7]{1,3}
xqcat {quote}{whitespace_with_newline}{quote}
+/* $foo$ style quotes ("dollar quoting")
+ * The quoted string starts with $foo$ where "foo" is an optional string
+ * in the form of an identifier, except that it may not contain "$",
+ * and extends to the first occurrence of an identical string.
+ * There is *no* processing of the quoted text.
+ */
+dolq_start [A-Za-z\200-\377_]
+dolq_cont [A-Za-z\200-\377_0-9]
+dolqdelim \$({dolq_start}{dolq_cont}*)?\$
+dolqinside [^$]+
+
/* Double quote
* Allows embedded spaces and other special characters into identifiers.
*/
other .
/*
- * Quoted strings must allow some special characters such as single-quote
+ * 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
<xq>{xqcat} {
/* ignore */
}
+<xq>. {
+ /* This is only needed for \ just before EOF */
+ addlitchar(yytext[0]);
+ }
<xq><<EOF>> { yyerror("unterminated quoted string"); }
+{dolqdelim} {
+ token_start = yytext;
+ dolqstart = pstrdup(yytext);
+ BEGIN(xdolq);
+ startlit();
+ }
+<xdolq>{dolqdelim} {
+ if (strcmp(yytext, dolqstart) == 0)
+ {
+ pfree(dolqstart);
+ BEGIN(INITIAL);
+ yylval.str = litbufdup();
+ return SCONST;
+ }
+ else
+ {
+ /*
+ * When we fail to match $...$ to dolqstart, transfer
+ * the $... part to the output, but put back the final
+ * $ for rescanning. Consider $delim$...$junk$delim$
+ */
+ addlit(yytext, yyleng-1);
+ yyless(yyleng-1);
+ }
+ }
+<xdolq>{dolqinside} {
+ addlit(yytext, yyleng);
+ }
+<xdolq>. {
+ /* This is only needed for $ inside the quoted text */
+ addlitchar(yytext[0]);
+ }
+<xdolq><<EOF>> { yyerror("unterminated dollar-quoted string"); }
+
{xdstart} {
token_start = yytext;
BEGIN(xd);
yylval.str = ident;
return IDENT;
}
-<xd>{xddouble} {
+<xd>{xddouble} {
addlitchar('"');
}
<xd>{xdinside} {
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/bin/psql/psqlscan.l,v 1.1 2004/02/19 19:40:09 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/psqlscan.l,v 1.2 2004/02/24 21:45:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
int start_state; /* saved YY_START */
int paren_depth; /* depth of nesting in parentheses */
int xcdepth; /* depth of nesting in slash-star comments */
+ char *dolqstart; /* current $foo$ quote start string */
} PsqlScanStateData;
static PsqlScanState cur_state; /* current state while active */
%option 8bit
%option never-interactive
+%option nodefault
%option nounput
%option noyywrap
* <xd> delimited identifiers (double-quoted identifiers)
* <xh> hexadecimal numeric string
* <xq> quoted strings
+ * <xdolq> $foo$ quoted strings
*/
%x xb
%x xd
%x xh
%x xq
+%x xdolq
/* Additional exclusive states for psql only: lex backslash commands */
%x xslashcmd
%x xslasharg
xqoctesc [\\][0-7]{1,3}
xqcat {quote}{whitespace_with_newline}{quote}
+/* $foo$ style quotes ("dollar quoting")
+ * The quoted string starts with $foo$ where "foo" is an optional string
+ * in the form of an identifier, except that it may not contain "$",
+ * and extends to the first occurrence of an identical string.
+ * There is *no* processing of the quoted text.
+ */
+dolq_start [A-Za-z\200-\377_]
+dolq_cont [A-Za-z\200-\377_0-9]
+dolqdelim \$({dolq_start}{dolq_cont}*)?\$
+dolqinside [^$]+
+
/* Double quote
* Allows embedded spaces and other special characters into identifiers.
*/
other .
/*
- * Quoted strings must allow some special characters such as single-quote
+ * 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
<xq>{xqcat} {
ECHO;
}
+<xq>. {
+ /* This is only needed for \ just before EOF */
+ ECHO;
+ }
+
+{dolqdelim} {
+ cur_state->dolqstart = pg_strdup(yytext);
+ BEGIN(xdolq);
+ ECHO;
+ }
+<xdolq>{dolqdelim} {
+ if (strcmp(yytext, cur_state->dolqstart) == 0)
+ {
+ free(cur_state->dolqstart);
+ cur_state->dolqstart = NULL;
+ BEGIN(INITIAL);
+ }
+ else
+ {
+ /*
+ * When we fail to match $...$ to dolqstart, transfer
+ * the $... part to the output, but put back the final
+ * $ for rescanning. Consider $delim$...$junk$delim$
+ */
+ yyless(yyleng-1);
+ }
+ ECHO;
+ }
+<xdolq>{dolqinside} {
+ ECHO;
+ }
+<xdolq>. {
+ /* This is only needed for $ inside the quoted text */
+ ECHO;
+ }
{xdstart} {
BEGIN(xd);
BEGIN(INITIAL);
ECHO;
}
-<xd>{xddouble} {
+<xd>{xddouble} {
ECHO;
}
<xd>{xdinside} {
"\\". { emit(yytext + 1, 1); }
-{other} { ECHO; }
+{other}|\n { ECHO; }
}
"`" { return LEXRES_OK; }
-{other} { ECHO; }
+{other}|\n { ECHO; }
}
BEGIN(xslashdefaultarg);
}
-{other} { ECHO; }
+{other}|\n { ECHO; }
}
"\\\\" { return LEXRES_OK; }
-{other} {
+{other}|\n {
yyless(0);
return LEXRES_OK;
}
{
psql_scan_finish(state);
+ psql_scan_reset(state);
+
free(state);
}
result = PSCAN_INCOMPLETE;
*prompt = PROMPT_SINGLEQUOTE;
break;
+ case xdolq:
+ result = PSCAN_INCOMPLETE;
+ *prompt = PROMPT_DOLLARQUOTE;
+ break;
default:
/* can't get here */
fprintf(stderr, "invalid YY_START\n");
state->start_state = INITIAL;
state->paren_depth = 0;
state->xcdepth = 0; /* not really necessary */
+ if (state->dolqstart)
+ free(state->dolqstart);
+ state->dolqstart = NULL;
}
/*