⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scan.l

📁 PostgreSQL7.4.6 for Linux
💻 L
字号:
%{/********************************************************************** * scan.l		- Scanner for the PL/pgSQL *			  procedural language * * IDENTIFICATION *    $Header: /cvsroot/pgsql/src/pl/plpgsql/src/scan.l,v 1.29 2003/07/25 23:37:29 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"/* 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) */#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 int	scanner_functype;static int	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;int	plpgsql_SpaceScanned = 0;%}%option 8bit%option never-interactive%option nounput%option noyywrap%option case-insensitive%x	IN_STRING IN_COMMENTdigit			[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]%%    /* ----------     * 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 = 0;    /* ----------     * On the first call to a new source report the     * functions type (T_FUNCTION or T_TRIGGER)     * ----------     */	if (!scanner_typereported)	{		scanner_typereported = 1;		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;		}cursor			{ return K_CURSOR;			}debug			{ return K_DEBUG;			}declare			{ return K_DECLARE;			}default			{ return K_DEFAULT;			}diagnostics		{ return K_DIAGNOSTICS;		}else			{ return K_ELSE;			}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;			}perform			{ return K_PERFORM;			}raise			{ return K_RAISE;			}record			{ return K_RECORD;			}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 = 1;		}    /* ----------     * Eat up comments     * ----------     */--[^\r\n]*		;\/\*			{ start_lineno = plpgsql_scanner_lineno();			  BEGIN IN_COMMENT;			}<IN_COMMENT>\*\/	{ BEGIN INITIAL; plpgsql_SpaceScanned = 1; }<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	 *	 * 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;			}<IN_STRING>\\.		{ }<IN_STRING>''		{ }<IN_STRING>'		{			  yyleng -= (yytext - start_charpos);			  yytext = start_charpos;			  BEGIN INITIAL;			  return T_STRING;			}<IN_STRING><<EOF>>	{				plpgsql_error_lineno = start_lineno;				ereport(ERROR,						(errcode(ERRCODE_DATATYPE_MISMATCH),						 errmsg("unterminated string")));			}<IN_STRING>[^'\\]*	{ }    /* ----------     * Any unmatched character is returned as is     * ----------     */.			{ return yytext[0];			}%%/* * This is the yylex routine called from outside. It exists to provide * a pushback facility, as well as to allow us to parse syntax that * requires more than one token of lookahead. */intplpgsql_yylex(void){	int cur_token;	if (have_pushback_token)	{		have_pushback_token = false;		cur_token = pushback_token;	}	else if (have_lookahead_token)	{		have_lookahead_token = false;		cur_token = lookahead_token;	}	else		cur_token = yylex();	/* Do we need to look ahead for a possible multiword token? */	switch (cur_token)	{		/* RETURN NEXT must be reduced to a single token */		case K_RETURN:			if (!have_lookahead_token)			{				lookahead_token = yylex();				have_lookahead_token = true;			}			if (lookahead_token == K_NEXT)			{				have_lookahead_token = false;				cur_token = K_RETURN_NEXT;			}			break;		default:			break;	}	return cur_token;}/* * Push back a single token to be re-read by next plpgsql_yylex() call. */voidplpgsql_push_back_token(int token){	if (have_pushback_token)		elog(ERROR, "cannot push back multiple tokens");	pushback_token = token;	have_pushback_token = true;}/* * Get the line number at which the current token ends.  This substitutes * for flex's very poorly implemented yylineno facility. * * We assume that flex has written a '\0' over the character following the * current token in scanbuf.  So, we just have to count the '\n' characters * before that.  We optimize this a little by keeping track of the last * '\n' seen so far. */intplpgsql_scanner_lineno(void){	const char *c;	while ((c = strchr(cur_line_start, '\n')) != NULL)	{		cur_line_start = c + 1;		cur_line_num++;	}	return cur_line_num;}/* * Called before any actual parsing is done */voidplpgsql_scanner_init(const char *str, int functype){	Size	slen;	/*----------	 * Hack: skip any initial newline, so that in the common coding layout	 *		CREATE FUNCTION ... AS '	 *			code body	 *		' LANGUAGE 'plpgsql';	 * we will think "line 1" is what the programmer thinks of as line 1.	 *----------	 */    if (*str == '\r')        str++;    if (*str == '\n')        str++;	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);	/* Other setup */    scanner_functype     = functype;    scanner_typereported = 0;	have_pushback_token = false;	have_lookahead_token = false;	cur_line_start = scanbuf;	cur_line_num = 1;	BEGIN(INITIAL);}/* * Called after parsing is done to clean up after plpgsql_scanner_init() */voidplpgsql_scanner_finish(void){	yy_delete_buffer(scanbufhandle);	pfree(scanbuf);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -