📄 pgc.l
字号:
<xe>{xehexesc} { addlit(yytext, yyleng); }<xq,xqc,xe,xn>{quotecontinue} { /* ignore */ }<xe>. { /* This is only needed for \ just before EOF */ addlitchar(yytext[0]); }<xq,xqc,xe,xn><<EOF>> { mmerror(PARSE_ERROR, ET_FATAL, "Unterminated quoted string"); }<SQL>{dolqfailed} { /* throw back all but the initial "$" */ yyless(1); /* and treat it as {other} */ return yytext[0]; }<SQL>{dolqdelim} { token_start = yytext; dolqstart = mm_strdup(yytext); BEGIN(xdolq); startlit(); addlit(yytext, yyleng); }<xdolq>{dolqdelim} { if (strcmp(yytext, dolqstart) == 0) { addlit(yytext, yyleng); free(dolqstart); BEGIN(SQL); yylval.str = mm_strdup(literalbuf); return DOLCONST; } 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); yyless(yyleng-1); } }<xdolq>{dolqinside} { addlit(yytext, yyleng); }<xdolq>{dolqfailed} { addlit(yytext, yyleng); }<xdolq>{other} { /* single quote or dollar sign */ addlitchar(yytext[0]); }<xdolq><<EOF>> { base_yyerror("unterminated dollar-quoted string"); }<SQL>{xdstart} { state_before = YYSTATE; BEGIN(xd); startlit(); }<xd>{xdstop} { BEGIN(state_before); if (literallen == 0) mmerror(PARSE_ERROR, ET_ERROR, "zero-length delimited identifier"); /* The backend will truncate the idnetifier here. We do not as it does not change the result. */ yylval.str = mm_strdup(literalbuf); return CSTRING; }<xdc>{xdstop} { BEGIN(state_before); yylval.str = mm_strdup(literalbuf); return CSTRING; }<xd>{xddouble} { addlitchar('"'); }<xd>{xdinside} { addlit(yytext, yyleng); }<xd,xdc><<EOF>> { mmerror(PARSE_ERROR, ET_FATAL, "Unterminated quoted identifier"); }<C,SQL>{xdstart} { state_before = YYSTATE; BEGIN(xdc); startlit(); }<xdc>{xdcinside} { addlit(yytext, yyleng); }<SQL>{typecast} { return TYPECAST; }<SQL>{informix_special} { /* are we simulating Informix? */ if (INFORMIX_MODE) { unput(':'); } else return yytext[0]; }<SQL>{self} { /* * We may find a ';' inside a structure * definition in a TYPE or VAR statement. * This is not an EOL marker. */ if (yytext[0] == ';' && struct_level == 0) BEGIN(C); return yytext[0]; }<SQL>{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. */ while (nchars > 1 && (yytext[nchars-1] == '+' || yytext[nchars-1] == '-')) { int ic; for (ic = nchars-2; ic >= 0; ic--) { if (strchr("~!@#^&|`?%", yytext[ic])) break; } if (ic >= 0) break; /* found a char that makes it OK */ nchars--; /* else remove the +/-, and check again */ } 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]; } /* Convert "!=" operator to "<>" for compatibility */ if (strcmp(yytext, "!=") == 0) yylval.str = mm_strdup("<>"); else yylval.str = mm_strdup(yytext); return Op; }<SQL>{param} { yylval.ival = atol(yytext+1); return PARAM; }<C,SQL>{integer} { long val; char* endptr; errno = 0; val = strtol((char *)yytext, &endptr,10); if (*endptr != '\0' || errno == ERANGE#ifdef HAVE_LONG_INT_64 /* if long > 32 bits, check for overflow of int4 */ || val != (long) ((int32) val)#endif ) { errno = 0; yylval.str = mm_strdup(yytext); return FCONST; } yylval.ival = val; return ICONST; }<SQL>{ip} { yylval.str = mm_strdup(yytext); return IP; }<C,SQL>{decimal} { yylval.str = mm_strdup(yytext); return FCONST; }<C,SQL>{real} { yylval.str = mm_strdup(yytext); return FCONST; }<SQL>{realfail1} { yyless(yyleng-1); yylval.str = mm_strdup(yytext); return FCONST; }<SQL>{realfail2} { yyless(yyleng-2); yylval.str = mm_strdup(yytext); return FCONST; }<SQL>:{identifier}((("->"|\.){identifier})|(\[{array}\]))* { yylval.str = mm_strdup(yytext+1); return(CVARIABLE); }<SQL>{identifier} { const ScanKeyword *keyword; if (!isdefine()) { /* Is it an SQL/ECPG keyword? */ keyword = ScanKeywordLookup(yytext); if (keyword != NULL) return keyword->value; /* Is it a C keyword? */ keyword = ScanCKeywordLookup(yytext); if (keyword != NULL) return keyword->value; /* * None of the above. Return it as an identifier. * * The backend will attempt to truncate and case-fold * the identifier, but I see no good reason for ecpg * to do so; that's just another way that ecpg could get * out of step with the backend. */ yylval.str = mm_strdup(yytext); return IDENT; } }<SQL>{other} { return yytext[0]; }<C>{exec_sql} { BEGIN(SQL); return SQL_START; }<C>{informix_special} { /* are we simulating Informix? */ if (INFORMIX_MODE) { BEGIN(SQL); return SQL_START; } else return S_ANYTHING; }<C>{ccomment} { ECHO; }<C>{xch} { char* endptr; errno = 0; yylval.ival = strtoul((char *)yytext,&endptr,16); if (*endptr != '\0' || errno == ERANGE) { errno = 0; yylval.str = mm_strdup(yytext); return SCONST; } return ICONST; }<C>{cppinclude} { if (system_includes) { BEGIN(incl); } else { yylval.str = mm_strdup(yytext); return(CPP_LINE); } }<C,SQL>{cppline} { yylval.str = mm_strdup(yytext); return(CPP_LINE); }<C>{identifier} { const ScanKeyword *keyword; /* Informix uses SQL defines only in SQL space */ /* however, some defines have to be taken care of for compatibility */ if ((!INFORMIX_MODE || !isinformixdefine()) && !isdefine()) { keyword = ScanCKeywordLookup(yytext); if (keyword != NULL) return keyword->value; else { yylval.str = mm_strdup(yytext); return IDENT; } } }<C>":" { return(':'); }<C>";" { return(';'); }<C>"," { return(','); }<C>"*" { return('*'); }<C>"%" { return('%'); }<C>"/" { return('/'); }<C>"+" { return('+'); }<C>"-" { return('-'); }<C>"(" { return('('); }<C>")" { return(')'); }<C,xskip>{space} { ECHO; }<C>\{ { return('{'); }<C>\} { return('}'); }<C>\[ { return('['); }<C>\] { return(']'); }<C>\= { return('='); }<C>"->" { return(S_MEMBER); }<C>">>" { return(S_RSHIFT); }<C>"<<" { return(S_LSHIFT); }<C>"||" { return(S_OR); }<C>"&&" { return(S_AND); }<C>"++" { return(S_INC); }<C>"--" { return(S_DEC); }<C>"==" { return(S_EQUAL); }<C>"!=" { return(S_NEQUAL); }<C>"+=" { return(S_ADD); }<C>"-=" { return(S_SUB); }<C>"*=" { return(S_MUL); }<C>"/=" { return(S_DIV); }<C>"%=" { return(S_MOD); }<C>"->*" { return(S_MEMPOINT); }<C>".*" { return(S_DOTPOINT); }<C>{other} { return S_ANYTHING; }<C>{exec_sql}{define}{space}* { BEGIN(def_ident); }<C>{informix_special}{define}{space}* { /* are we simulating Informix? */ if (INFORMIX_MODE) { BEGIN(def_ident); } else { yyless(1); return (S_ANYTHING); } }<C>{exec_sql}{undef}{space}* { BEGIN(undef); }<C>{informix_special}{undef}{space}* { /* are we simulating Informix? */ if (INFORMIX_MODE) { BEGIN(undef); } else { yyless(1); return (S_ANYTHING); } }<undef>{identifier}{space}*";" { struct _defines *ptr, *ptr2 = NULL; int i; /* * Skip the ";" and trailing whitespace. Note that yytext * contains at least one non-space character plus the ";" */ for (i = strlen(yytext)-2; i > 0 && ecpg_isspace(yytext[i]); i-- ) ; yytext[i+1] = '\0'; for (ptr = defines; ptr != NULL; ptr2 = ptr, ptr = ptr->next) { if (strcmp(yytext, ptr->old) == 0) { if (ptr2 == NULL) defines = ptr->next; else ptr2->next = ptr->next; free(ptr->new); free(ptr->old); free(ptr); break; } } BEGIN(C); }<undef>{other}|\n { mmerror(PARSE_ERROR, ET_FATAL, "Missing identifier in 'EXEC SQL UNDEF' command"); yyterminate(); }<C>{exec_sql}{include}{space}* { BEGIN(incl); }<C>{informix_special}{include}{space}* { /* are we simulating Informix? */ if (INFORMIX_MODE) { BEGIN(incl); } else { yyless(1); return (S_ANYTHING); } }<C,xskip>{exec_sql}{ifdef}{space}* { ifcond = TRUE; BEGIN(xcond); }<C,xskip>{informix_special}{ifdef}{space}* { /* are we simulating Informix? */ if (INFORMIX_MODE) { ifcond = TRUE; BEGIN(xcond); } else { yyless(1); return (S_ANYTHING); } }<C,xskip>{exec_sql}{ifndef}{space}* { ifcond = FALSE; BEGIN(xcond); }<C,xskip>{informix_special}{ifndef}{space}* { /* are we simulating Informix? */ if (INFORMIX_MODE) { ifcond = FALSE; BEGIN(xcond); } else { yyless(1); return (S_ANYTHING); } }<C,xskip>{exec_sql}{elif}{space}* { /* pop stack */ if ( preproc_tos == 0 ) { mmerror(PARSE_ERROR, ET_FATAL, "Missing matching 'EXEC SQL IFDEF / EXEC SQL IFNDEF'"); } else if ( stacked_if_value[preproc_tos].else_branch ) mmerror(PARSE_ERROR, ET_FATAL, "Missing 'EXEC SQL ENDIF;'"); else preproc_tos--; ifcond = TRUE; BEGIN(xcond); }<C,xskip>{informix_special}{elif}{space}* { /* are we simulating Informix? */ if (INFORMIX_MODE) { if (preproc_tos == 0) mmerror(PARSE_ERROR, ET_FATAL, "Missing matching 'EXEC SQL IFDEF / EXEC SQL IFNDEF'"); else if (stacked_if_value[preproc_tos].else_branch) mmerror(PARSE_ERROR, ET_FATAL, "Missing 'EXEC SQL ENDIF;'"); else preproc_tos--; ifcond = TRUE; BEGIN(xcond); } else { yyless(1); return (S_ANYTHING); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -