📄 scan.l
字号:
%{/********************************************************************** * scan.l - Scanner for the PL/pgSQL * procedural language * * IDENTIFICATION * $PostgreSQL: pgsql/src/pl/plpgsql/src/scan.l,v 1.42 2005/06/26 19:16:07 tgl Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * * The author hereby grants permission to use, copy, modify, * distribute, and license this software and its documentation * for any purpose, provided that existing copyright notices are * retained in all copies and that this notice is included * verbatim in any distributions. No written agreement, license, * or royalty fee is required for any of the authorized uses. * Modifications to this software may be copyrighted by their * author and need not follow the licensing terms described * here, provided that the new terms are clearly indicated on * the first page of each file where they apply. * * IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS * SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN * IF THE AUTHOR HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. * * THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON * AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAVE NO * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, * ENHANCEMENTS, OR MODIFICATIONS. * **********************************************************************/#include "plpgsql.h"#include "mb/pg_wchar.h"/* No reason to constrain amount of data slurped */#define YY_READ_BUF_SIZE 16777216/* Avoid exit() on fatal scanner errors (a bit ugly -- see yy_fatal_error) */#undef fprintf#define fprintf(file, fmt, msg) ereport(ERROR, (errmsg_internal("%s", msg)))/* Handles to the buffer that the lexer uses internally */static YY_BUFFER_STATE scanbufhandle;static char *scanbuf;static const char *scanstr; /* original input string */static int scanner_functype;static bool scanner_typereported;static int pushback_token;static bool have_pushback_token;static int lookahead_token; static bool have_lookahead_token;static const char *cur_line_start;static int cur_line_num;static char *dolqstart; /* current $foo$ quote start string */static int dolqlen; /* signal to plpgsql_get_string_value */bool plpgsql_SpaceScanned = false;%}%option 8bit%option never-interactive%option nodefault%option nounput%option noyywrap%option case-insensitive%x IN_STRING%x IN_COMMENT%x IN_DOLLARQUOTEdigit [0-9]ident_start [A-Za-z\200-\377_]ident_cont [A-Za-z\200-\377_0-9\$]quoted_ident (\"[^\"]*\")+identifier ({ident_start}{ident_cont}*|{quoted_ident})param \${digit}+space [ \t\n\r\f]/* $foo$ style quotes ("dollar quoting") * copied straight from the backend SQL parser */dolq_start [A-Za-z\200-\377_]dolq_cont [A-Za-z\200-\377_0-9]dolqdelim \$({dolq_start}{dolq_cont}*)?\$dolqinside [^$]+%% /* ---------- * Local variables in scanner to remember where * a string or comment started * ---------- */ int start_lineno = 0; char *start_charpos = NULL; /* ---------- * Reset the state when entering the scanner * ---------- */ BEGIN(INITIAL); plpgsql_SpaceScanned = false; /* ---------- * On the first call to a new source report the * function's type (T_FUNCTION or T_TRIGGER) * ---------- */ if (!scanner_typereported) { scanner_typereported = true; return scanner_functype; } /* ---------- * The keyword rules * ---------- */:= { return K_ASSIGN; }= { return K_ASSIGN; }\.\. { return K_DOTDOT; }alias { return K_ALIAS; }begin { return K_BEGIN; }close { return K_CLOSE; }constant { return K_CONSTANT; }continue { return K_CONTINUE; }cursor { return K_CURSOR; }debug { return K_DEBUG; }declare { return K_DECLARE; }default { return K_DEFAULT; }diagnostics { return K_DIAGNOSTICS; }else { return K_ELSE; }elseif { return K_ELSIF; }elsif { return K_ELSIF; }end { return K_END; }exception { return K_EXCEPTION; }execute { return K_EXECUTE; }exit { return K_EXIT; }fetch { return K_FETCH; }for { return K_FOR; }from { return K_FROM; }get { return K_GET; }if { return K_IF; }in { return K_IN; }info { return K_INFO; }into { return K_INTO; }is { return K_IS; }log { return K_LOG; }loop { return K_LOOP; }next { return K_NEXT; }not { return K_NOT; }notice { return K_NOTICE; }null { return K_NULL; }open { return K_OPEN; }or { return K_OR; }perform { return K_PERFORM; }raise { return K_RAISE; }rename { return K_RENAME; }result_oid { return K_RESULT_OID; }return { return K_RETURN; }reverse { return K_REVERSE; }row_count { return K_ROW_COUNT; }select { return K_SELECT; }then { return K_THEN; }to { return K_TO; }type { return K_TYPE; }warning { return K_WARNING; }when { return K_WHEN; }while { return K_WHILE; }^#option { return O_OPTION; }dump { return O_DUMP; } /* ---------- * Special word rules * * We set plpgsql_error_lineno in each rule so that errors reported * in the pl_comp.c subroutines will point to the right place. * ---------- */{identifier} { plpgsql_error_lineno = plpgsql_scanner_lineno(); return plpgsql_parse_word(yytext); }{identifier}{space}*\.{space}*{identifier} { plpgsql_error_lineno = plpgsql_scanner_lineno(); return plpgsql_parse_dblword(yytext); }{identifier}{space}*\.{space}*{identifier}{space}*\.{space}*{identifier} { plpgsql_error_lineno = plpgsql_scanner_lineno(); return plpgsql_parse_tripword(yytext); }{identifier}{space}*%TYPE { plpgsql_error_lineno = plpgsql_scanner_lineno(); return plpgsql_parse_wordtype(yytext); }{identifier}{space}*\.{space}*{identifier}{space}*%TYPE { plpgsql_error_lineno = plpgsql_scanner_lineno(); return plpgsql_parse_dblwordtype(yytext); }{identifier}{space}*\.{space}*{identifier}{space}*\.{space}*{identifier}{space}*%TYPE { plpgsql_error_lineno = plpgsql_scanner_lineno(); return plpgsql_parse_tripwordtype(yytext); }{identifier}{space}*%ROWTYPE { plpgsql_error_lineno = plpgsql_scanner_lineno(); return plpgsql_parse_wordrowtype(yytext); }{identifier}{space}*\.{space}*{identifier}{space}*%ROWTYPE { plpgsql_error_lineno = plpgsql_scanner_lineno(); return plpgsql_parse_dblwordrowtype(yytext); }{param} { plpgsql_error_lineno = plpgsql_scanner_lineno(); return plpgsql_parse_word(yytext); }{param}{space}*\.{space}*{identifier} { plpgsql_error_lineno = plpgsql_scanner_lineno(); return plpgsql_parse_dblword(yytext); }{param}{space}*\.{space}*{identifier}{space}*\.{space}*{identifier} { plpgsql_error_lineno = plpgsql_scanner_lineno(); return plpgsql_parse_tripword(yytext); }{param}{space}*%TYPE { plpgsql_error_lineno = plpgsql_scanner_lineno(); return plpgsql_parse_wordtype(yytext); }{param}{space}*\.{space}*{identifier}{space}*%TYPE { plpgsql_error_lineno = plpgsql_scanner_lineno(); return plpgsql_parse_dblwordtype(yytext); }{param}{space}*\.{space}*{identifier}{space}*\.{space}*{identifier}{space}*%TYPE { plpgsql_error_lineno = plpgsql_scanner_lineno(); return plpgsql_parse_tripwordtype(yytext); }{param}{space}*%ROWTYPE { plpgsql_error_lineno = plpgsql_scanner_lineno(); return plpgsql_parse_wordrowtype(yytext); }{param}{space}*\.{space}*{identifier}{space}*%ROWTYPE { plpgsql_error_lineno = plpgsql_scanner_lineno(); return plpgsql_parse_dblwordrowtype(yytext); }{digit}+ { return T_NUMBER; }\". { plpgsql_error_lineno = plpgsql_scanner_lineno(); ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("unterminated quoted identifier"))); } /* ---------- * Ignore whitespaces but remember this happened * ---------- */{space}+ { plpgsql_SpaceScanned = true; } /* ---------- * Eat up comments * ---------- */--[^\r\n]* ;\/\* { start_lineno = plpgsql_scanner_lineno(); BEGIN(IN_COMMENT); }<IN_COMMENT>\*\/ { BEGIN(INITIAL); plpgsql_SpaceScanned = true; }<IN_COMMENT>\n ;<IN_COMMENT>. ;<IN_COMMENT><<EOF>> { plpgsql_error_lineno = start_lineno; ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("unterminated comment"))); } /* ---------- * Collect anything inside of ''s and return one STRING token * * Hacking yytext/yyleng here lets us avoid using yymore(), which is * a win for performance. It's safe because we know the underlying * input buffer is not changing. * ---------- */' { start_lineno = plpgsql_scanner_lineno(); start_charpos = yytext; BEGIN(IN_STRING); }[eE]' { /* for now, treat the same as a regular literal */ start_lineno = plpgsql_scanner_lineno(); start_charpos = yytext; BEGIN(IN_STRING); }<IN_STRING>\\. { }<IN_STRING>\\ { /* can only happen with \ at EOF */ }<IN_STRING>'' { }<IN_STRING>' { /* tell plpgsql_get_string_value it's not a dollar quote */ dolqlen = 0; /* adjust yytext/yyleng to describe whole string token */ yyleng += (yytext - start_charpos); yytext = start_charpos; BEGIN(INITIAL); return T_STRING;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -