📄 gram.y
字号:
%{/********************************************************************** * gram.y - Parser for the PL/pgSQL * procedural language * * IDENTIFICATION * $Header: /usr/local/cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.4.2.1 1999/08/16 19:55:46 momjian 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 "stdio.h"#include "string.h"#include "plpgsql.h"#ifdef YYBISON#include "pl_scan.c" /* GNU bison wants it here */#endifstatic PLpgSQL_expr *read_sqlstmt(int until, char *s, char *sqlstart);static PLpgSQL_stmt *make_select_stmt(void);static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);%}%union { int32 ival; char *str; struct { char *name; int lineno; } varname; struct { int nalloc; int nused; int *dtnums; } dtlist; struct { int reverse; PLpgSQL_expr *expr; } forilow; struct { char *label; int n_initvars; int *initvarnos; } declhdr; PLpgSQL_type *dtype; PLpgSQL_var *var; PLpgSQL_row *row; PLpgSQL_rec *rec; PLpgSQL_recfield *recfield; PLpgSQL_trigarg *trigarg; PLpgSQL_expr *expr; PLpgSQL_stmt *stmt; PLpgSQL_stmts *stmts; PLpgSQL_stmt_block *program; PLpgSQL_nsitem *nsitem;}%type <declhdr> decl_sect%type <varname> decl_varname%type <str> decl_renname%type <ival> decl_const, decl_notnull, decl_atttypmod, decl_atttypmodval%type <expr> decl_defval%type <dtype> decl_datatype, decl_dtypename%type <row> decl_rowtype%type <nsitem> decl_aliasitem%type <str> decl_stmts, decl_stmt%type <expr> expr_until_semi, expr_until_then, expr_until_loop%type <expr> opt_exitcond%type <ival> assign_var%type <var> fori_var%type <varname> fori_varname%type <forilow> fori_lower%type <rec> fors_target%type <str> opt_lblname, opt_label%type <str> opt_exitlabel%type <str> execsql_start%type <stmts> proc_sect, proc_stmts, stmt_else, loop_body%type <stmt> proc_stmt, pl_block%type <stmt> stmt_assign, stmt_if, stmt_loop, stmt_while, stmt_exit%type <stmt> stmt_return, stmt_raise, stmt_execsql, stmt_fori%type <stmt> stmt_fors, stmt_select, stmt_perform%type <dtlist> raise_params%type <ival> raise_level, raise_param%type <str> raise_msg%type <ival> lno /* * Keyword tokens */%token K_ALIAS%token K_ASSIGN%token K_BEGIN%token K_CONSTANT%token K_DEBUG%token K_DECLARE%token K_DEFAULT%token K_DOTDOT%token K_ELSE%token K_END%token K_EXCEPTION%token K_EXIT%token K_FOR%token K_FROM%token K_IF%token K_IN%token K_INTO%token K_LOOP%token K_NOT%token K_NOTICE%token K_NULL%token K_PERFORM%token K_RAISE%token K_RECORD%token K_RENAME%token K_RETURN%token K_REVERSE%token K_SELECT%token K_THEN%token K_TO%token K_TYPE%token K_WHEN%token K_WHILE /* * Other tokens */%token T_FUNCTION%token T_TRIGGER%token T_CHAR%token T_BPCHAR%token T_VARCHAR%token T_LABEL%token T_STRING%token T_VARIABLE%token T_ROW%token T_ROWTYPE%token T_RECORD%token T_RECFIELD%token T_TGARGV%token T_DTYPE%token T_WORD%token T_NUMBER%token T_ERROR%token O_OPTION%token O_DUMP%%pl_function : T_FUNCTION comp_optsect pl_block { yylval.program = (PLpgSQL_stmt_block *)$3; } | T_TRIGGER comp_optsect pl_block { yylval.program = (PLpgSQL_stmt_block *)$3; } ;comp_optsect : | comp_options ;comp_options : comp_options comp_option | comp_option ;comp_option : O_OPTION O_DUMP { plpgsql_DumpExecTree = 1; } ;pl_block : decl_sect K_BEGIN lno proc_sect K_END ';' { PLpgSQL_stmt_block *new; new = malloc(sizeof(PLpgSQL_stmt_block)); memset(new, 0, sizeof(PLpgSQL_stmt_block)); new->cmd_type = PLPGSQL_STMT_BLOCK; new->lineno = $3; new->label = $1.label; new->n_initvars = $1.n_initvars; new->initvarnos = $1.initvarnos; new->body = $4; plpgsql_ns_pop(); $$ = (PLpgSQL_stmt *)new; } ;decl_sect : opt_label { plpgsql_ns_setlocal(false); $$.label = $1; $$.n_initvars = 0; $$.initvarnos = NULL; plpgsql_add_initdatums(NULL); } | opt_label decl_start { plpgsql_ns_setlocal(false); $$.label = $1; $$.n_initvars = 0; $$.initvarnos = NULL; plpgsql_add_initdatums(NULL); } | opt_label decl_start decl_stmts { plpgsql_ns_setlocal(false); if ($3 != NULL) { $$.label = $3; } else { $$.label = $1; } $$.n_initvars = plpgsql_add_initdatums(&($$.initvarnos)); } ;decl_start : K_DECLARE { plpgsql_ns_setlocal(true); } ;decl_stmts : decl_stmts decl_stmt { $$ = $2; } | decl_stmt { $$ = $1; } ;decl_stmt : '<' '<' opt_lblname '>' '>' { $$ = $3; } | K_DECLARE { $$ = NULL; } | decl_statement { $$ = NULL; } ;decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval { PLpgSQL_var *new; new = malloc(sizeof(PLpgSQL_var)); new->dtype = PLPGSQL_DTYPE_VAR; new->refname = $1.name; new->lineno = $1.lineno; new->datatype = $3; new->isconst = $2; new->notnull = $4; new->default_val = $5; plpgsql_adddatum((PLpgSQL_datum *)new); plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno, $1.name); } | decl_varname K_RECORD ';' { PLpgSQL_rec *new; new = malloc(sizeof(PLpgSQL_var)); new->dtype = PLPGSQL_DTYPE_REC; new->refname = $1.name; new->lineno = $1.lineno; plpgsql_adddatum((PLpgSQL_datum *)new); plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, new->recno, $1.name); } | decl_varname decl_rowtype ';' { $2->dtype = PLPGSQL_DTYPE_ROW; $2->refname = $1.name; $2->lineno = $1.lineno; plpgsql_adddatum((PLpgSQL_datum *)$2); plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW, $2->rowno, $1.name); } | decl_varname K_ALIAS K_FOR decl_aliasitem ';' { plpgsql_ns_additem($4->itemtype, $4->itemno, $1.name); } | K_RENAME decl_renname K_TO decl_renname ';' { plpgsql_ns_rename($2, $4); } ;decl_aliasitem : T_WORD { PLpgSQL_nsitem *nsi; char *name; plpgsql_ns_setlocal(false); name = plpgsql_tolower(yytext); if (name[0] != '$') { elog(ERROR, "can only alias positional parameters"); } nsi = plpgsql_ns_lookup(name, NULL); if (nsi == NULL) { elog(ERROR, "function has no parameter %s", name); } plpgsql_ns_setlocal(true); $$ = nsi; } ;decl_rowtype : T_ROW { $$ = yylval.row; } ;decl_varname : T_WORD { $$.name = strdup(yytext); $$.lineno = yylineno; } ;decl_renname : T_WORD { $$ = plpgsql_tolower(yytext); } ;decl_const : { $$ = 0; } | K_CONSTANT { $$ = 1; } ;decl_datatype : decl_dtypename { $$ = $1; } ;decl_dtypename : T_DTYPE { $$ = yylval.dtype; } | T_CHAR decl_atttypmod { if ($2 < 0) { plpgsql_parse_word("char"); $$ = yylval.dtype; } else { plpgsql_parse_word("bpchar"); $$ = yylval.dtype; $$->atttypmod = $2; } } | T_VARCHAR decl_atttypmod { plpgsql_parse_word("varchar"); $$ = yylval.dtype; $$->atttypmod = $2; } | T_BPCHAR '(' decl_atttypmodval ')' { plpgsql_parse_word("bpchar"); $$ = yylval.dtype; $$->atttypmod = $3; } ;decl_atttypmod : { $$ = -1; } | '(' decl_atttypmodval ')' { $$ = $2; } ;decl_atttypmodval : T_NUMBER { $$ = int2in(yytext) + VARHDRSZ; } ;decl_notnull : { $$ = 0; } | K_NOT K_NULL { $$ = 1; } ;decl_defval : ';' { $$ = NULL; } | decl_defkey { int tok; int lno; PLpgSQL_dstring ds; PLpgSQL_expr *expr; lno = yylineno; expr = malloc(sizeof(PLpgSQL_expr)); plpgsql_dstring_init(&ds); plpgsql_dstring_append(&ds, "SELECT "); expr->dtype = PLPGSQL_DTYPE_EXPR; expr->plan = NULL; expr->nparams = 0; tok = yylex(); switch (tok) { case 0: plpgsql_error_lineno = lno; plpgsql_comperrinfo(); elog(ERROR, "unexpected end of file"); case K_NULL: if (yylex() != ';') { plpgsql_error_lineno = lno; plpgsql_comperrinfo(); elog(ERROR, "expectec ; after NULL"); } free(expr); plpgsql_dstring_free(&ds); $$ = NULL; break; default: plpgsql_dstring_append(&ds, yytext); while ((tok = yylex()) != ';') { if (tok == 0) { plpgsql_error_lineno = lno; plpgsql_comperrinfo(); elog(ERROR, "unterminated default value"); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -