您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“PostgreSQL中的Rules有什么作用”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
Flex輸入文件由四部分組成:
%{ Declarations %} Definitions %% Rules %% User subroutines
在Flex的模式文件中,%%和%%之間的內(nèi)容被稱為規(guī)則(rules),每一行表示一條規(guī)則,每條規(guī)則由匹配模式(pattern)和 動作(action)組成。其中模式在前面,用正則表達(dá)式表示,動作在后面,即C代碼。每當(dāng)一個模式被匹配到時,后面的C代碼將被執(zhí)行。
Flex會將規(guī)則翻譯成名為yylex的函數(shù),該函數(shù)掃描輸入文件(默認(rèn)標(biāo)準(zhǔn)輸入),當(dāng)掃描到一個完整的、最長的、可以和某條規(guī)則的正則表達(dá)式所匹配的輸入時,函數(shù)會執(zhí)行此規(guī)則后面的C代碼。如果代碼中沒有return語句,則執(zhí)行完畢后,yylex會繼續(xù)運行,開始下一輪的掃描和匹配。注意:當(dāng)有多條規(guī)則的模式被匹配到時, yylex會優(yōu)先選擇匹配長度最長的那條規(guī)則,如果有匹配長度相等的規(guī)則,則選擇排在最前面的那條規(guī)則。
PG中的規(guī)則定義如下:
%% {whitespace} { //--------- 空白字符 //忽略,不作任何處理 /* ignore */ } {xcstart} { //--------- C風(fēng)格注釋 /* Set location in case of syntax error in comment */ //設(shè)置位置,以防注釋中的語法錯誤 SET_YYLLOC(); //深度 yyextra->xcdepth = 0; //進(jìn)入xc狀態(tài) BEGIN(xc); /* Put back any characters past slash-star; see above */ //把斜杠星后的字符放回去 // 注意:"/*"是2個字符,從位置2(偏移從0起算)開始把之后的字符放回去 yyless(2); } <xc>{xcstart} { //遇到下一層的注釋,深度+1 (yyextra->xcdepth)++; /* Put back any characters past slash-star; see above */ //類似的,把之后的字符放回去 yyless(2); } <xc>{xcstop} { //層次≤0,回到INITIAL狀態(tài),否則層次減1 if (yyextra->xcdepth <= 0) BEGIN(INITIAL); else (yyextra->xcdepth)--; } <xc>{xcinside} { //注釋里面的內(nèi)容,忽略 /* ignore */ } <xc>{op_chars} { //注釋里面的內(nèi)容,忽略 /* ignore */ } <xc>\*+ { //注釋里面的內(nèi)容,忽略 /* ignore */ } <xc><<EOF>> { yyerror("unterminated /* comment"); }//遇到結(jié)束符,出錯 {xbstart} { /* Binary bit type. * At some point we should simply pass the string * forward to the parser and label it there. * In the meantime, place a leading "b" on the string * to mark it for the input routine as a binary string. */ //--------- 二進(jìn)制位串 //在某些點上,我們應(yīng)該簡單的把字符串向前傳遞給解析器并標(biāo)記它 //在此期間,設(shè)置一個打頭的字符"b"以標(biāo)記該輸入為二進(jìn)制串 SET_YYLLOC(); BEGIN(xb); startlit(); addlitchar('b', yyscanner); } <xb>{quotestop} | <xb>{quotefail} { yyless(1); BEGIN(INITIAL); yylval->str = litbufdup(yyscanner); return BCONST; } <xh>{xhinside} | <xb>{xbinside} { addlit(yytext, yyleng, yyscanner); } <xh>{quotecontinue} | <xb>{quotecontinue} { /* ignore */ } <xb><<EOF>> { yyerror("unterminated bit string literal"); } {xhstart} { //------------- 十六進(jìn)制串 /* Hexadecimal bit type. * At some point we should simply pass the string * forward to the parser and label it there. * In the meantime, place a leading "x" on the string * to mark it for the input routine as a hex string. */ SET_YYLLOC(); BEGIN(xh); startlit(); addlitchar('x', yyscanner); } <xh>{quotestop} | <xh>{quotefail} { yyless(1); BEGIN(INITIAL); yylval->str = litbufdup(yyscanner); return XCONST; } <xh><<EOF>> { yyerror("unterminated hexadecimal string literal"); } {xnstart} { //------------- 國家字符 /* National character. * We will pass this along as a normal character string, * but preceded with an internally-generated "NCHAR". */ const ScanKeyword *keyword; SET_YYLLOC(); yyless(1); /* eat only 'n' this time */ keyword = ScanKeywordLookup("nchar", yyextra->keywords, yyextra->num_keywords); if (keyword != NULL) { yylval->keyword = keyword->name; return keyword->value; } else { /* If NCHAR isn't a keyword, just return "n" */ yylval->str = pstrdup("n"); return IDENT; } } {xqstart} { yyextra->warn_on_first_escape = true; yyextra->saw_non_ascii = false; SET_YYLLOC(); if (yyextra->standard_conforming_strings) BEGIN(xq); else BEGIN(xe); startlit(); } {xestart} { yyextra->warn_on_first_escape = false; yyextra->saw_non_ascii = false; SET_YYLLOC(); BEGIN(xe); startlit(); } {xusstart} { SET_YYLLOC(); if (!yyextra->standard_conforming_strings) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("unsafe use of string constant with Unicode escapes"), errdetail("String constants with Unicode escapes cannot be used when standard_conforming_strings is off."), lexer_errposition())); BEGIN(xus); startlit(); } <xq,xe>{quotestop} | <xq,xe>{quotefail} { yyless(1); BEGIN(INITIAL); /* * check that the data remains valid if it might have been * made invalid by unescaping any chars. */ if (yyextra->saw_non_ascii) pg_verifymbstr(yyextra->literalbuf, yyextra->literallen, false); yylval->str = litbufdup(yyscanner); return SCONST; } <xus>{quotestop} | <xus>{quotefail} { /* throw back all but the quote */ yyless(1); /* xusend state looks for possible UESCAPE */ BEGIN(xusend); } <xusend>{whitespace} { /* stay in xusend state over whitespace */ } <xusend><<EOF>> | <xusend>{other} | <xusend>{xustop1} { /* no UESCAPE after the quote, throw back everything */ yyless(0); BEGIN(INITIAL); yylval->str = litbuf_udeescape('\\', yyscanner); return SCONST; } <xusend>{xustop2} { /* found UESCAPE after the end quote */ BEGIN(INITIAL); if (!check_uescapechar(yytext[yyleng - 2])) { SET_YYLLOC(); ADVANCE_YYLLOC(yyleng - 2); yyerror("invalid Unicode escape character"); } yylval->str = litbuf_udeescape(yytext[yyleng - 2], yyscanner); return SCONST; } <xq,xe,xus>{xqdouble} { addlitchar('\'', yyscanner); } <xq,xus>{xqinside} { addlit(yytext, yyleng, yyscanner); } <xe>{xeinside} { addlit(yytext, yyleng, yyscanner); } <xe>{xeunicode} { pg_wchar c = strtoul(yytext + 2, NULL, 16); check_escape_warning(yyscanner); if (is_utf16_surrogate_first(c)) { yyextra->utf16_first_part = c; BEGIN(xeu); } else if (is_utf16_surrogate_second(c)) yyerror("invalid Unicode surrogate pair"); else addunicode(c, yyscanner); } <xeu>{xeunicode} { pg_wchar c = strtoul(yytext + 2, NULL, 16); if (!is_utf16_surrogate_second(c)) yyerror("invalid Unicode surrogate pair"); c = surrogate_pair_to_codepoint(yyextra->utf16_first_part, c); addunicode(c, yyscanner); BEGIN(xe); } <xeu>. { yyerror("invalid Unicode surrogate pair"); } <xeu>\n { yyerror("invalid Unicode surrogate pair"); } <xeu><<EOF>> { yyerror("invalid Unicode surrogate pair"); } <xe,xeu>{xeunicodefail} { ereport(ERROR, (errcode(ERRCODE_INVALID_ESCAPE_SEQUENCE), errmsg("invalid Unicode escape"), errhint("Unicode escapes must be \\uXXXX or \\UXXXXXXXX."), lexer_errposition())); } <xe>{xeescape} { if (yytext[1] == '\'') { if (yyextra->backslash_quote == BACKSLASH_QUOTE_OFF || (yyextra->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."), lexer_errposition())); } check_string_escape_warning(yytext[1], yyscanner); addlitchar(unescape_single_char(yytext[1], yyscanner), yyscanner); } <xe>{xeoctesc} { unsigned char c = strtoul(yytext + 1, NULL, 8); check_escape_warning(yyscanner); addlitchar(c, yyscanner); if (c == '\0' || IS_HIGHBIT_SET(c)) yyextra->saw_non_ascii = true; } <xe>{xehexesc} { unsigned char c = strtoul(yytext + 2, NULL, 16); check_escape_warning(yyscanner); addlitchar(c, yyscanner); if (c == '\0' || IS_HIGHBIT_SET(c)) yyextra->saw_non_ascii = true; } <xq,xe,xus>{quotecontinue} { /* ignore */ } <xe>. { /* This is only needed for \ just before EOF */ addlitchar(yytext[0], yyscanner); } <xq,xe,xus><<EOF>> { yyerror("unterminated quoted string"); } {dolqdelim} { SET_YYLLOC(); yyextra->dolqstart = pstrdup(yytext); BEGIN(xdolq); startlit(); } {dolqfailed} { SET_YYLLOC(); /* throw back all but the initial "$" */ yyless(1); /* and treat it as {other} */ return yytext[0]; } <xdolq>{dolqdelim} { if (strcmp(yytext, yyextra->dolqstart) == 0) { pfree(yyextra->dolqstart); yyextra->dolqstart = NULL; BEGIN(INITIAL); yylval->str = litbufdup(yyscanner); 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, yyscanner); yyless(yyleng - 1); } } <xdolq>{dolqinside} { addlit(yytext, yyleng, yyscanner); } <xdolq>{dolqfailed} { addlit(yytext, yyleng, yyscanner); } <xdolq>. { /* This is only needed for $ inside the quoted text */ addlitchar(yytext[0], yyscanner); } <xdolq><<EOF>> { yyerror("unterminated dollar-quoted string"); } {xdstart} { SET_YYLLOC(); BEGIN(xd); startlit(); } {xuistart} { SET_YYLLOC(); BEGIN(xui); startlit(); } <xd>{xdstop} { char *ident; BEGIN(INITIAL); if (yyextra->literallen == 0) yyerror("zero-length delimited identifier"); ident = litbufdup(yyscanner); if (yyextra->literallen >= NAMEDATALEN) truncate_identifier(ident, yyextra->literallen, true); yylval->str = ident; return IDENT; } <xui>{dquote} { yyless(1); /* xuiend state looks for possible UESCAPE */ BEGIN(xuiend); } <xuiend>{whitespace} { /* stay in xuiend state over whitespace */ } <xuiend><<EOF>> | <xuiend>{other} | <xuiend>{xustop1} { /* no UESCAPE after the quote, throw back everything */ char *ident; int identlen; yyless(0); BEGIN(INITIAL); if (yyextra->literallen == 0) yyerror("zero-length delimited identifier"); ident = litbuf_udeescape('\\', yyscanner); identlen = strlen(ident); if (identlen >= NAMEDATALEN) truncate_identifier(ident, identlen, true); yylval->str = ident; return IDENT; } <xuiend>{xustop2} { /* found UESCAPE after the end quote */ char *ident; int identlen; BEGIN(INITIAL); if (yyextra->literallen == 0) yyerror("zero-length delimited identifier"); if (!check_uescapechar(yytext[yyleng - 2])) { SET_YYLLOC(); ADVANCE_YYLLOC(yyleng - 2); yyerror("invalid Unicode escape character"); } ident = litbuf_udeescape(yytext[yyleng - 2], yyscanner); identlen = strlen(ident); if (identlen >= NAMEDATALEN) truncate_identifier(ident, identlen, true); yylval->str = ident; return IDENT; } <xd,xui>{xddouble} { addlitchar('"', yyscanner); } <xd,xui>{xdinside} { addlit(yytext, yyleng, yyscanner); } <xd,xui><<EOF>> { yyerror("unterminated quoted identifier"); } {xufailed} { char *ident; SET_YYLLOC(); /* throw back all but the initial u/U */ yyless(1); /* and treat it as {identifier} */ ident = downcase_truncate_identifier(yytext, yyleng, true); yylval->str = ident; return IDENT; } {typecast} { SET_YYLLOC(); return TYPECAST; } {dot_dot} { SET_YYLLOC(); return DOT_DOT; } {colon_equals} { SET_YYLLOC(); return COLON_EQUALS; } {equals_greater} { SET_YYLLOC(); return EQUALS_GREATER; } {less_equals} { SET_YYLLOC(); return LESS_EQUALS; } {greater_equals} { SET_YYLLOC(); return GREATER_EQUALS; } {less_greater} { /* We accept both "<>" and "!=" as meaning NOT_EQUALS */ SET_YYLLOC(); return NOT_EQUALS; } {not_equals} { /* We accept both "<>" and "!=" as meaning NOT_EQUALS */ SET_YYLLOC(); return NOT_EQUALS; } {self} { SET_YYLLOC(); 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. */ if (nchars > 1 && (yytext[nchars - 1] == '+' || yytext[nchars - 1] == '-')) { int ic; for (ic = nchars - 2; ic >= 0; ic--) { char c = yytext[ic]; if (c == '~' || c == '!' || c == '@' || c == '#' || c == '^' || c == '&' || c == '|' || c == '`' || c == '?' || c == '%') break; } if (ic < 0) { /* * didn't find a qualifying character, so remove * all trailing [+-] */ do { nchars--; } while (nchars > 1 && (yytext[nchars - 1] == '+' || yytext[nchars - 1] == '-')); } } SET_YYLLOC(); 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]; /* * Likewise, if what we have left is two chars, and * those match the tokens ">=", "<=", "=>", "<>" or * "!=", then we must return the appropriate token * rather than the generic Op. */ if (nchars == 2) { if (yytext[0] == '=' && yytext[1] == '>') return EQUALS_GREATER; if (yytext[0] == '>' && yytext[1] == '=') return GREATER_EQUALS; if (yytext[0] == '<' && yytext[1] == '=') return LESS_EQUALS; if (yytext[0] == '<' && yytext[1] == '>') return NOT_EQUALS; if (yytext[0] == '!' && yytext[1] == '=') return NOT_EQUALS; } } /* * 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"); yylval->str = pstrdup(yytext); return Op; } {param} { SET_YYLLOC(); yylval->ival = atol(yytext + 1); return PARAM; } {integer} { SET_YYLLOC(); return process_integer_literal(yytext, yylval); } {decimal} { SET_YYLLOC(); yylval->str = pstrdup(yytext); return FCONST; } {decimalfail} { /* throw back the .., and treat as integer */ yyless(yyleng - 2); SET_YYLLOC(); return process_integer_literal(yytext, yylval); } {real} { SET_YYLLOC(); 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); SET_YYLLOC(); yylval->str = pstrdup(yytext); return FCONST; } {realfail2} { /* throw back the [Ee][+-], and proceed as above */ yyless(yyleng - 2); SET_YYLLOC(); yylval->str = pstrdup(yytext); return FCONST; } {identifier} { //---------- 標(biāo)識符 const ScanKeyword *keyword; char *ident; SET_YYLLOC(); /* Is it a keyword? */ //是否關(guān)鍵字? keyword = ScanKeywordLookup(yytext, yyextra->keywords, yyextra->num_keywords); if (keyword != NULL) { //是,則返回關(guān)鍵字值 yylval->keyword = keyword->name; return keyword->value; } /* * No. Convert the identifier to lower case, and truncate * if necessary. */ //如果不是關(guān)鍵字,則設(shè)置為小寫字母,如需要則截斷 ident = downcase_truncate_identifier(yytext, yyleng, true); yylval->str = ident; return IDENT; } {other} { SET_YYLLOC(); return yytext[0]; } <<EOF>> { SET_YYLLOC(); yyterminate(); } %%
“PostgreSQL中的Rules有什么作用”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。