From: helly Date: Wed, 21 Apr 2004 08:49:44 +0000 (+0000) Subject: Bugfix 869297 X-Git-Tag: 0.13.6~712 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a833e5a086e266900df201a1e6f2ea00b7b5da56;p=re2c Bugfix 869297 --- diff --git a/bootstrap/scanner.cc b/bootstrap/scanner.cc index 29fd5cb8..783f4671 100644 --- a/bootstrap/scanner.cc +++ b/bootstrap/scanner.cc @@ -1,4 +1,4 @@ -/* Generated by re2c 0.9.2 on Mon Apr 19 04:31:02 2004 */ +/* Generated by re2c 0.9.2 on Wed Apr 21 10:37:57 2004 */ #line 1 "scanner.re" /* $Id$ */ #include @@ -96,7 +96,7 @@ yy3: #line 92 "scanner.re" { goto echo; } #line 26 "re2c-output.c" -yy4: yych = *++YYCURSOR; +yy4: ++YYCURSOR; goto yy5; yy5: #line 88 "scanner.re" @@ -126,7 +126,7 @@ yy11: yych = *++YYCURSOR; yy12: yych = *++YYCURSOR; if(yych != 'c') goto yy8; goto yy13; -yy13: yych = *++YYCURSOR; +yy13: ++YYCURSOR; goto yy14; yy14: #line 85 "scanner.re" @@ -216,15 +216,15 @@ yy18: goto code; } #line 134 "re2c-output.c" -yy19: yych = *++YYCURSOR; - if(yych == '*') goto yy61; +yy19: ++YYCURSOR; + if((yych = *YYCURSOR) == '*') goto yy61; goto yy20; yy20: #line 132 "scanner.re" { RETURN(*tok); } #line 141 "re2c-output.c" -yy21: yych = *++YYCURSOR; - if(yych == '/') goto yy59; +yy21: ++YYCURSOR; + if((yych = *YYCURSOR) == '/') goto yy59; goto yy22; yy22: #line 134 "scanner.re" @@ -259,7 +259,8 @@ yy29: yych = *++YYCURSOR; goto yy20; yy30: yych = *++YYCURSOR; goto yy22; -yy31: yych = *++YYCURSOR; +yy31: ++YYCURSOR; + yych = *YYCURSOR; goto yy42; yy32: #line 149 "scanner.re" @@ -267,13 +268,14 @@ yy32: yylval.symbol = Symbol::find(token()); return ID; } #line 185 "re2c-output.c" -yy33: yych = *++YYCURSOR; +yy33: ++YYCURSOR; + yych = *YYCURSOR; goto yy40; yy34: #line 153 "scanner.re" { goto scan; } #line 191 "re2c-output.c" -yy35: yych = *++YYCURSOR; +yy35: ++YYCURSOR; goto yy36; yy36: #line 155 "scanner.re" @@ -282,7 +284,7 @@ yy36: goto scan; } #line 200 "re2c-output.c" -yy37: yych = *++YYCURSOR; +yy37: ++YYCURSOR; goto yy38; yy38: #line 160 "scanner.re" @@ -335,14 +337,14 @@ yy46: ++YYCURSOR; yych = *YYCURSOR; if(yych == '\n') goto yy45; goto yy43; -yy47: yych = *++YYCURSOR; +yy47: ++YYCURSOR; goto yy48; yy48: #line 126 "scanner.re" { cur = cursor; yylval.regexp = ranToRE(token()); return RANGE; } -#line 261 "re2c-output.c" +#line 265 "re2c-output.c" yy49: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; @@ -360,14 +362,14 @@ yy51: ++YYCURSOR; yych = *YYCURSOR; if(yych == '\n') goto yy45; goto yy49; -yy52: yych = *++YYCURSOR; +yy52: ++YYCURSOR; goto yy53; yy53: #line 119 "scanner.re" { cur = cursor; yylval.regexp = strToCaseInsensitiveRE(token()); return STRING; } -#line 286 "re2c-output.c" +#line 292 "re2c-output.c" yy54: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; @@ -385,28 +387,28 @@ yy56: ++YYCURSOR; yych = *YYCURSOR; if(yych == '\n') goto yy45; goto yy54; -yy57: yych = *++YYCURSOR; +yy57: ++YYCURSOR; goto yy58; yy58: #line 115 "scanner.re" { cur = cursor; yylval.regexp = strToRE(token()); return STRING; } -#line 311 "re2c-output.c" -yy59: yych = *++YYCURSOR; +#line 319 "re2c-output.c" +yy59: ++YYCURSOR; goto yy60; yy60: #line 112 "scanner.re" { tok = cursor; RETURN(0); } -#line 318 "re2c-output.c" -yy61: yych = *++YYCURSOR; +#line 326 "re2c-output.c" +yy61: ++YYCURSOR; goto yy62; yy62: #line 109 "scanner.re" { depth = 1; goto comment; } -#line 325 "re2c-output.c" +#line 333 "re2c-output.c" yy63: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; @@ -419,25 +421,25 @@ yy64: if(yych <= '/'){ if(yych != '}') goto yy45; goto yy65; } -yy65: yych = *++YYCURSOR; +yy65: ++YYCURSOR; goto yy66; yy66: #line 137 "scanner.re" { yylval.extop.minsize = atoi((char *)tok+1); yylval.extop.maxsize = atoi((char *)tok+1); RETURN(CLOSESIZE); } -#line 345 "re2c-output.c" +#line 354 "re2c-output.c" yy67: yych = *++YYCURSOR; if(yych != '}') goto yy71; goto yy68; -yy68: yych = *++YYCURSOR; +yy68: ++YYCURSOR; goto yy69; yy69: #line 145 "scanner.re" { yylval.extop.minsize = atoi((char *)tok+1); yylval.extop.maxsize = -1; RETURN(CLOSESIZE); } -#line 356 "re2c-output.c" +#line 365 "re2c-output.c" yy70: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; @@ -446,21 +448,21 @@ yy71: if(yych <= '/') goto yy45; if(yych <= '9') goto yy70; if(yych != '}') goto yy45; goto yy72; -yy72: yych = *++YYCURSOR; +yy72: ++YYCURSOR; goto yy73; yy73: #line 141 "scanner.re" { yylval.extop.minsize = atoi((char *)tok+1); yylval.extop.maxsize = MAX(yylval.extop.minsize,atoi(strchr((char *)tok, ',')+1)); RETURN(CLOSESIZE); } -#line 372 "re2c-output.c" +#line 382 "re2c-output.c" } #line 163 "scanner.re" code: -#line 376 "re2c-output.c" +#line 386 "re2c-output.c" { YYCTYPE yych; unsigned int yyaccept; @@ -487,7 +489,7 @@ yy74: goto yy76; } } -yy76: yych = *++YYCURSOR; +yy76: ++YYCURSOR; goto yy77; yy77: #line 167 "scanner.re" @@ -497,15 +499,15 @@ yy77: return CODE; } goto code; } -#line 413 "re2c-output.c" -yy78: yych = *++YYCURSOR; +#line 423 "re2c-output.c" +yy78: ++YYCURSOR; goto yy79; yy79: #line 173 "scanner.re" { ++depth; goto code; } -#line 420 "re2c-output.c" -yy80: yych = *++YYCURSOR; +#line 430 "re2c-output.c" +yy80: ++YYCURSOR; goto yy81; yy81: #line 175 "scanner.re" @@ -513,13 +515,13 @@ yy81: pos = cursor; cline++; goto code; } -#line 429 "re2c-output.c" -yy82: yych = *++YYCURSOR; +#line 439 "re2c-output.c" +yy82: ++YYCURSOR; goto yy83; yy83: #line 179 "scanner.re" { goto code; } -#line 435 "re2c-output.c" +#line 445 "re2c-output.c" yy84: yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); if(yych == '\n') goto yy83; @@ -572,7 +574,7 @@ yy92: ++YYCURSOR; comment: -#line 485 "re2c-output.c" +#line 499 "re2c-output.c" { YYCTYPE yych; unsigned int yyaccept; @@ -589,17 +591,17 @@ yy93: if(yych == '/') goto yy97; goto yy100; } -yy95: yych = *++YYCURSOR; - if(yych == '/') goto yy103; +yy95: ++YYCURSOR; + if((yych = *YYCURSOR) == '/') goto yy103; goto yy96; yy96: #line 194 "scanner.re" { goto comment; } -#line 508 "re2c-output.c" +#line 522 "re2c-output.c" yy97: yych = *++YYCURSOR; if(yych == '*') goto yy101; goto yy96; -yy98: yych = *++YYCURSOR; +yy98: ++YYCURSOR; goto yy99; yy99: #line 190 "scanner.re" @@ -607,17 +609,17 @@ yy99: tok = pos = cursor; cline++; goto comment; } -#line 520 "re2c-output.c" +#line 534 "re2c-output.c" yy100: yych = *++YYCURSOR; goto yy96; -yy101: yych = *++YYCURSOR; +yy101: ++YYCURSOR; goto yy102; yy102: #line 188 "scanner.re" { ++depth; goto comment; } -#line 529 "re2c-output.c" -yy103: yych = *++YYCURSOR; +#line 543 "re2c-output.c" +yy103: ++YYCURSOR; goto yy104; yy104: #line 184 "scanner.re" @@ -625,7 +627,7 @@ yy104: goto scan; else goto comment; } -#line 538 "re2c-output.c" +#line 552 "re2c-output.c" } #line 195 "scanner.re" diff --git a/code.cc b/code.cc index b6331d18..c106131e 100644 --- a/code.cc +++ b/code.cc @@ -151,79 +151,115 @@ prt(cerr, b->go, b->on); cerr << endl; first = NULL; } -void genGoTo(ostream &o, State *to){ - o << "\tgoto yy" << to->label << ";\n"; - ++oline; +void genGoTo(ostream &o, State *from, State *to, bool & readCh) +{ + if (readCh && from->label + 1 != to->label) + { + o << "\tyych = *YYCURSOR;\n"; + readCh = false; + } + o << "\tgoto yy" << to->label << ";\n"; + ++oline; } -void genIf(ostream &o, char *cmp, uint v){ - o << "\tif(yych " << cmp << " '"; - prtCh(o, v); - o << "')"; +void genIf(ostream &o, char *cmp, uint v, bool &readCh) +{ + if (readCh) + { + o << "\tif((yych = *YYCURSOR) "; + readCh = false; + } + else + { + o << "\tif(yych "; + } + o << cmp << " '"; + prtCh(o, v); + o << "')"; } -void indent(ostream &o, uint i){ - while(i-- > 0) - o << "\t"; +void indent(ostream &o, uint i) +{ + while(i-- > 0) + { + o << "\t"; + } } -static void need(ostream &o, uint n){ - if(n == 1) - { - o << "\tif(YYLIMIT == YYCURSOR) YYFILL(1);\n"; - ++oline; - } - else - { - o << "\tif((YYLIMIT - YYCURSOR) < " << n << ") YYFILL(" << n << ");\n"; +static void need(ostream &o, uint n, bool & readCh) +{ + if(n == 1) + { + o << "\tif(YYLIMIT == YYCURSOR) YYFILL(1);\n"; + ++oline; + } + else + { + o << "\tif((YYLIMIT - YYCURSOR) < " << n << ") YYFILL(" << n << ");\n"; + ++oline; + } + o << "\tyych = *YYCURSOR;\n"; + readCh = false; ++oline; - } - o << "\tyych = *YYCURSOR;\n"; - ++oline; } -void Match::emit(ostream &o){ - if(state->link){ - o << "\t++YYCURSOR;\n"; - ++oline; - need(o, state->depth); - } else { - o << "\tyych = *++YYCURSOR;\n"; +void Match::emit(ostream &o, bool &readCh) +{ + if (state->link || !readAhead()) + { + /* do not read next char if match */ + o << "\t++YYCURSOR;\n"; + readCh = true; + } + else + { + o << "\tyych = *++YYCURSOR;\n"; + readCh = false; + } ++oline; - } + if(state->link) + { + ++oline; + need(o, state->depth, readCh); + } } -void Enter::emit(ostream &o){ - if(state->link){ - o << "\t++YYCURSOR;\n"; - o << "yy" << label << ":\n"; - oline += 2; - need(o, state->depth); - } else { - o << "\tyych = *++YYCURSOR;\n"; - o << "yy" << label << ":\n"; - oline += 2; - } +void Enter::emit(ostream &o, bool &readCh) +{ + if(state->link){ + o << "\t++YYCURSOR;\n"; + o << "yy" << label << ":\n"; + oline += 2; + need(o, state->depth, readCh); + } else { + /* we shouldn't need 'rule-following' protection here */ + o << "\tyych = *++YYCURSOR;\n"; + o << "yy" << label << ":\n"; + oline += 2; + readCh = false; + } } -void Save::emit(ostream &o){ - o << "\tyyaccept = " << selector << ";\n"; - ++oline; - if(state->link){ - o << "\tYYMARKER = ++YYCURSOR;\n"; +void Save::emit(ostream &o, bool &readCh) +{ + o << "\tyyaccept = " << selector << ";\n"; ++oline; - need(o, state->depth); - } else { - o << "\tyych = *(YYMARKER = ++YYCURSOR);\n"; - ++oline; - } + if(state->link){ + o << "\tYYMARKER = ++YYCURSOR;\n"; + ++oline; + need(o, state->depth, readCh); + } else { + o << "\tyych = *(YYMARKER = ++YYCURSOR);\n"; + ++oline; + readCh = false; + } } Move::Move(State *s) : Action(s) { ; } -void Move::emit(ostream &o){ +void Move::emit(ostream &o, bool &readCh){ ; } @@ -232,79 +268,96 @@ Accept::Accept(State *x, uint n, uint *s, State **r) ; } -void Accept::emit(ostream &o){ - bool first = true; - for(uint i = 0; i < nRules; ++i) - if(saves[i] != ~0u){ - if(first){ - first = false; - o << "\tYYCURSOR = YYMARKER;\n"; - o << "\tswitch(yyaccept){\n"; - oline += 2; - } - o << "\tcase " << saves[i] << ":"; - genGoTo(o, rules[i]); +void Accept::emit(ostream &o, bool &readCh) +{ + bool first = true; + for(uint i = 0; i < nRules; ++i) + if(saves[i] != ~0u) + { + if(first) + { + first = false; + o << "\tYYCURSOR = YYMARKER;\n"; + o << "\tswitch(yyaccept){\n"; + oline += 2; + } + o << "\tcase " << saves[i] << ":"; + genGoTo(o, state, rules[i], readCh); + } + if(!first) + { + o << "\t}\n"; + ++oline; } - if(!first) - { - o << "\t}\n"; - ++oline; - } } Rule::Rule(State *s, RuleOp *r) : Action(s), rule(r) { ; } -void Rule::emit(ostream &o){ - uint back = rule->ctx->fixedLength(); - if(back != ~0u && back > 0u) - o << "\tYYCURSOR -= " << back << ";"; - o << "\n"; - ++oline; - line_source(rule->code->line, o); - o << rule->code->text; -// not sure if we need this or not. oline += std::count(rule->code->text, rule->code->text + ::strlen(rule->code->text), '\n'); - o << "\n"; - ++oline; - o << "#line " << ++oline << " \"re2c-output.c\"\n"; - // TODO: use this once we get an output filename: o << "#line " << ++oline << " \"" << outputFileName << "\"\n"; -// o << "\n#line " << rule->code->line -// << "\n\t" << rule->code->text << "\n"; -} - -void doLinear(ostream &o, uint i, Span *s, uint n, State *next){ - for(;;){ - State *bg = s[0].to; - while(n >= 3 && s[2].to == bg && (s[1].ub - s[0].ub) == 1){ - if(s[1].to == next && n == 3){ - indent(o, i); genIf(o, "!=", s[0].ub); genGoTo(o, bg); - indent(o, i); genGoTo(o, next); - return; - } else { - indent(o, i); genIf(o, "==", s[0].ub); genGoTo(o, s[1].to); - } - n -= 2; s += 2; - } - if(n == 1){ -// if(bg != next){ - indent(o, i); genGoTo(o, s[0].to); -// } - return; - } else if(n == 2 && bg == next){ - indent(o, i); genIf(o, ">=", s[0].ub); genGoTo(o, s[1].to); - indent(o, i); genGoTo(o, next); - return; - } else { - indent(o, i); genIf(o, "<=", s[0].ub - 1); genGoTo(o, bg); - n -= 1; s += 1; +void Rule::emit(ostream &o, bool &readCh) +{ + uint back = rule->ctx->fixedLength(); + if(back != ~0u && back > 0u) { + o << "\tYYCURSOR -= " << back << ";"; } - } - indent(o, i); genGoTo(o, next); + o << "\n"; + ++oline; + line_source(rule->code->line, o); + o << rule->code->text; + // not sure if we need this or not. oline += std::count(rule->code->text, rule->code->text + ::strlen(rule->code->text), '\n'); + o << "\n"; + ++oline; + o << "#line " << ++oline << " \"re2c-output.c\"\n"; + // TODO: use this once we get an output filename: o << "#line " << ++oline << " \"" << outputFileName << "\"\n"; + // o << "\n#line " << rule->code->line + // << "\n\t" << rule->code->text << "\n"; +} + +void doLinear(ostream &o, uint i, Span *s, uint n, State *from, State *next, bool &readCh) +{ + for(;;) + { + State *bg = s[0].to; + while(n >= 3 && s[2].to == bg && (s[1].ub - s[0].ub) == 1) + { + if(s[1].to == next && n == 3) + { + indent(o, i); genIf(o, "!=", s[0].ub, readCh); genGoTo(o, from, bg, readCh); + indent(o, i); genGoTo(o, from, next, readCh); + return; + } + else + { + indent(o, i); genIf(o, "==", s[0].ub, readCh); genGoTo(o, from, s[1].to, readCh); + } + n -= 2; s += 2; + } + if(n == 1) + { +// if(bg != next){ + indent(o, i); genGoTo(o, from, s[0].to, readCh); +// } + return; + } + else if(n == 2 && bg == next) + { + indent(o, i); genIf(o, ">=", s[0].ub, readCh); genGoTo(o, from, s[1].to, readCh); + indent(o, i); genGoTo(o, from, next, readCh); + return; + } + else + { + indent(o, i); genIf(o, "<=", s[0].ub - 1, readCh); genGoTo(o, from, bg, readCh); + n -= 1; s += 1; + } + } + indent(o, i); genGoTo(o, from, next, readCh); } -void Go::genLinear(ostream &o, State *next){ - doLinear(o, 0, span, nSpans, next); +void Go::genLinear(ostream &o, State *from, State *next, bool &readCh) +{ + doLinear(o, 0, span, nSpans, from, next, readCh); } void genCases(ostream &o, uint lb, Span *s){ @@ -319,394 +372,529 @@ void genCases(ostream &o, uint lb, Span *s){ } } -void Go::genSwitch(ostream &o, State *next){ - if(nSpans <= 2){ - genLinear(o, next); - } else { - State *def = span[nSpans-1].to; - Span **sP = new Span*[nSpans-1], **r, **s, **t; - - t = &sP[0]; - for(uint i = 0; i < nSpans; ++i) - if(span[i].to != def) - *(t++) = &span[i]; - - o << "\tswitch(yych){\n"; - ++oline; - while(t != &sP[0]){ - r = s = &sP[0]; - if(*s == &span[0]) - genCases(o, 0, *s); - else - genCases(o, (*s)[-1].ub, *s); - State *to = (*s)->to; - while(++s < t){ - if((*s)->to == to) - genCases(o, (*s)[-1].ub, *s); +void Go::genSwitch(ostream &o, State *from, State *next, bool &readCh) +{ + if(nSpans <= 2){ + genLinear(o, from, next, readCh); + } + else + { + State *def = span[nSpans-1].to; + Span **sP = new Span*[nSpans-1], **r, **s, **t; + + t = &sP[0]; + for(uint i = 0; i < nSpans; ++i) + { + if(span[i].to != def) + { + *(t++) = &span[i]; + } + } + + if (readCh) + { + o << "\tswitch((yych = *YYCURSOR)) {\n"; + readCh =false; + } else - *(r++) = *s; - } - genGoTo(o, to); - t = r; + { + o << "\tswitch(yych){\n"; + } + ++oline; + while(t != &sP[0]) + { + r = s = &sP[0]; + if(*s == &span[0]) + genCases(o, 0, *s); + else + genCases(o, (*s)[-1].ub, *s); + State *to = (*s)->to; + while(++s < t) + { + if((*s)->to == to) + { + genCases(o, (*s)[-1].ub, *s); + } + else + { + *(r++) = *s; + } + } + genGoTo(o, from, to, readCh); + t = r; + } + o << "\tdefault:"; + genGoTo(o, from, def, readCh); + o << "\t}\n"; + ++oline; + + delete [] sP; } - o << "\tdefault:"; - genGoTo(o, def); - o << "\t}\n"; - ++oline; - - delete [] sP; - } } -void doBinary(ostream &o, uint i, Span *s, uint n, State *next){ - if(n <= 4){ - doLinear(o, i, s, n, next); - } else { - uint h = n/2; - indent(o, i); genIf(o, "<=", s[h-1].ub - 1); o << "{\n"; - ++oline; - doBinary(o, i+1, &s[0], h, next); - indent(o, i); o << "\t} else {\n"; - ++oline; - doBinary(o, i+1, &s[h], n - h, next); - indent(o, i); o << "\t}\n"; - ++oline; - } +void doBinary(ostream &o, uint i, Span *s, uint n, State *from, State *next, bool &readCh) +{ + if(n <= 4) + { + doLinear(o, i, s, n, from, next, readCh); + } + else + { + uint h = n/2; + indent(o, i); genIf(o, "<=", s[h-1].ub - 1, readCh); o << "{\n"; + ++oline; + doBinary(o, i+1, &s[0], h, from, next, readCh); + indent(o, i); o << "\t} else {\n"; + ++oline; + doBinary(o, i+1, &s[h], n - h, from, next, readCh); + indent(o, i); o << "\t}\n"; + ++oline; + } } -void Go::genBinary(ostream &o, State *next){ - doBinary(o, 0, span, nSpans, next); +void Go::genBinary(ostream &o, State *from, State *next, bool &readCh) +{ + doBinary(o, 0, span, nSpans, from, next, readCh); } -void Go::genBase(ostream &o, State *next){ - if(nSpans == 0) - return; - if(!sFlag){ - genSwitch(o, next); - return; - } - if(nSpans > 8){ - Span *bot = &span[0], *top = &span[nSpans-1]; - uint util; - if(bot[0].to == top[0].to){ - util = (top[-1].ub - bot[0].ub)/(nSpans - 2); - } else { - if(bot[0].ub > (top[0].ub - top[-1].ub)){ - util = (top[0].ub - bot[0].ub)/(nSpans - 1); - } else { - util = top[-1].ub/(nSpans - 1); - } +void Go::genBase(ostream &o, State *from, State *next, bool &readCh) +{ + if(nSpans == 0) + { + return; } - if(util <= 2){ - genSwitch(o, next); - return; + if(!sFlag) + { + genSwitch(o, from, next, readCh); + return; + } + if(nSpans > 8) + { + Span *bot = &span[0], *top = &span[nSpans-1]; + uint util; + if(bot[0].to == top[0].to) + { + util = (top[-1].ub - bot[0].ub)/(nSpans - 2); + } + else + { + if(bot[0].ub > (top[0].ub - top[-1].ub)) + { + util = (top[0].ub - bot[0].ub)/(nSpans - 1); + } + else + { + util = top[-1].ub/(nSpans - 1); + } + } + if(util <= 2) + { + genSwitch(o, from, next, readCh); + return; + } + } + if(nSpans > 5) + { + genBinary(o, from, next, readCh); + } + else + { + genLinear(o, from, next, readCh); } - } - if(nSpans > 5){ - genBinary(o, next); - } else { - genLinear(o, next); - } } -void Go::genGoto(ostream &o, State *next){ - if(bFlag){ - for(uint i = 0; i < nSpans; ++i){ - State *to = span[i].to; - if(to && to->isBase){ - BitMap *b = BitMap::find(to); - if(b && matches(b->go, b->on, this, to)){ - Go go; - go.span = new Span[nSpans]; - go.unmap(this, to); - o << "\tif(yybm[" << b->i << "+yych] & " << (uint) b->m << ")"; - genGoTo(o, to); - go.genBase(o, next); - delete [] go.span; - return; +void Go::genGoto(ostream &o, State *from, State *next, bool &readCh) +{ + if(bFlag) + { + for(uint i = 0; i < nSpans; ++i) + { + State *to = span[i].to; + if(to && to->isBase) + { + BitMap *b = BitMap::find(to); + if(b && matches(b->go, b->on, this, to)) + { + Go go; + go.span = new Span[nSpans]; + go.unmap(this, to); + o << "\tif(yybm[" << b->i << "+"; + if (readCh) + { + o << "(yych = *YYCURSOR)"; + } + else + { + o << "ych"; + } + o << "] & " << (uint) b->m << ")"; + genGoTo(o, from, to, readCh); + go.genBase(o, from, next, readCh); + delete [] go.span; + return; + } + } } - } } - } - genBase(o, next); -} - -void State::emit(ostream &o){ - o << "yy" << label << ":"; - action->emit(o); -} - -uint merge(Span *x0, State *fg, State *bg){ - Span *x = x0, *f = fg->go.span, *b = bg->go.span; - uint nf = fg->go.nSpans, nb = bg->go.nSpans; - State *prev = NULL, *to; - // NB: we assume both spans are for same range - for(;;){ - if(f->ub == b->ub){ - to = f->to == b->to? bg : f->to; - if(to == prev){ - --x; - } else { - x->to = prev = to; - } - x->ub = f->ub; - ++x; ++f; --nf; ++b; --nb; - if(nf == 0 && nb == 0) - return x - x0; - } - while(f->ub < b->ub){ - to = f->to == b->to? bg : f->to; - if(to == prev){ - --x; - } else { - x->to = prev = to; - } - x->ub = f->ub; - ++x; ++f; --nf; - } - while(b->ub < f->ub){ - to = b->to == f->to? bg : f->to; - if(to == prev){ - --x; - } else { - x->to = prev = to; - } - x->ub = b->ub; - ++x; ++b; --nb; + genBase(o, from, next, readCh); +} + +void State::emit(ostream &o, bool &readCh){ + o << "yy" << label << ":"; +/* o << "\nfprintf(stderr, \"<" << label << ">\");\n";*/ + action->emit(o, readCh); +} + +uint merge(Span *x0, State *fg, State *bg) +{ + Span *x = x0, *f = fg->go.span, *b = bg->go.span; + uint nf = fg->go.nSpans, nb = bg->go.nSpans; + State *prev = NULL, *to; + // NB: we assume both spans are for same range + for(;;) + { + if(f->ub == b->ub) + { + to = f->to == b->to? bg : f->to; + if(to == prev){ + --x; + } + else + { + x->to = prev = to; + } + x->ub = f->ub; + ++x; ++f; --nf; ++b; --nb; + if(nf == 0 && nb == 0) + { + return x - x0; + } + } + while(f->ub < b->ub) + { + to = f->to == b->to? bg : f->to; + if(to == prev) + { + --x; + } + else + { + x->to = prev = to; + } + x->ub = f->ub; + ++x; ++f; --nf; + } + while(b->ub < f->ub) + { + to = b->to == f->to? bg : f->to; + if(to == prev) + { + --x; + } + else + { + x->to = prev = to; + } + x->ub = b->ub; + ++x; ++b; --nb; + } } - } } const uint cInfinity = ~0; class SCC { public: - State **top, **stk; + State **top, **stk; public: - SCC(uint); - ~SCC(); - void traverse(State*); + SCC(uint); + ~SCC(); + void traverse(State*); }; SCC::SCC(uint size){ - top = stk = new State*[size]; + top = stk = new State*[size]; } SCC::~SCC(){ - delete [] stk; -} - -void SCC::traverse(State *x){ - *top = x; - uint k = ++top - stk; - x->depth = k; - for(uint i = 0; i < x->go.nSpans; ++i){ - State *y = x->go.span[i].to; - if(y){ - if(y->depth == 0) - traverse(y); - if(y->depth < x->depth) - x->depth = y->depth; + delete [] stk; +} + +void SCC::traverse(State *x) +{ + *top = x; + uint k = ++top - stk; + x->depth = k; + for(uint i = 0; i < x->go.nSpans; ++i) + { + State *y = x->go.span[i].to; + if(y) + { + if(y->depth == 0) + { + traverse(y); + } + if(y->depth < x->depth) + { + x->depth = y->depth; + } + } } - } - if(x->depth == k) - do { - (*--top)->depth = cInfinity; - (*top)->link = x; - } while(*top != x); -} - -uint maxDist(State *s){ - uint mm = 0; - for(uint i = 0; i < s->go.nSpans; ++i){ - State *t = s->go.span[i].to; - if(t){ - uint m = 1; - if(!t->link) - m += maxDist(t); - if(m > mm) - mm = m; + if(x->depth == k) + { + do + { + (*--top)->depth = cInfinity; + (*top)->link = x; + } while(*top != x); } - } - return mm; } -void calcDepth(State *head){ - State *t; - for(State *s = head; s; s = s->next){ - if(s->link == s){ - for(uint i = 0; i < s->go.nSpans; ++i){ - t = s->go.span[i].to; - if(t && t->link == s) - goto inSCC; - } - s->link = NULL; - } else { - inSCC: - s->depth = maxDist(s); +uint maxDist(State *s) +{ + uint mm = 0; + for(uint i = 0; i < s->go.nSpans; ++i) + { + State *t = s->go.span[i].to; + if(t) + { + uint m = 1; + if(!t->link) + { + m += maxDist(t); + } + if(m > mm) + { + mm = m; + } + } + } + return mm; +} + +void calcDepth(State *head) +{ + State *t; + for(State *s = head; s; s = s->next) + { + if(s->link == s){ + for(uint i = 0; i < s->go.nSpans; ++i) + { + t = s->go.span[i].to; + if(t && t->link == s) + { + goto inSCC; + } + } + s->link = NULL; + }else + { + inSCC: + s->depth = maxDist(s); + } } - } } -void DFA::findSCCs(){ - SCC scc(nStates); - State *s; +void DFA::findSCCs() +{ + SCC scc(nStates); + State *s; + + for(s = head; s; s = s->next) + { + s->depth = 0; + s->link = NULL; + } - for(s = head; s; s = s->next){ - s->depth = 0; - s->link = NULL; - } + for(s = head; s; s = s->next) + { + if(!s->depth) + { + scc.traverse(s); + } + } - for(s = head; s; s = s->next) - if(!s->depth) - scc.traverse(s); - - calcDepth(head); -} - -void DFA::split(State *s){ - State *move = new State; - (void) new Move(move); - addState(&s->next, move); - move->link = s->link; - move->rule = s->rule; - move->go = s->go; - s->rule = NULL; - s->go.nSpans = 1; - s->go.span = new Span[1]; - s->go.span[0].ub = ubChar; - s->go.span[0].to = move; -} - -void DFA::emit(ostream &o){ - static uint label = 0; - State *s; - uint i; - - findSCCs(); - head->link = head; - head->depth = maxDist(head); - - uint nRules = 0; - for(s = head; s; s = s->next) - if(s->rule && s->rule->accept >= nRules) - nRules = s->rule->accept + 1; - - uint nSaves = 0; - uint *saves = new uint[nRules]; - memset(saves, ~0, (nRules)*sizeof(*saves)); - - // mark backtracking points - for(s = head; s; s = s->next){ - RuleOp *ignore = NULL; - if(s->rule){ - for(i = 0; i < s->go.nSpans; ++i) - if(s->go.span[i].to && !s->go.span[i].to->rule){ - delete s->action; - if(saves[s->rule->accept] == ~0u) - saves[s->rule->accept] = nSaves++; - (void) new Save(s, saves[s->rule->accept]); - continue; + calcDepth(head); +} + +void DFA::split(State *s) +{ + State *move = new State; + (void) new Move(move); + addState(&s->next, move); + move->link = s->link; + move->rule = s->rule; + move->go = s->go; + s->rule = NULL; + s->go.nSpans = 1; + s->go.span = new Span[1]; + s->go.span[0].ub = ubChar; + s->go.span[0].to = move; +} + +void DFA::emit(ostream &o) +{ + static uint label = 0; + State *s; + uint i; + + findSCCs(); + head->link = head; + head->depth = maxDist(head); + + uint nRules = 0; + for(s = head; s; s = s->next) + { + if(s->rule && s->rule->accept >= nRules) + { + nRules = s->rule->accept + 1; } - ignore = s->rule; } - } - // insert actions - State **rules = new State*[nRules]; - memset(rules, 0, (nRules)*sizeof(*rules)); - State *accept = NULL; - for(s = head; s; s = s->next){ - State *ow; - if(!s->rule){ - ow = accept; - } else { - if(!rules[s->rule->accept]){ - State *n = new State; - (void) new Rule(n, s->rule); - rules[s->rule->accept] = n; - addState(&s->next, n); - } - ow = rules[s->rule->accept]; - } - for(i = 0; i < s->go.nSpans; ++i) - if(!s->go.span[i].to){ - if(!ow){ - ow = accept = new State; - (void) new Accept(accept, nRules, saves, rules); - addState(&s->next, accept); + uint nSaves = 0; + uint *saves = new uint[nRules]; + memset(saves, ~0, (nRules)*sizeof(*saves)); + + // mark backtracking points + for(s = head; s; s = s->next) + { + RuleOp *ignore = NULL; + if(s->rule) + { + for(i = 0; i < s->go.nSpans; ++i) + { + if(s->go.span[i].to && !s->go.span[i].to->rule){ + delete s->action; + if(saves[s->rule->accept] == ~0u) + { + saves[s->rule->accept] = nSaves++; + } + (void) new Save(s, saves[s->rule->accept]); + continue; + } + } + ignore = s->rule; } - s->go.span[i].to = ow; - } - } + } - // split ``base'' states into two parts - for(s = head; s; s = s->next){ - s->isBase = false; - if(s->link){ - for(i = 0; i < s->go.nSpans; ++i){ - if(s->go.span[i].to == s){ - s->isBase = true; - split(s); - if(bFlag) - BitMap::find(&s->next->go, s); - s = s->next; - break; + // insert actions + State **rules = new State*[nRules]; + memset(rules, 0, (nRules)*sizeof(*rules)); + State *accept = NULL; + for(s = head; s; s = s->next) + { + State *ow; + if(!s->rule) + { + ow = accept; + } + else + { + if(!rules[s->rule->accept]) + { + State *n = new State; + (void) new Rule(n, s->rule); + rules[s->rule->accept] = n; + addState(&s->next, n); + } + ow = rules[s->rule->accept]; + } + for(i = 0; i < s->go.nSpans; ++i) + if(!s->go.span[i].to) + { + if(!ow) + { + ow = accept = new State; + (void) new Accept(accept, nRules, saves, rules); + addState(&s->next, accept); + } + s->go.span[i].to = ow; } - } } - } - // find ``base'' state, if possible - Span *span = new Span[ubChar - lbChar]; - for(s = head; s; s = s->next){ - if(!s->link){ - for(i = 0; i < s->go.nSpans; ++i){ - State *to = s->go.span[i].to; - if(to && to->isBase){ - to = to->go.span[0].to; - uint nSpans = merge(span, s, to); - if(nSpans < s->go.nSpans){ - delete [] s->go.span; - s->go.nSpans = nSpans; - s->go.span = new Span[nSpans]; - memcpy(s->go.span, span, nSpans*sizeof(Span)); - } - break; + // split ``base'' states into two parts + for(s = head; s; s = s->next) + { + s->isBase = false; + if(s->link) + { + for(i = 0; i < s->go.nSpans; ++i) + { + if(s->go.span[i].to == s){ + s->isBase = true; + split(s); + if(bFlag) + { + BitMap::find(&s->next->go, s); + } + s = s->next; + break; + } + } } - } } - } - delete [] span; - delete head->action; + // find ``base'' state, if possible + Span *span = new Span[ubChar - lbChar]; + for(s = head; s; s = s->next) + { + if(!s->link) + { + for(i = 0; i < s->go.nSpans; ++i) + { + State *to = s->go.span[i].to; + if(to && to->isBase) + { + to = to->go.span[0].to; + uint nSpans = merge(span, s, to); + if(nSpans < s->go.nSpans) + { + delete [] s->go.span; + s->go.nSpans = nSpans; + s->go.span = new Span[nSpans]; + memcpy(s->go.span, span, nSpans*sizeof(Span)); + } + break; + } + } + } + } + delete [] span; - ++oline; - o << "\n#line " << ++oline << " \"re2c-output.c\"\n"; - // TODO: Switch to use this once we have an outputFileName: o << "\n#line " << ++oline << " \"" << outputFileName << "\"\n"; - o << "{\n\tYYCTYPE yych;\n\tunsigned int yyaccept;\n"; - oline += 3; + delete head->action; + ++oline; + o << "\n#line " << ++oline << " \"re2c-output.c\"\n"; + // TODO: Switch to use this once we have an outputFileName: o << "\n#line " << ++oline << " \"" << outputFileName << "\"\n"; + o << "{\n\tYYCTYPE yych;\n\tunsigned int yyaccept;\n"; + oline += 3; - if(bFlag) - BitMap::gen(o, lbChar, ubChar); - o << "\tgoto yy" << label << ";\n"; - ++oline; - (void) new Enter(head, label++); + if(bFlag) + { + BitMap::gen(o, lbChar, ubChar); + } - for(s = head; s; s = s->next) - s->label = label++; + o << "\tgoto yy" << label << ";\n"; + ++oline; + (void) new Enter(head, label++); - for(s = head; s; s = s->next){ - s->emit(o); - s->go.genGoto(o, s->next); - } - o << "}\n"; - ++oline; + for(s = head; s; s = s->next) + { + s->label = label++; + } + + for(s = head; s; s = s->next) + { + bool readCh = false; + s->emit(o, readCh); + s->go.genGoto(o, s, s->next, readCh); + } + o << "}\n"; + ++oline; - BitMap::first = NULL; + BitMap::first = NULL; - delete [] saves; - delete [] rules; + delete [] saves; + delete [] rules; } diff --git a/dfa.h b/dfa.h index 6ca66360..6bd78248 100644 --- a/dfa.h +++ b/dfa.h @@ -16,13 +16,17 @@ public: State *state; public: Action(State*); - virtual void emit(ostream&) = 0; + virtual void emit(ostream&, bool&) = 0; + virtual bool isRule() const; + virtual bool isMatch() const; + virtual bool readAhead() const; }; class Match: public Action { public: Match(State*); - void emit(ostream&); + void emit(ostream&, bool&); + bool isMatch() const; }; class Enter: public Action { @@ -30,7 +34,7 @@ public: uint label; public: Enter(State*, uint); - void emit(ostream&); + void emit(ostream&, bool&); }; class Save: public Match { @@ -38,13 +42,14 @@ public: uint selector; public: Save(State*, uint); - void emit(ostream&); + void emit(ostream&, bool&); + bool isMatch() const; }; class Move: public Action { public: Move(State*); - void emit(ostream&); + void emit(ostream&, bool&); }; class Accept: public Action { @@ -54,7 +59,7 @@ public: State **rules; public: Accept(State*, uint, uint*, State**); - void emit(ostream&); + void emit(ostream&, bool&); }; class Rule: public Action { @@ -62,7 +67,8 @@ public: RuleOp *rule; public: Rule(State*, RuleOp*); - void emit(ostream&); + void emit(ostream&, bool&); + bool isRule() const; }; class Span { @@ -78,11 +84,11 @@ public: uint nSpans; Span *span; public: - void genGoto(ostream&, State*); - void genBase(ostream&, State*); - void genLinear(ostream&, State*); - void genBinary(ostream&, State*); - void genSwitch(ostream&, State*); + void genGoto(ostream&, State *from, State*, bool &readCh); + void genBase(ostream&, State *from, State*, bool &readCh); + void genLinear(ostream&, State *from, State*, bool &readCh); + void genBinary(ostream&, State *from, State*, bool &readCh); + void genSwitch(ostream&, State *from, State*, bool &readCh); void compact(); void unmap(Go*, State*); }; @@ -102,7 +108,7 @@ public: public: State(); ~State(); - void emit(ostream&); + void emit(ostream&, bool&); friend ostream& operator<<(ostream&, const State&); friend ostream& operator<<(ostream&, const State*); }; @@ -132,15 +138,33 @@ inline Action::Action(State *s) : state(s) { s->action = this; } +inline bool Action::isRule() const + { return false; } + +inline bool Action::isMatch() const + { return false; } + +inline bool Action::readAhead() const + { return !isMatch() || !state->next->action->isRule(); } + inline Match::Match(State *s) : Action(s) { } +inline bool Match::isMatch() const + { return true; } + inline Enter::Enter(State *s, uint l) : Action(s), label(l) { } inline Save::Save(State *s, uint i) : Match(s), selector(i) { } +inline bool Save::isMatch() const + { return false; } + +inline bool Rule::isRule() const + { return true; } + inline ostream& operator<<(ostream &o, const State *s) { return o << *s; } diff --git a/re2c.spec.in b/re2c.spec.in index add18f5d..2963b697 100644 --- a/re2c.spec.in +++ b/re2c.spec.in @@ -24,8 +24,8 @@ flexible. make re2c #regenerate file scanner.cc rm -f scanner.cc -make scanner.cc -rm -f re2c +./re2c scanner.re > scanner.cc +rm -f re2c scanner.o make %install