📄 gram.y
字号:
if (plpgsql_SpaceScanned) { plpgsql_dstring_append(&ds, " "); } plpgsql_dstring_append(&ds, yytext); } expr->query = strdup(plpgsql_dstring_get(&ds)); plpgsql_dstring_free(&ds); $$ = expr; break; } } ;decl_defkey : K_ASSIGN | K_DEFAULTproc_sect : { PLpgSQL_stmts *new; new = malloc(sizeof(PLpgSQL_stmts)); memset(new, 0, sizeof(PLpgSQL_stmts)); $$ = new; } | proc_stmts { $$ = $1; } ;proc_stmts : proc_stmts proc_stmt { if ($1->stmts_used == $1->stmts_alloc) { $1->stmts_alloc *= 2; $1->stmts = realloc($1->stmts, sizeof(PLpgSQL_stmt *) * $1->stmts_alloc); } $1->stmts[$1->stmts_used++] = (struct PLpgSQL_stmt *)$2; $$ = $1; } | proc_stmt { PLpgSQL_stmts *new; new = malloc(sizeof(PLpgSQL_stmts)); memset(new, 0, sizeof(PLpgSQL_stmts)); new->stmts_alloc = 64; new->stmts_used = 1; new->stmts = malloc(sizeof(PLpgSQL_stmt *) * new->stmts_alloc); new->stmts[0] = (struct PLpgSQL_stmt *)$1; $$ = new; } ;proc_stmt : pl_block { $$ = $1; } | stmt_assign { $$ = $1; } | stmt_if { $$ = $1; } | stmt_loop { $$ = $1; } | stmt_while { $$ = $1; } | stmt_fori { $$ = $1; } | stmt_fors { $$ = $1; } | stmt_select { $$ = $1; } | stmt_exit { $$ = $1; } | stmt_return { $$ = $1; } | stmt_raise { $$ = $1; } | stmt_execsql { $$ = $1; } | stmt_perform { $$ = $1; } ;stmt_perform : K_PERFORM lno expr_until_semi { PLpgSQL_stmt_assign *new; new = malloc(sizeof(PLpgSQL_stmt_assign)); memset(new, 0, sizeof(PLpgSQL_stmt_assign)); new->cmd_type = PLPGSQL_STMT_ASSIGN; new->lineno = $2; new->varno = -1; new->expr = $3; $$ = (PLpgSQL_stmt *)new; } ;stmt_assign : assign_var lno K_ASSIGN expr_until_semi { PLpgSQL_stmt_assign *new; new = malloc(sizeof(PLpgSQL_stmt_assign)); memset(new, 0, sizeof(PLpgSQL_stmt_assign)); new->cmd_type = PLPGSQL_STMT_ASSIGN; new->lineno = $2; new->varno = $1; new->expr = $4; $$ = (PLpgSQL_stmt *)new; } ;assign_var : T_VARIABLE { if (yylval.var->isconst) { plpgsql_comperrinfo(); elog(ERROR, "%s is declared CONSTANT", yylval.var->refname); } $$ = yylval.var->varno; } | T_RECFIELD { $$ = yylval.recfield->rfno; } ;stmt_if : K_IF lno expr_until_then proc_sect stmt_else K_END K_IF ';' { PLpgSQL_stmt_if *new; new = malloc(sizeof(PLpgSQL_stmt_if)); memset(new, 0, sizeof(PLpgSQL_stmt_if)); new->cmd_type = PLPGSQL_STMT_IF; new->lineno = $2; new->cond = $3; new->true_body = $4; new->false_body = $5; $$ = (PLpgSQL_stmt *)new; } ;stmt_else : { PLpgSQL_stmts *new; new = malloc(sizeof(PLpgSQL_stmts)); memset(new, 0, sizeof(PLpgSQL_stmts)); $$ = new; } | K_ELSE proc_sect { $$ = $2; } ;stmt_loop : opt_label K_LOOP lno loop_body { PLpgSQL_stmt_loop *new; new = malloc(sizeof(PLpgSQL_stmt_loop)); memset(new, 0, sizeof(PLpgSQL_stmt_loop)); new->cmd_type = PLPGSQL_STMT_LOOP; new->lineno = $3; new->label = $1; new->body = $4; plpgsql_ns_pop(); $$ = (PLpgSQL_stmt *)new; } ;stmt_while : opt_label K_WHILE lno expr_until_loop loop_body { PLpgSQL_stmt_while *new; new = malloc(sizeof(PLpgSQL_stmt_while)); memset(new, 0, sizeof(PLpgSQL_stmt_while)); new->cmd_type = PLPGSQL_STMT_WHILE; new->lineno = $3; new->label = $1; new->cond = $4; new->body = $5; plpgsql_ns_pop(); $$ = (PLpgSQL_stmt *)new; } ;stmt_fori : opt_label K_FOR lno fori_var K_IN fori_lower expr_until_loop loop_body { PLpgSQL_stmt_fori *new; new = malloc(sizeof(PLpgSQL_stmt_fori)); memset(new, 0, sizeof(PLpgSQL_stmt_fori)); new->cmd_type = PLPGSQL_STMT_FORI; new->lineno = $3; new->label = $1; new->var = $4; new->reverse = $6.reverse; new->lower = $6.expr; new->upper = $7; new->body = $8; plpgsql_ns_pop(); $$ = (PLpgSQL_stmt *)new; } ;fori_var : fori_varname { PLpgSQL_var *new; new = malloc(sizeof(PLpgSQL_var)); new->dtype = PLPGSQL_DTYPE_VAR; new->refname = $1.name; new->lineno = $1.lineno; plpgsql_parse_word("integer"); new->datatype = yylval.dtype; new->isconst = false; new->notnull = false; new->default_val = NULL; plpgsql_adddatum((PLpgSQL_datum *)new); plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno, $1.name); plpgsql_add_initdatums(NULL); $$ = new; } ;fori_varname : T_VARIABLE { $$.name = strdup(yytext); $$.lineno = yylineno; } | T_WORD { $$.name = strdup(yytext); $$.lineno = yylineno; } ;fori_lower : { int tok; int lno; PLpgSQL_dstring ds; int nparams = 0; int params[1024]; char buf[32]; PLpgSQL_expr *expr; int firsttok = 1; lno = yylineno; plpgsql_dstring_init(&ds); plpgsql_dstring_append(&ds, "SELECT "); $$.reverse = 0; while((tok = yylex()) != K_DOTDOT) { if (firsttok) { firsttok = 0; if (tok == K_REVERSE) { $$.reverse = 1; continue; } } if (tok == ';') break; if (plpgsql_SpaceScanned) { plpgsql_dstring_append(&ds, " "); } switch (tok) { case T_VARIABLE: params[nparams] = yylval.var->varno; sprintf(buf, "$%d", ++nparams); plpgsql_dstring_append(&ds, buf); break; case T_RECFIELD: params[nparams] = yylval.recfield->rfno; sprintf(buf, "$%d", ++nparams); plpgsql_dstring_append(&ds, buf); break; case T_TGARGV: params[nparams] = yylval.trigarg->dno; sprintf(buf, "$%d", ++nparams); plpgsql_dstring_append(&ds, buf); break; default: if (tok == 0) { plpgsql_error_lineno = lno; plpgsql_comperrinfo(); elog(ERROR, "missing .. to terminate lower bound of for loop"); } plpgsql_dstring_append(&ds, yytext); break; } } expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - 1); expr->dtype = PLPGSQL_DTYPE_EXPR; expr->query = strdup(plpgsql_dstring_get(&ds)); expr->plan = NULL; expr->nparams = nparams; while(nparams-- > 0) { expr->params[nparams] = params[nparams]; } plpgsql_dstring_free(&ds); $$.expr = expr; }stmt_fors : opt_label K_FOR lno fors_target K_IN K_SELECT expr_until_loop loop_body { PLpgSQL_stmt_fors *new; new = malloc(sizeof(PLpgSQL_stmt_fors)); memset(new, 0, sizeof(PLpgSQL_stmt_fors)); new->cmd_type = PLPGSQL_STMT_FORS; new->lineno = $3; new->label = $1; switch ($4->dtype) { case PLPGSQL_DTYPE_REC: new->rec = $4; break; case PLPGSQL_DTYPE_ROW: new->row = (PLpgSQL_row *)$4; break; default: plpgsql_comperrinfo(); elog(ERROR, "unknown dtype %d in stmt_fors", $4->dtype); } new->query = $7; new->body = $8; plpgsql_ns_pop(); $$ = (PLpgSQL_stmt *)new; }fors_target : T_RECORD { $$ = yylval.rec; } | T_ROW { $$ = (PLpgSQL_rec *)(yylval.row); } ;stmt_select : K_SELECT lno { $$ = make_select_stmt(); $$->lineno = $2; } ;stmt_exit : K_EXIT lno opt_exitlabel opt_exitcond { PLpgSQL_stmt_exit *new; new = malloc(sizeof(PLpgSQL_stmt_exit)); memset(new, 0, sizeof(PLpgSQL_stmt_exit)); new->cmd_type = PLPGSQL_STMT_EXIT; new->lineno = $2; new->label = $3; new->cond = $4; $$ = (PLpgSQL_stmt *)new; } ;stmt_return : K_RETURN lno { PLpgSQL_stmt_return *new; PLpgSQL_expr *expr = NULL; int tok; new = malloc(sizeof(PLpgSQL_stmt_return)); memset(new, 0, sizeof(PLpgSQL_stmt_return)); if (plpgsql_curr_compile->fn_retistuple) { new->retistuple = true; new->retrecno = -1; switch (tok = yylex()) { case K_NULL: expr = NULL; break; case T_ROW: expr = make_tupret_expr(yylval.row); break; case T_RECORD: new->retrecno = yylval.rec->recno; expr = NULL; break; default: yyerror("return type mismatch in function returning table row"); break; } if (yylex() != ';') { yyerror("expected ';'"); } } else { new->retistuple = false; expr = plpgsql_read_expression(';', ";"); } new->cmd_type = PLPGSQL_STMT_RETURN; new->lineno = $2; new->expr = expr; $$ = (PLpgSQL_stmt *)new; } ;stmt_raise : K_RAISE lno raise_level raise_msg raise_params ';' { PLpgSQL_stmt_raise *new; new = malloc(sizeof(PLpgSQL_stmt_raise)); new->cmd_type = PLPGSQL_STMT_RAISE; new->lineno = $2; new->elog_level = $3; new->message = $4; new->nparams = $5.nused; new->params = malloc(sizeof(int) * $5.nused); memcpy(new->params, $5.dtnums, sizeof(int) * $5.nused); $$ = (PLpgSQL_stmt *)new; } | K_RAISE lno raise_level raise_msg ';' { PLpgSQL_stmt_raise *new; new = malloc(sizeof(PLpgSQL_stmt_raise)); new->cmd_type = PLPGSQL_STMT_RAISE; new->lineno = $2; new->elog_level = $3; new->message = $4; new->nparams = 0; new->params = NULL; $$ = (PLpgSQL_stmt *)new; } ;raise_msg : T_STRING { $$ = strdup(yytext); } ;raise_level : K_EXCEPTION { $$ = ERROR; } | K_NOTICE { $$ = NOTICE; } | K_DEBUG { $$ = DEBUG; } ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -