?? scan.l
字號:
}<xq>{xqinside} { addlit(yytext, yyleng); }<xq>{xqescape} { if (yytext[1] == '\'') { if (backslash_quote == BACKSLASH_QUOTE_OFF || (backslash_quote == BACKSLASH_QUOTE_SAFE_ENCODING && PG_ENCODING_IS_CLIENT_ONLY(pg_get_client_encoding()))) ereport(ERROR, (errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER), errmsg("unsafe use of \\' in a string literal"), errhint("Use '' to write quotes in strings. \\' is insecure in client-only encodings."), errposition(pg_err_position()))); if (warn_on_first_escape && escape_string_warning) ereport(WARNING, (errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER), errmsg("nonstandard use of \\' in a string literal"), errhint("Use '' to write quotes in strings, or use the escape string syntax (E'...')."), errposition(pg_err_position()))); warn_on_first_escape = false; /* warn only once per string */ } else if (yytext[1] == '\\') { if (warn_on_first_escape && escape_string_warning) ereport(WARNING, (errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER), errmsg("nonstandard use of \\\\ in a string literal"), errhint("Use the escape string syntax for backslashes, e.g., E'\\\\'."), errposition(pg_err_position()))); warn_on_first_escape = false; /* warn only once per string */ } else check_escape_warning(); addlitchar(unescape_single_char(yytext[1])); }<xq>{xqoctesc} { unsigned char c = strtoul(yytext+1, NULL, 8); check_escape_warning(); addlitchar(c); }<xq>{xqhexesc} { unsigned char c = strtoul(yytext+2, NULL, 16); check_escape_warning(); addlitchar(c); }<xq>{quotecontinue} { /* 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(); }{dolqfailed} { /* throw back all but the initial "$" */ yyless(1); /* and treat it as {other} */ return yytext[0]; }<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>{dolqfailed} { 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); startlit(); }<xd>{xdstop} { char *ident; BEGIN(INITIAL); if (literallen == 0) yyerror("zero-length delimited identifier"); ident = litbufdup(); if (literallen >= NAMEDATALEN) truncate_identifier(ident, literallen, true); yylval.str = ident; return IDENT; }<xd>{xddouble} { addlitchar('"'); }<xd>{xdinside} { addlit(yytext, yyleng); }<xd><<EOF>> { yyerror("unterminated quoted identifier"); }{typecast} { return TYPECAST; }{self} { return yytext[0]; }{operator} { /* * Check for embedded slash-star or dash-dash; those * are comment starts, so operator must stop there. * Note that slash-star or dash-dash at the first * character will match a prior rule, not this one. */ int nchars = yyleng; char *slashstar = strstr(yytext, "/*"); char *dashdash = strstr(yytext, "--"); if (slashstar && dashdash) { /* if both appear, take the first one */ if (slashstar > dashdash) slashstar = dashdash; } else if (!slashstar) slashstar = dashdash; if (slashstar) nchars = slashstar - yytext; /* * For SQL compatibility, '+' and '-' cannot be the * last char of a multi-char operator unless the operator * contains chars that are not in SQL operators. * The idea is to lex '=-' as two operators, but not * to forbid operator names like '?-' that could not be * sequences of SQL operators. */ while (nchars > 1 && (yytext[nchars-1] == '+' || yytext[nchars-1] == '-')) { int ic; for (ic = nchars-2; ic >= 0; ic--) { if (strchr("~!@#^&|`?%", yytext[ic])) break; } if (ic >= 0) break; /* found a char that makes it OK */ nchars--; /* else remove the +/-, and check again */ } if (nchars < yyleng) { /* Strip the unwanted chars from the token */ yyless(nchars); /* * If what we have left is only one char, and it's * one of the characters matching "self", then * return it as a character token the same way * that the "self" rule would have. */ if (nchars == 1 && strchr(",()[].;:+-*/%^<>=", yytext[0])) return yytext[0]; } /* * Complain if operator is too long. Unlike the case * for identifiers, we make this an error not a notice- * and-truncate, because the odds are we are looking at * a syntactic mistake anyway. */ if (nchars >= NAMEDATALEN) yyerror("operator too long"); /* Convert "!=" operator to "<>" for compatibility */ if (strcmp(yytext, "!=") == 0) yylval.str = pstrdup("<>"); else yylval.str = pstrdup(yytext); return Op; }{param} { yylval.ival = atol(yytext + 1); return PARAM; }{integer} { long val; char* endptr; errno = 0; val = strtol(yytext, &endptr, 10); if (*endptr != '\0' || errno == ERANGE#ifdef HAVE_LONG_INT_64 /* if long > 32 bits, check for overflow of int4 */ || val != (long) ((int32) val)#endif ) { /* integer too large, treat it as a float */ yylval.str = pstrdup(yytext); return FCONST; } yylval.ival = val; return ICONST; }{decimal} { yylval.str = pstrdup(yytext); return FCONST; }{real} { yylval.str = pstrdup(yytext); return FCONST; }{realfail1} { /* * 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); yylval.str = pstrdup(yytext); return FCONST; }{realfail2} { /* throw back the [Ee][+-], and proceed as above */ yyless(yyleng-2); yylval.str = pstrdup(yytext); return FCONST; }{identifier} { const ScanKeyword *keyword; char *ident; /* Is it a keyword? */ keyword = ScanKeywordLookup(yytext); if (keyword != NULL) { yylval.keyword = keyword->name; return keyword->value; } /* * No. Convert the identifier to lower case, and truncate * if necessary. */ ident = downcase_truncate_identifier(yytext, yyleng, true); yylval.str = ident; return IDENT; }{other} { return yytext[0]; }%%static intpg_err_position(void){ const char *loc = token_start ? token_start : yytext; /* in multibyte encodings, return index in characters not bytes */ return pg_mbstrlen_with_len(scanbuf, loc - scanbuf) + 1;}voidyyerror(const char *message){ const char *loc = token_start ? token_start : yytext; int cursorpos = pg_err_position(); if (*loc == YY_END_OF_BUFFER_CHAR) { ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), /* translator: %s is typically "syntax error" */ errmsg("%s at end of input", _(message)), errposition(cursorpos))); } else { ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), /* translator: first %s is typically "syntax error" */ errmsg("%s at or near \"%s\"", _(message), loc), errposition(cursorpos))); }}/* * Called before any actual parsing is done */voidscanner_init(const char *str){ Size slen = strlen(str); /* * Might be left over after ereport() */ if (YY_CURRENT_BUFFER) yy_delete_buffer(YY_CURRENT_BUFFER); /* * Make a scan buffer with special termination needed by flex. */ scanbuf = palloc(slen + 2); memcpy(scanbuf, str, slen); scanbuf[slen] = scanbuf[slen + 1] = YY_END_OF_BUFFER_CHAR; scanbufhandle = yy_scan_buffer(scanbuf, slen + 2); /* initialize literal buffer to a reasonable but expansible size */ literalalloc = 128; literalbuf = (char *) palloc(literalalloc); startlit(); BEGIN(INITIAL);}/* * Called after parsing is done to clean up after scanner_init() */voidscanner_finish(void){ yy_delete_buffer(scanbufhandle); pfree(scanbuf);}static voidaddlit(char *ytext, int yleng){ /* enlarge buffer if needed */ if ((literallen+yleng) >= literalalloc) { do { literalalloc *= 2; } while ((literallen+yleng) >= literalalloc); literalbuf = (char *) repalloc(literalbuf, literalalloc); } /* append new data, add trailing null */ memcpy(literalbuf+literallen, ytext, yleng); literallen += yleng; literalbuf[literallen] = '\0';}static voidaddlitchar(unsigned char ychar){ /* enlarge buffer if needed */ if ((literallen+1) >= literalalloc) { literalalloc *= 2; literalbuf = (char *) repalloc(literalbuf, literalalloc); } /* append new data, add trailing null */ literalbuf[literallen] = ychar; literallen += 1; literalbuf[literallen] = '\0';}/* * One might be tempted to write pstrdup(literalbuf) instead of this, * but for long literals this is much faster because the length is * already known. */static char *litbufdup(void){ char *new; new = palloc(literallen + 1); memcpy(new, literalbuf, literallen+1); return new;}unsigned charunescape_single_char(unsigned char c){ switch (c) { case 'b': return '\b'; case 'f': return '\f'; case 'n': return '\n'; case 'r': return '\r'; case 't': return '\t'; default: return c; }}static voidcheck_escape_warning(void){ if (warn_on_first_escape && escape_string_warning) ereport(WARNING, (errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER), errmsg("nonstandard use of escape in a string literal"), errhint("Use the escape string syntax for escapes, e.g., E'\\r\\n'."), errposition(pg_err_position()))); warn_on_first_escape = false; /* warn only once per string */}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -