]> granicus.if.org Git - re2c/commitdiff
One pass.
authorUlya Trofimovich <skvadrik@gmail.com>
Wed, 25 Feb 2015 23:13:55 +0000 (23:13 +0000)
committerUlya Trofimovich <skvadrik@gmail.com>
Wed, 25 Feb 2015 23:13:55 +0000 (23:13 +0000)
Second pass was used because some information (which influences
early parts of the generated code, e.g enum with condition names
or YYMAXFILL definition) becomes available only at the end of first
pass.

I isolate all (I hope so) these things and generate stubs for them,
which are filled later. I restructured output as follows: the whole
output consists of source and header, each of them is a list of
blocks (corresponding to re2c blocks in source file), each block
is a list of code fragments (which can be either regular strings
with code or stubs that will be filled later).

18 files changed:
re2c/Makefile.am
re2c/bootstrap/parser.cc
re2c/bootstrap/scanner.cc
re2c/code.cc
re2c/code.h
re2c/dfa.h
re2c/globals.h
re2c/main.cc
re2c/output.cc [new file with mode: 0644]
re2c/output.h [new file with mode: 0644]
re2c/parser.h
re2c/parser.y
re2c/re.h
re2c/scanner.h
re2c/scanner.re
re2c/test/error13.1.c
re2c/test/error14.1.c
re2c/test/error14.c

index 1e7f8cf26fc3731e51031b5635a774c557b39689..d699040049df3e6bcb0a1e1b9ba373113092a19c 100755 (executable)
@@ -3,11 +3,11 @@
 bin_PROGRAMS = re2c
 win_BINARIES = $(WINBUILDDIR)/re2c.exe
 re2c_SOURCES = code.cc dfa.cc main.cc parser.cc actions.cc scanner.re substr.cc range.cc \
-       translate.cc scanner.cc mbo_getopt.cc print.cc input_api.cc \
+       translate.cc scanner.cc mbo_getopt.cc print.cc input_api.cc output.cc \
        enc.cc utf8.cc utf8_range.cc utf8_regexp.cc utf16.cc utf16_range.cc utf16_regexp.cc range_suffix.cc \
        basics.h code.h code_names.h dfa.h enc.h indent.h input_api.h free_list.h globals.h ins.h \
        mbo_getopt.h parser.h print.h range.h range_suffix.h re.h \
-       scanner.h smart_ptr.h substr.h stream_lc.h token.h \
+       scanner.h smart_ptr.h substr.h stream_lc.h token.h output.h \
        utf16.h utf16_range.h utf16_regexp.h utf8.h utf8_range.h utf8_regexp.h
 BUILT_SOURCES = parser.cc scanner.cc
 
@@ -101,7 +101,6 @@ $(DOCS): re2c.ad
        a2x -f manpage re2c.ad
        mkdir -p htdocs
        asciidoc -o htdocs/manual.html re2c.ad
-       cp re2c.1 $(top_srcdir)/bootstrap/re2c.1
 else
 docs: $(DOCS)
 $(DOCS): $(top_srcdir)/bootstrap/re2c.1
index 051e3ae826e4af96fdfa41c1efb4f6281a80872c..2a7be60135d9893e0ed9dc1395927b6b0511850c 100644 (file)
@@ -184,16 +184,13 @@ void setup_rule(CondList *clist, Token *code)
        assert(clist);
        assert(code);
        context_check(clist);
-       if (bFirstPass)
+       for(CondList::const_iterator it = clist->begin(); it != clist->end(); ++it)
        {
-               for(CondList::const_iterator it = clist->begin(); it != clist->end(); ++it)
+               if (ruleSetupMap.find(*it) != ruleSetupMap.end())
                {
-                       if (ruleSetupMap.find(*it) != ruleSetupMap.end())
-                       {
-                               in->fatalf_at(code->line, "code to setup rule '%s' is already defined", it->c_str());
-                       }
-                       ruleSetupMap[*it] = std::make_pair(code->line, code->text.to_string());
+                       in->fatalf_at(code->line, "code to setup rule '%s' is already defined", it->c_str());
                }
+               ruleSetupMap[*it] = std::make_pair(code->line, code->text.to_string());
        }
        delete clist;
        delete code;
@@ -204,16 +201,13 @@ void default_rule(CondList *clist, Token *code)
        assert(clist);
        assert(code);
        context_check(clist);
-       if (bFirstPass)
+       for(CondList::const_iterator it = clist->begin(); it != clist->end(); ++it)
        {
-               for(CondList::const_iterator it = clist->begin(); it != clist->end(); ++it)
+               if (ruleDefaultMap.find(*it) != ruleDefaultMap.end())
                {
-                       if (ruleDefaultMap.find(*it) != ruleDefaultMap.end())
-                       {
-                               in->fatalf_at(code->line, "code to default rule '%s' is already defined", it->c_str());
-                       }
-                       ruleDefaultMap[*it] = code;
+                       in->fatalf_at(code->line, "code to default rule '%s' is already defined", it->c_str());
                }
+               ruleDefaultMap[*it] = code;
        }
        delete clist;
 }
@@ -611,12 +605,12 @@ static const yytype_int8 yyrhs[] =
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   186,   186,   188,   192,   196,   205,   214,   218,   222,
-     228,   236,   245,   254,   258,   263,   268,   274,   278,   286,
-     294,   299,   305,   311,   323,   335,   341,   349,   352,   359,
-     364,   373,   376,   384,   387,   394,   398,   405,   409,   420,
-     424,   431,   435,   450,   457,   461,   465,   469,   476,   484,
-     488,   492
+       0,   180,   180,   182,   186,   190,   199,   208,   212,   216,
+     222,   230,   239,   248,   252,   257,   262,   268,   272,   280,
+     288,   293,   299,   305,   317,   329,   335,   343,   346,   353,
+     358,   367,   370,   378,   381,   388,   392,   399,   403,   414,
+     418,   425,   429,   444,   451,   455,   459,   463,   470,   478,
+     482,   486
 };
 #endif
 
@@ -2231,27 +2225,22 @@ int yylex(){
 namespace re2c
 {
 
-void parse(Scanner& i, std::ostream& o, std::ostream* h)
+void parse(Scanner& i, Output & o)
 {
        std::map<std::string, smart_ptr<DFA> >  dfa_map;
        ScannerState rules_state;
 
        in = &i;
 
-       o << "/* Generated by re2c " PACKAGE_VERSION;
-       if (!bNoGenerationDate)
-       {
-               o << " on ";
-               time_t now = time(&now);
-               o.write(ctime(&now), 24);
-       }
-       o << " */\n";
-       o << sourceFileInfo;
-       
+       output_version_time (o.source);
+       o.source << sourceFileInfo;
+       output_version_time (o.header);
+
        Enc encodingOld = encoding;
        
        while ((parseMode = i.echo()) != Scanner::Stop)
        {
+               o.source.new_block ();
                bool bPrologBrace = false;
                ScannerState curr_state;
 
@@ -2388,16 +2377,20 @@ void parse(Scanner& i, std::ostream& o, std::ostream* h)
                                                }
                                        }
                                        dfa_map[it->first] = genCode(it->second.second);
-                                       dfa_map[it->first]->prepare();
+                                       dfa_map[it->first]->prepare(o.max_fill);
                                }
                                if (parseMode != Scanner::Rules && dfa_map.find(it->first) != dfa_map.end())
                                {
                                        dfa_map[it->first]->emit(o, topIndent, &specMap, it->first, !--nCount, bPrologBrace);
                                }
                        }
-                       if (!h && !bTypesDone)
+
+                       genTypes (o, specMap);
+                       if (o.header.status != OutputFile::NO_FILE)
                        {
-                               genTypes(typesInline, 0, specMap);
+                               o.header.insert_line_info ();
+                               o.header << "\n";
+                               o.header.insert_types ();
                        }
                }
                else
@@ -2412,7 +2405,7 @@ void parse(Scanner& i, std::ostream& o, std::ostream* h)
                                if (parseMode != Scanner::Reuse)
                                {
                                        dfa_map[""] = genCode(spec);
-                                       dfa_map[""]->prepare();
+                                       dfa_map[""]->prepare(o.max_fill);
                                }
                                if (parseMode != Scanner::Rules && dfa_map.find("") != dfa_map.end())
                                {
@@ -2420,7 +2413,7 @@ void parse(Scanner& i, std::ostream& o, std::ostream* h)
                                }
                        }
                }
-               o << sourceFileInfo;
+               o.source << sourceFileInfo;
                /* restore original char handling mode*/
                encoding = encodingOld;
        }
@@ -2447,11 +2440,6 @@ void parse(Scanner& i, std::ostream& o, std::ostream* h)
                }
        }
 
-       if (h)
-       {
-               genHeader(*h, 0, specMap);
-       }
-       
        parse_cleanup();
        in = NULL;
 }
index 85b9278d7775b79e7ee2eaeabb2681b6b2cef74f..47205749c90a9e1c06022c31ce0e0b396870a479 100644 (file)
@@ -1,5 +1,4 @@
-/* Generated by re2c 0.13.7.dev on Thu Apr 10 00:33:47 2014 */
-/* $Id$ */
+/* Generated by re2c 0.14.1.dev on Tue Feb 24 15:15:39 2015 */
 #include <stdlib.h>
 #include <string.h>
 #include <iostream>
@@ -233,10 +232,6 @@ yy21:
                                        {
                                                fatal("found 'rules:re2c' block without -r flag");
                                        }
-                                       if (bUsedYYMaxFill && bSinglePass)
-                                       {
-                                               fatal("found scanner block after YYMAXFILL declaration");
-                                       }
                                        tok = cursor;
                                        RETURN(Rules);
                                }
@@ -250,10 +245,6 @@ yy32:
                                        {
                                                fatal("found standard 're2c' block while using -r flag");
                                        }
-                                       if (bUsedYYMaxFill && bSinglePass)
-                                       {
-                                               fatal("found scanner block after YYMAXFILL declaration");
-                                       }
                                        if (!DFlag)
                                        {
                                                out.write((const char*)(tok), (const char*)(&cursor[-7]) - (const char*)(tok));
@@ -281,10 +272,6 @@ yy34:
                                                fatal("found 'use:re2c' block without -r flag");
                                        }
                                        reuse();
-                                       if (bUsedYYMaxFill && bSinglePass)
-                                       {
-                                               fatal("found scanner block after YYMAXFILL declaration");
-                                       }
                                        if (!DFlag)
                                        {
                                                out.write((const char*)(tok), (const char*)(&cursor[-11]) - (const char*)(tok));
@@ -307,17 +294,12 @@ yy42:
        if (yych != 'c') goto yy12;
        ++YYCURSOR;
        {
-                                       if (bUsedYYMaxFill)
-                                       {
-                                               fatal("cannot generate YYMAXFILL twice");
-                                       }
                                        if (!DFlag)
                                        {
-                                               out << "#define YYMAXFILL " << maxFill << std::endl;
+                                               out.insert_yymaxfill ();
                                        }
                                        tok = pos = cursor;
                                        ignore_eoc = true;
-                                       bUsedYYMaxFill = true;
                                        goto echo;
                                }
 yy50:
@@ -346,7 +328,7 @@ yy50:
        ++YYCURSOR;
        {
                                        tok = pos = cursor;
-                                       genGetStateGoto(out, topIndent, 0);
+                                       out.insert_state_goto (topIndent, 0);
                                        ignore_eoc = true;
                                        goto echo;
                                }
@@ -394,17 +376,13 @@ yy74:
        if (yych != 'c') goto yy12;
        ++YYCURSOR;
        {
-                                       if (bSinglePass)
-                                       {
-                                               fatal("cannot generate types inline in single pass mode");
-                                       }
                                        tok = pos = cursor;
                                        ignore_eoc = true;
-                                       if (bLastPass && !DFlag)
+                                       if (!DFlag)
                                        {
-                                               out << outputFileInfo;
+                                               out.insert_line_info ();
                                                out << "\n";
-                                               out << typesInline;
+                                               out.insert_types ();
                                                out << "\n";
                                                out << sourceFileInfo;
                                        }
index bc05fd6d74284c3d9c17e92faea5fae8153e7852..b398a8b56f8e27d06d81b62e635c9fac127cbd97 100644 (file)
@@ -2,11 +2,12 @@
 #include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
+#include <ctime>
 #include <ctype.h>
 #include <iomanip>
 #include <iostream>
 #include <sstream>
-#include <time.h>
+
 #include "code.h"
 #include "globals.h"
 #include "dfa.h"
@@ -39,7 +40,7 @@ std::string replaceParam(std::string str, const std::string& param, const _Ty& v
        return str;
 }
 
-static void genYYFill(std::ostream &o, uint, uint need)
+static void genYYFill(OutputFile & o, uint, uint need)
 {
        if (bUseYYFillParam)
        {
@@ -85,7 +86,7 @@ static std::string genGetCondition()
        }
 }
 
-static void genSetCondition(std::ostream& o, uint ind, const std::string& newcond)
+static void genSetCondition(OutputFile & o, uint ind, const std::string& newcond)
 {
        if (bUseYYSetConditionParam)
        {
@@ -171,22 +172,6 @@ static void doGen(const Go *g, const State *s, uint *bm, uint f, uint m)
        }
 }
 
-static void prt(std::ostream& o, const Go *g, const State *s)
-{
-       Span *b = g->span, *e = &b[g->nSpans];
-       uint lb = 0;
-
-       for (; b < e; ++b)
-       {
-               if (b->to == s)
-               {
-                       printSpan(o, lb, b->ub);
-               }
-
-               lb = b->ub;
-       }
-}
-
 static bool matches(const Go *g1, const State *s1, const Go *g2, const State *s2)
 {
        Span *b1 = g1->span, *e1 = &b1[g1->nSpans];
@@ -269,9 +254,9 @@ const BitMap *BitMap::find(const State *x)
        return NULL;
 }
 
-void BitMap::gen(std::ostream &o, uint ind, uint lb, uint ub)
+void BitMap::gen(OutputFile & o, uint ind, uint lb, uint ub)
 {
-       if (first && bLastPass && bUsedYYBitmap)
+       if (first && bUsedYYBitmap)
        {
                o << indent(ind) << "static const unsigned char " << mapCodeName["yybm"] << "[] = {";
 
@@ -311,39 +296,23 @@ void BitMap::gen(std::ostream &o, uint ind, uint lb, uint ub)
 
                                if (yybmHexTable)
                                {
-                                       prtHex(o, bm[j]);
+                                       prtHex(o.fragment (), bm[j]);
                                }
                                else
                                {
-                                       o << std::setw(3) << (uint)bm[j];
+                                       o << Setw (3) << (uint)bm[j];
                                }
                                o  << ", ";
                        }
                }
 
                o << "\n" << indent(ind) << "};\n";
-               /* stats(); */
                
                delete[] bm;
        }
 }
 
-void BitMap::stats()
-{
-       uint n = 0;
-
-       for (const BitMap *b = first; b; b = b->next)
-       {
-               prt(std::cerr, b->go, b->on);
-               std::cerr << std::endl;
-               ++n;
-       }
-
-       std::cerr << n << " bitmaps\n";
-       first = NULL;
-}
-
-static void genGoTo(std::ostream &o, uint ind, const State *from, const State *to, bool & readCh)
+static void genGoTo(OutputFile & o, uint ind, const State *from, const State *to, bool & readCh)
 {
        if (DFlag)
        {
@@ -361,7 +330,7 @@ static void genGoTo(std::ostream &o, uint ind, const State *from, const State *t
        vUsedLabels.insert(to->label);
 }
 
-static void genIf(std::ostream &o, uint ind, const char *cmp, uint v, bool &readCh)
+static void genIf(OutputFile & o, uint ind, const char *cmp, uint v, bool &readCh)
 {
        o << indent(ind) << "if (";
        if (readCh)
@@ -375,11 +344,11 @@ static void genIf(std::ostream &o, uint ind, const char *cmp, uint v, bool &read
        }
 
        o << " " << cmp << " ";
-       prtChOrHex(o, v);
+       prtChOrHex(o.fragment (), v);
        o << ") ";
 }
 
-static void need(std::ostream &o, uint ind, uint n, bool & readCh, bool bSetMarker)
+static void need(OutputFile & o, uint ind, uint n, bool & readCh, bool bSetMarker)
 {
        if (DFlag)
        {
@@ -441,8 +410,10 @@ static void need(std::ostream &o, uint ind, uint n, bool & readCh, bool bSetMark
        }
 }
 
-void Match::emit(std::ostream &o, uint ind, bool &readCh, const std::string&) const
+void Match::emit(Output & output, uint ind, bool &readCh, const std::string&) const
 {
+       OutputFile & o = output.source;
+
        if (DFlag)
        {
                return;
@@ -470,8 +441,10 @@ void Match::emit(std::ostream &o, uint ind, bool &readCh, const std::string&) co
        }
 }
 
-void Enter::emit(std::ostream &o, uint ind, bool &readCh, const std::string&) const
+void Enter::emit(Output & output, uint ind, bool &readCh, const std::string&) const
 {
+       OutputFile & o = output.source;
+
        if (state->link)
        {
                o << input_api.stmt_skip (ind);
@@ -493,8 +466,10 @@ void Enter::emit(std::ostream &o, uint ind, bool &readCh, const std::string&) co
        }
 }
 
-void Initial::emit(std::ostream &o, uint ind, bool &readCh, const std::string&) const
+void Initial::emit(Output & output, uint ind, bool &readCh, const std::string&) const
 {
+       OutputFile & o = output.source;
+
        if (!cFlag && !startLabelName.empty())
        {
                o << startLabelName << ":\n";
@@ -523,7 +498,7 @@ void Initial::emit(std::ostream &o, uint ind, bool &readCh, const std::string&)
 
        if (dFlag)
        {
-               o << indent(ind) << mapCodeName["YYDEBUG"] << "(" << label << ", " << input_api.expr_peek () << ");\n";
+               o << indent(ind) << mapCodeName["YYDEBUG"] << "(" << label << ", *" << mapCodeName["YYCURSOR"] << ");" << "\n";
        }
 
        if (state->link)
@@ -540,17 +515,16 @@ void Initial::emit(std::ostream &o, uint ind, bool &readCh, const std::string&)
        }
 }
 
-void Save::emit(std::ostream &o, uint ind, bool &readCh, const std::string&) const
+void Save::emit(Output & output, uint ind, bool &readCh, const std::string&) const
 {
+       OutputFile & o = output.source;
+
        if (DFlag)
        {
                return;
        }
 
-       if (bUsedYYAccept)
-       {
-               o << indent(ind) << mapCodeName["yyaccept"] << " = " << selector << ";\n";
-       }
+       o.insert_yyaccept_selector (ind, selector);
 
        if (state->link)
        {
@@ -579,7 +553,7 @@ Move::Move(State *s) : Action(s)
        ;
 }
 
-void Move::emit(std::ostream &, uint, bool &, const std::string&) const
+void Move::emit(Output &, uint, bool &, const std::string&) const
 {
        ;
 }
@@ -601,13 +575,12 @@ void Accept::genRuleMap()
        }
 }
 
-void Accept::emitBinary(std::ostream &o, uint ind, uint l, uint r, bool &readCh) const
+void Accept::emitBinary(OutputFile & o, uint ind, uint l, uint r, bool &readCh) const
 {
        if (l < r)
        {
                uint m = (l + r) >> 1;
 
-               assert(bUsedYYAccept);
                o << indent(ind) << "if (" << mapCodeName["yyaccept"] << (r == l+1 ? " == " : " <= ") << m << ") {\n";
                emitBinary(o, ++ind, l, m, readCh);
                o << indent(--ind) << "} else {\n";
@@ -620,8 +593,10 @@ void Accept::emitBinary(std::ostream &o, uint ind, uint l, uint r, bool &readCh)
        }
 }
 
-void Accept::emit(std::ostream &o, uint ind, bool &readCh, const std::string&) const
+void Accept::emit(Output & output, uint ind, bool &readCh, const std::string &) const
 {
+       OutputFile & o = output.source;
+
        if (mapRules.size() > 0)
        {
                bUsedYYMarker = true;
@@ -638,7 +613,7 @@ void Accept::emit(std::ostream &o, uint ind, bool &readCh, const std::string&) c
 
                if (mapRules.size() > 1)
                {
-                       bUsedYYAccept = true;
+                       o.set_used_yyaccept ();
 
                        if (gFlag && mapRules.size() >= cGotoThreshold)
                        {
@@ -703,8 +678,10 @@ Rule::Rule(State *s, RuleOp *r) : Action(s), rule(r)
        ;
 }
 
-void Rule::emit(std::ostream &o, uint ind, bool &, const std::string& condName) const
+void Rule::emit(Output & output, uint ind, bool &, const std::string& condName) const
 {
+       OutputFile & o = output.source;
+
        if (DFlag)
        {
                o << state->label << " [label=\"" << sourceFileInfo.fname << ":" << rule->code->line << "\"]\n";
@@ -741,10 +718,10 @@ void Rule::emit(std::ostream &o, uint ind, bool &, const std::string& condName)
                o << rule->code->text;
        }
        o << "\n";
-       o << outputFileInfo;
+       o.insert_line_info ();
 }
 
-static void doLinear(std::ostream &o, uint ind, Span *s, uint n, const State *from, const State *next, bool &readCh, uint mask)
+static void doLinear(OutputFile & o, uint ind, Span *s, uint n, const State *from, const State *next, bool &readCh, uint mask)
 {
        for (;;)
        {
@@ -819,12 +796,12 @@ static void doLinear(std::ostream &o, uint ind, Span *s, uint n, const State *fr
        }
 }
 
-void Go::genLinear(std::ostream &o, uint ind, const State *from, const State *next, bool &readCh, uint mask) const
+void Go::genLinear(OutputFile & o, uint ind, const State *from, const State *next, bool &readCh, uint mask) const
 {
        doLinear(o, ind, span, nSpans, from, next, readCh, mask);
 }
 
-static void printDotCharInterval(std::ostream &o, uint lastPrintableChar, uint chr, const State *from, const State *to, bool multipleIntervals)
+static void printDotCharInterval(OutputFile & o, uint lastPrintableChar, uint chr, const State *from, const State *to, bool multipleIntervals)
 {
        o << from->label << " -> " << to->label;
        o << " [label=";
@@ -843,23 +820,23 @@ static void printDotCharInterval(std::ostream &o, uint lastPrintableChar, uint c
                                o << "]\n";
                                o << from->label << " -> " << to->label;
                                o << " [label=";
-                               prtChOrHex(o, ++chr);
+                               prtChOrHex(o.fragment (), ++chr);
                        }
                }
                else
                {
-                       prtChOrHex(o, chr);
+                       prtChOrHex(o.fragment (), chr);
                }
        }
        else
        {
-               prtChOrHex(o, chr);
+               prtChOrHex(o.fragment (), chr);
        }
 
        o << "]";
 }
 
-static bool genCases(std::ostream &o, uint ind, uint lb, Span *s, bool &newLine, uint mask, const State *from, const State *to)
+static bool genCases(OutputFile & o, uint ind, uint lb, Span *s, bool &newLine, uint mask, const State *from, const State *to)
 {
        bool used = false;
        uint lastPrintableChar = 0;
@@ -897,7 +874,7 @@ static bool genCases(std::ostream &o, uint ind, uint lb, Span *s, bool &newLine,
                                else
                                {
                                        o << indent(ind) << "case ";
-                                       prtChOrHex(o, lb);
+                                       prtChOrHex(o.fragment (), lb);
                                        o << ":";
                                        if (dFlag && encoding.is(Enc::EBCDIC))
                                        {
@@ -931,7 +908,7 @@ static bool genCases(std::ostream &o, uint ind, uint lb, Span *s, bool &newLine,
        return used;
 }
 
-void Go::genSwitch(std::ostream &o, uint ind, const State *from, const State *next, bool &readCh, uint mask) const
+void Go::genSwitch(OutputFile & o, uint ind, const State *from, const State *next, bool &readCh, uint mask) const
 {
        bool newLine = true;
 
@@ -1031,7 +1008,7 @@ void Go::genSwitch(std::ostream &o, uint ind, const State *from, const State *ne
        }
 }
 
-static void doBinary(std::ostream &o, uint ind, Span *s, uint n, const State *from, const State *next, bool &readCh, uint mask)
+static void doBinary(OutputFile & o, uint ind, Span *s, uint n, const State *from, const State *next, bool &readCh, uint mask)
 {
        if (n <= 4)
        {
@@ -1050,7 +1027,7 @@ static void doBinary(std::ostream &o, uint ind, Span *s, uint n, const State *fr
        }
 }
 
-void Go::genBinary(std::ostream &o, uint ind, const State *from, const State *next, bool &readCh, uint mask) const
+void Go::genBinary(OutputFile & o, uint ind, const State *from, const State *next, bool &readCh, uint mask) const
 {
        if (mask)
        {
@@ -1074,7 +1051,7 @@ void Go::genBinary(std::ostream &o, uint ind, const State *from, const State *ne
        }
 }
 
-void Go::genBase(std::ostream &o, uint ind, const State *from, const State *next, bool &readCh, uint mask) const
+void Go::genBase(OutputFile & o, uint ind, const State *from, const State *next, bool &readCh, uint mask) const
 {
        if ((mask ? wSpans : nSpans) == 0)
        {
@@ -1125,7 +1102,7 @@ void Go::genBase(std::ostream &o, uint ind, const State *from, const State *next
        }
 }
 
-void Go::genCpGoto(std::ostream &o, uint ind, const State *from, const State *next, bool &readCh) const
+void Go::genCpGoto(OutputFile & o, uint ind, const State *from, const State *next, bool &readCh) const
 {
        std::string sYych;
        
@@ -1181,7 +1158,7 @@ void Go::genCpGoto(std::ostream &o, uint ind, const State *from, const State *ne
        o << indent(--ind) << "}\n";
 }
 
-void Go::genGoto(std::ostream &o, uint ind, const State *from, const State *next, bool &readCh)
+void Go::genGoto(OutputFile & o, uint ind, const State *from, const State *next, bool &readCh)
 {
        if ((gFlag || (encoding.szCodeUnit() > 1)) && wSpans == ~0u)
        {
@@ -1271,7 +1248,7 @@ void Go::genGoto(std::ostream &o, uint ind, const State *from, const State *next
                                        o << "if (" << mapCodeName["yybm"] << "[" << b->i << "+" << sYych << "] & ";
                                        if (yybmHexTable)
                                        {
-                                               prtHex(o, b->m);
+                                               prtHex(o.fragment (), b->m);
                                        }
                                        else
                                        {
@@ -1291,8 +1268,10 @@ void Go::genGoto(std::ostream &o, uint ind, const State *from, const State *next
        genBase(o, ind, from, next, readCh, 0);
 }
 
-void State::emit(std::ostream &o, uint ind, bool &readCh, const std::string& condName) const
+void State::emit(Output & output, uint ind, bool &readCh, const std::string& condName) const
 {
+       OutputFile & o = output.source;
+
        if (vUsedLabels.count(label))
        {
                o << labelPrefix << label << ":\n";
@@ -1305,7 +1284,7 @@ void State::emit(std::ostream &o, uint ind, bool &readCh, const std::string& con
        {
                o << input_api.stmt_backupctx (ind);
        }
-       action->emit(o, ind, readCh, condName);
+       action->emit(output, ind, readCh, condName);
 }
 
 static uint merge(Span *x0, State *fg, State *bg)
@@ -1619,7 +1598,7 @@ void DFA::findBaseState()
        delete [] span;
 }
 
-void DFA::prepare()
+void DFA::prepare(uint & max_fill)
 {
        State *s;
        uint i;
@@ -1634,9 +1613,9 @@ void DFA::prepare()
        for (s = head; s; s = s->next)
        {
                s->depth = maxDist(s);
-               if (maxFill < s->depth)
+               if (max_fill < s->depth)
                {
-                       maxFill = s->depth;
+                       max_fill = s->depth;
                }
                if (s->rule && s->rule->accept >= nRules)
                {
@@ -1758,15 +1737,11 @@ void DFA::prepare()
 }
 
 
-void DFA::emit(std::ostream &o, uint& ind, const RegExpMap* specMap, const std::string& condName, bool isLastCond, bool& bPrologBrace)
+void DFA::emit(Output & output, uint& ind, const RegExpMap* specMap, const std::string& condName, bool isLastCond, bool& bPrologBrace)
 {
+       OutputFile & o = output.source;
        bool bProlog = (!cFlag || !bWroteCondCheck);
 
-       if (!cFlag)
-       {
-               bUsedYYAccept = false;
-       }
-       
        // In -c mode, the prolog needs its own label separate from start_label.
        // prolog_label is before the condition branch (GenCondGoto). It is
        // equivalent to startLabelName.
@@ -1801,13 +1776,13 @@ void DFA::emit(std::ostream &o, uint& ind, const RegExpMap* specMap, const std::
        // Save 'next_fill_index' and compute information about code generation
        // while writing to null device.
        uint save_fill_index = next_fill_index;
-       null_stream  null_dev;
+       Output null_dev (NULL, NULL);
 
        for (s = head; s; s = s->next)
        {
                bool readCh = false;
                s->emit(null_dev, ind, readCh, condName);
-               s->go.genGoto(null_dev, ind, s, s->next, readCh);
+               s->go.genGoto(null_dev.source, ind, s, s->next, readCh);
        }
        if (last_fill_index < next_fill_index)
        {
@@ -1818,14 +1793,15 @@ void DFA::emit(std::ostream &o, uint& ind, const RegExpMap* specMap, const std::
        // Generate prolog
        if (bProlog)
        {
-               o << "\n" << outputFileInfo;
+               o << "\n";
+               o.insert_line_info ();
 
                if (DFlag)
                {
                        bPrologBrace = true;
                        o << "digraph re2c {\n";
                }
-               else if ((!fFlag && bUsedYYAccept)
+               else if ((!fFlag && o.get_used_yyaccept ())
                ||  (!fFlag && bEmitYYCh)
                ||  (bFlag && !cFlag && BitMap::first)
                ||  (cFlag && !bWroteCondCheck && gFlag && !specMap->empty())
@@ -1846,10 +1822,7 @@ void DFA::emit(std::ostream &o, uint& ind, const RegExpMap* specMap, const std::
                        {
                                o << indent(ind) << mapCodeName["YYCTYPE"] << " " << mapCodeName["yych"] << ";\n";
                        }
-                       if (bUsedYYAccept)
-                       {
-                               o << indent(ind) << "unsigned int " << mapCodeName["yyaccept"] << " = 0;\n";
-                       }
+                       o.insert_yyaccept_init (ind);
                }
                else
                {
@@ -1863,7 +1836,7 @@ void DFA::emit(std::ostream &o, uint& ind, const RegExpMap* specMap, const std::
        if (bProlog)
        {
                genCondTable(o, ind, *specMap);
-               genGetStateGoto(o, ind, prolog_label);
+               o.insert_state_goto (ind, prolog_label);
                if (cFlag && !DFlag)
                {
                        if (vUsedLabels.count(prolog_label))
@@ -1911,7 +1884,7 @@ void DFA::emit(std::ostream &o, uint& ind, const RegExpMap* specMap, const std::
        for (s = head; s; s = s->next)
        {
                bool readCh = false;
-               s->emit(o, ind, readCh, condName);
+               s->emit(output, ind, readCh, condName);
                s->go.genGoto(o, ind, s, s->next, readCh);
        }
 
@@ -1935,7 +1908,7 @@ void DFA::emit(std::ostream &o, uint& ind, const RegExpMap* specMap, const std::
        bUseStartLabel = false;
 }
 
-static void genGetStateGotoSub(std::ostream &o, uint ind, uint start_label, int cMin, int cMax)
+static void output_state_goto_sub (OutputFragment & o, uint ind, uint start_label, int cMin, int cMax)
 {
        if (cMin == cMax)
        {
@@ -1953,86 +1926,83 @@ static void genGetStateGotoSub(std::ostream &o, uint ind, uint start_label, int
                int cMid = cMin + ((cMax - cMin + 1) / 2);
 
                o << indent(ind) << "if (" << genGetState() << " < " << cMid << ") {\n";
-               genGetStateGotoSub(o, ind + 1, start_label, cMin, cMid - 1);
+               output_state_goto_sub (o, ind + 1, start_label, cMin, cMid - 1);
                o << indent(ind) << "} else {\n";
-               genGetStateGotoSub(o, ind + 1, start_label, cMid, cMax);
+               output_state_goto_sub (o, ind + 1, start_label, cMid, cMax);
                o << indent(ind) << "}\n";
        }
 }
 
-void genGetStateGoto(std::ostream &o, uint& ind, uint start_label)
+void output_state_goto (OutputFragment & o, uint start_label)
 {
-       if (fFlag && !bWroteGetState)
+       uint ind = o.indent;
+       if (gFlag)
        {
-               vUsedLabels.insert(start_label);
-               if (gFlag)
+               o << indent(ind++) << "static void *" << mapCodeName["yystable"] << "[" << "] = {\n";
+
+               for (size_t i=0; i<last_fill_index; ++i)
                {
-                       o << indent(ind++) << "static void *" << mapCodeName["yystable"] << "[" << "] = {\n";
+                       o << indent(ind) << "&&" << mapCodeName["yyFillLabel"] << i << ",\n";
+               }
 
-                       for (size_t i=0; i<last_fill_index; ++i)
-                       {
-                               o << indent(ind) << "&&" << mapCodeName["yyFillLabel"] << i << ",\n";
-                       }
+               o << indent(--ind) << "};\n";
+               o << "\n";
 
-                       o << indent(--ind) << "};\n";
-                       o << "\n";
+               o << indent(ind) << "if (" << genGetState();
+               if (bUseStateAbort)
+               {
+                       o << " == -1) {\n";
+               }
+               else
+               {
+                       o << " < 0) {\n";
+               }
+               o << indent(++ind) << "goto " << labelPrefix << start_label << ";\n";
+               if (bUseStateAbort)
+               {
+                       o << indent(--ind) << "} else if (" << genGetState() << " < -1) {\n";
+                       o << indent(++ind) << "abort();\n";
+               }
+               o << indent(--ind) << "}\n";
 
-                       o << indent(ind) << "if (" << genGetState();
-                       if (bUseStateAbort)
-                       {
-                               o << " == -1) {\n";
-                       }
-                       else
-                       {
-                               o << " < 0) {\n";
-                       }
-                       o << indent(++ind) << "goto " << labelPrefix << start_label << ";\n";
-                       if (bUseStateAbort)
-                       {
-                               o << indent(--ind) << "} else if (" << genGetState() << " < -1) {\n";
-                               o << indent(++ind) << "abort();\n";
-                       }
-                       o << indent(--ind) << "}\n";
+               o << indent(ind) << "goto *" << mapCodeName["yystable"] << "[" << genGetState() << "];\n";
 
-                       o << indent(ind) << "goto *" << mapCodeName["yystable"] << "[" << genGetState() << "];\n";
+       }
+       else if (bFlag)
+       {
+               output_state_goto_sub (o, ind, start_label, -1, last_fill_index-1);
+               if (bUseStateAbort)
+               {
+                       o << indent(ind) << "abort();\n";
                }
-               else if (bFlag)
+       }
+       else
+       {
+               o << indent(ind) << "switch (" << genGetState() << ") {\n";
+               if (bUseStateAbort)
                {
-                       genGetStateGotoSub(o, ind, start_label, -1, last_fill_index-1);
-                       if (bUseStateAbort)
-                       {
-                               o << indent(ind) << "abort();\n";
-                       }
+                       o << indent(ind) << "default: abort();\n";
+                       o << indent(ind) << "case -1: goto " << labelPrefix << start_label << ";\n";
                }
                else
                {
-                       o << indent(ind) << "switch (" << genGetState() << ") {\n";
-                       if (bUseStateAbort)
-                       {
-                               o << indent(ind) << "default: abort();\n";
-                               o << indent(ind) << "case -1: goto " << labelPrefix << start_label << ";\n";
-                       }
-                       else
-                       {
-                               o << indent(ind) << "default: goto " << labelPrefix << start_label << ";\n";
-                       }
-       
-                       for (size_t i=0; i<last_fill_index; ++i)
-                       {
-                               o << indent(ind) << "case " << i << ": goto " << mapCodeName["yyFillLabel"] << i << ";\n";
-                       }
-       
-                       o << indent(ind) << "}\n";
+                       o << indent(ind) << "default: goto " << labelPrefix << start_label << ";\n";
                }
-               if (bUseStateNext)
+
+               for (size_t i=0; i<last_fill_index; ++i)
                {
-                       o << mapCodeName["yyNext"] << ":\n";
+                       o << indent(ind) << "case " << i << ": goto " << mapCodeName["yyFillLabel"] << i << ";\n";
                }
-               bWroteGetState = true;
+
+               o << indent(ind) << "}\n";
+       }
+       if (bUseStateNext)
+       {
+               o << mapCodeName["yyNext"] << ":\n";
        }
 }
 
-void genCondTable(std::ostream &o, uint ind, const RegExpMap& specMap)
+void genCondTable(OutputFile & o, uint ind, const RegExpMap& specMap)
 {
        if (cFlag && !bWroteCondCheck && gFlag && specMap.size())
        {
@@ -2053,7 +2023,7 @@ void genCondTable(std::ostream &o, uint ind, const RegExpMap& specMap)
        }
 }
 
-static void genCondGotoSub(std::ostream &o, uint ind, RegExpIndices& vCondList, uint cMin, uint cMax)
+static void genCondGotoSub(OutputFile & o, uint ind, RegExpIndices& vCondList, uint cMin, uint cMax)
 {
        if (cMin == cMax)
        {
@@ -2071,7 +2041,7 @@ static void genCondGotoSub(std::ostream &o, uint ind, RegExpIndices& vCondList,
        }
 }
 
-void genCondGoto(std::ostream &o, uint ind, const RegExpMap& specMap)
+void genCondGoto(OutputFile & o, uint ind, const RegExpMap& specMap)
 {
        if (cFlag && !bWroteCondCheck && specMap.size())
        {
@@ -2113,47 +2083,70 @@ void genCondGoto(std::ostream &o, uint ind, const RegExpMap& specMap)
        }
 }
 
-void genTypes(std::string& o, uint ind, const RegExpMap& specMap)
+void genTypes(Output & output, const RegExpMap& specMap)
 {
-       o.clear();
-
-       o += indent(ind++) + "enum " + mapCodeName["YYCONDTYPE"] + " {\n";
-
-       RegExpIndices  vCondList(specMap.size());
-
+       output.types.resize (specMap.size());
        for(RegExpMap::const_iterator itSpecMap = specMap.begin(); itSpecMap != specMap.end(); ++itSpecMap)
        {
                // If an entry is < 0 then we did the 0/empty correction twice.
                assert(itSpecMap->second.first >= 0);
-               vCondList[itSpecMap->second.first] = itSpecMap->first;
+               output.types[itSpecMap->second.first] = itSpecMap->first;
        }
+}
 
-       for(RegExpIndices::const_iterator itCondType = vCondList.begin(); itCondType != vCondList.end(); ++itCondType)
+void output_yyaccept_init (OutputFragment & o, bool used_yyaccept)
+{
+       if (used_yyaccept)
        {
-               o += indent(ind) + condEnumPrefix + *itCondType + ",\n";
+               o << indent (o.indent) << "unsigned int " << mapCodeName["yyaccept"] << " = 0;\n";
        }
+}
+
+void output_yyaccept_selector (OutputFragment & o, bool used_yyaccept)
+{
+       if (used_yyaccept)
+       {
+               o << indent (o.indent) << mapCodeName["yyaccept"] << " = " << o.info.yyaccept_selector << ";\n";
+       }
+}
 
-       o += indent(--ind) + "};\n";
+void output_yymaxfill (OutputFragment & o, uint max_fill)
+{
+       o << "#define YYMAXFILL " << max_fill << "\n";
+}
+
+void output_line_info (OutputFragment & o, uint line_number, const char * filename)
+{
+       if (!iFlag)
+       {
+               o << "#line " << line_number << " \"" << filename << "\"\n";
+       }
+}
+
+void output_types (OutputFragment & o, const std::vector<std::string> & types)
+{
+       uint ind = o.indent;
+       o << indent (ind++) << "enum " << mapCodeName["YYCONDTYPE"] << " {\n";
+       for (unsigned int i = 0; i < types.size (); ++i)
+       {
+               o << indent (ind) << condEnumPrefix << types[i] << ",\n";
+       }
+       o << indent (--ind) << "};\n";
 }
 
-void genHeader(std::ostream &o, uint ind, const RegExpMap& specMap)
+void output_version_time (OutputFile & o)
 {
        o << "/* Generated by re2c " PACKAGE_VERSION;
        if (!bNoGenerationDate)
        {
                o << " on ";
-               time_t now = time(&now);
-               o.write(ctime(&now), 24);
+               time_t now = time (NULL);
+               o.write (ctime (&now), 24);
        }
-       o << " */\n";
-       o << headerFileInfo;
-       o << "\n";
-       // now the type(s)
-       genTypes(typesInline, ind, specMap);
-       o << typesInline;
+       o << "*/" << "\n";
 }
 
-std::ostream& operator << (std::ostream& o, const file_info& li)
+OutputFragment & operator << (OutputFragment & o, const file_info& li)
 {
        if (li.ln && !iFlag)
        {
@@ -2397,32 +2390,26 @@ void Scanner::config(const Str& cfg, const Str& val)
                bUseYYSetStateParam = false;
        }
        else if (mapVariableKeys.find(cfg.to_string()) != mapVariableKeys.end())
-    {
-       if ((bFirstPass || rFlag) && !mapCodeName.insert(
-                       std::make_pair(cfg.to_string().substr(sizeof("variable:") - 1), strVal)
-                       ).second)
-       {
+       {
+               if (!mapCodeName.insert(std::make_pair(cfg.to_string().substr(sizeof("variable:") - 1), strVal)).second)
+               {
                        fatalf("variable '%s' already being used and cannot be changed", cfg.to_string().c_str());
-       }
-    }
+               }
+       }
        else if (mapDefineKeys.find(cfg.to_string()) != mapDefineKeys.end())
-    {
-       if ((bFirstPass || rFlag) && !mapCodeName.insert(
-                       std::make_pair(cfg.to_string().substr(sizeof("define:") - 1), strVal)
-                       ).second)
-       {
-                       fatalf("define '%s' already being used and cannot be changed", cfg.to_string().c_str());
-               }
-    }
+       {
+               if (!mapCodeName.insert(std::make_pair(cfg.to_string().substr(sizeof("define:") - 1), strVal)).second)
+               {
+                       fatalf("define '%s' already being used and cannot be changed", cfg.to_string().c_str());
+               }
+       }
        else if (mapLabelKeys.find(cfg.to_string()) != mapLabelKeys.end())
-    {
-       if ((bFirstPass || rFlag) && !mapCodeName.insert(
-                       std::make_pair(cfg.to_string().substr(sizeof("label:") - 1), strVal)
-                       ).second)
-       {
+       {
+               if (!mapCodeName.insert(std::make_pair(cfg.to_string().substr(sizeof("label:") - 1), strVal)).second)
+               {
                        fatalf("label '%s' already being used and cannot be changed", cfg.to_string().c_str());
-       }
-    }
+               }
+       }
        else
        {
                std::string msg = "unrecognized configuration name '";
@@ -2440,7 +2427,7 @@ ScannerState::ScannerState()
 {
 }
 
-Scanner::Scanner(std::istream& i, std::ostream& o)
+Scanner::Scanner(std::istream& i, OutputFile & o)
        : ScannerState(), in(i), out(o)
 {
 }
@@ -2510,7 +2497,6 @@ void Scanner::set_in_parse(bool new_in_parse)
 
 void Scanner::fatal_at(uint line, uint ofs, const char *msg) const
 {
-       out.flush();
        std::cerr << "re2c: error: "
                << "line " << line << ", column " << (tchar + ofs + 1) << ": "
                << msg << std::endl;
index 12b735e50c2783475f005174ff75a2c31a9221f7..1227fb229cc1237fd6b188cba565e3459d4b51a9 100755 (executable)
@@ -22,8 +22,7 @@ public:
 public:
        static const BitMap *find(const Go*, const State*);
        static const BitMap *find(const State*);
-       static void gen(std::ostream&, uint ind, uint, uint);
-       static void stats();
+       static void gen(OutputFile &, uint ind, uint, uint);
        BitMap(const Go*, const State*);
        ~BitMap();
 
index 66c391a4293107a5bf85724d324950a449652d69..0f4499bb3a4972d93a17bed3c351fa8191370be8 100644 (file)
@@ -23,7 +23,7 @@ public:
        Action(State*);
        virtual ~Action();
 
-       virtual void emit(std::ostream&, uint, bool&, const std::string&) const = 0;
+       virtual void emit(Output &, uint, bool&, const std::string&) const = 0;
        virtual bool isRule() const;
        virtual bool isMatch() const;
        virtual bool isInitial() const;
@@ -47,7 +47,7 @@ class Match: public Action
 {
 public:
        Match(State*);
-       void emit(std::ostream&, uint, bool&, const std::string&) const;
+       void emit(Output &, uint, bool&, const std::string&) const;
        bool isMatch() const;
 };
 
@@ -58,7 +58,7 @@ public:
 
 public:
        Enter(State*, uint);
-       void emit(std::ostream&, uint, bool&, const std::string&) const;
+       void emit(Output &, uint, bool&, const std::string&) const;
 };
 
 class Initial: public Enter
@@ -68,7 +68,7 @@ public:
 
 public:
        Initial(State*, uint, bool);
-       void emit(std::ostream&, uint, bool&, const std::string&) const;
+       void emit(Output &, uint, bool&, const std::string&) const;
        bool isInitial() const;
 };
 
@@ -80,7 +80,7 @@ public:
 
 public:
        Save(State*, uint);
-       void emit(std::ostream&, uint, bool&, const std::string&) const;
+       void emit(Output &, uint, bool&, const std::string&) const;
        bool isMatch() const;
 };
 
@@ -89,7 +89,7 @@ class Move: public Action
 
 public:
        Move(State*);
-       void emit(std::ostream&, uint, bool&, const std::string&) const;
+       void emit(Output &, uint, bool&, const std::string&) const;
 };
 
 class Accept: public Action
@@ -105,8 +105,8 @@ public:
 
 public:
        Accept(State*, uint, uint*, State**);
-       void emit(std::ostream&, uint, bool&, const std::string&) const;
-       void emitBinary(std::ostream &o, uint ind, uint l, uint r, bool &readCh) const;
+       void emit(Output &, uint, bool&, const std::string&) const;
+       void emitBinary(OutputFile & o, uint ind, uint l, uint r, bool &readCh) const;
        void genRuleMap();
 
 #ifdef PEDANTIC
@@ -134,7 +134,7 @@ public:
 
 public:
        Rule(State*, RuleOp*);
-       void emit(std::ostream&, uint, bool&, const std::string&) const;
+       void emit(Output &, uint, bool&, const std::string&) const;
        bool isRule() const;
 
 #ifdef PEDANTIC
@@ -185,12 +185,12 @@ public:
        Span    *span;
 
 public:
-       void genGoto(  std::ostream&, uint ind, const State *from, const State *next, bool &readCh);
-       void genBase(  std::ostream&, uint ind, const State *from, const State *next, bool &readCh, uint mask) const;
-       void genLinear(std::ostream&, uint ind, const State *from, const State *next, bool &readCh, uint mask) const;
-       void genBinary(std::ostream&, uint ind, const State *from, const State *next, bool &readCh, uint mask) const;
-       void genSwitch(std::ostream&, uint ind, const State *from, const State *next, bool &readCh, uint mask) const;
-       void genCpGoto(std::ostream&, uint ind, const State *from, const State *next, bool &readCh) const;
+       void genGoto(OutputFile &, uint ind, const State *from, const State *next, bool &readCh);
+       void genBase(OutputFile &, uint ind, const State *from, const State *next, bool &readCh, uint mask) const;
+       void genLinear(OutputFile &, uint ind, const State *from, const State *next, bool &readCh, uint mask) const;
+       void genBinary(OutputFile &, uint ind, const State *from, const State *next, bool &readCh, uint mask) const;
+       void genSwitch(OutputFile &, uint ind, const State *from, const State *next, bool &readCh, uint mask) const;
+       void genCpGoto(OutputFile &, uint ind, const State *from, const State *next, bool &readCh) const;
        void compact();
        void unmap(Go*, const State*);
 };
@@ -215,7 +215,7 @@ public:
 public:
        State();
        ~State();
-       void emit(std::ostream&, uint, bool&, const std::string&) const;
+       void emit(Output &, uint, bool&, const std::string&) const;
        friend std::ostream& operator<<(std::ostream&, const State&);
        friend std::ostream& operator<<(std::ostream&, const State*);
 
@@ -268,8 +268,8 @@ public:
 
        void findSCCs();
        void findBaseState();
-       void prepare();
-       void emit(std::ostream&, uint&, const RegExpMap*, const std::string&, bool, bool&);
+       void prepare(uint &);
+       void emit(Output &, uint&, const RegExpMap*, const std::string&, bool, bool&);
 
        friend std::ostream& operator<<(std::ostream&, const DFA&);
        friend std::ostream& operator<<(std::ostream&, const DFA*);
index 5a78315c731718eba5f3ae5c2c8e4e4f0c318ca4..92c86031d3bf7f5f9e82bb0dca6ad98a883324db 100644 (file)
@@ -17,8 +17,6 @@ namespace re2c
 enum BUFFERSIZE { BSIZE = 8192};
 
 extern file_info sourceFileInfo;
-extern file_info outputFileInfo;
-extern file_info headerFileInfo;
 
 extern bool bFlag;
 extern bool cFlag;
@@ -33,13 +31,6 @@ extern bool sFlag;
 extern bool tFlag;
 
 extern bool bNoGenerationDate;
-
-extern bool bSinglePass;
-extern bool bFirstPass;
-extern bool bLastPass;
-
-extern bool bUsedYYAccept;
-extern bool bUsedYYMaxFill;
 extern bool bUsedYYMarker;
 extern bool bUsedYYBitmap;
 
@@ -57,7 +48,6 @@ extern std::string yyFillLength;
 extern std::string yySetConditionParam;
 extern std::string yySetStateParam;
 extern std::string yySetupRule;
-extern uint maxFill;
 extern uint next_label;
 extern uint cGotoThreshold;
 
@@ -81,7 +71,6 @@ extern bool bWroteGetState;
 extern bool bWroteCondCheck;
 extern bool bCaseInsensitive;
 extern bool bCaseInverted;
-extern bool bTypesDone;
 
 extern const uint asc2asc[256];
 extern const uint asc2ebc[256];
@@ -91,7 +80,6 @@ extern uint next_fill_index;
 extern uint last_fill_index;
 extern std::set<uint> vUsedLabels;
 extern CodeNames mapCodeName;
-extern std::string typesInline;
 
 extern Enc encoding;
 extern InputAPI input_api;
index cb07d15e21d015095774560c31da7b0e4da2e269..8d0e665015a381194a5982d2ed4f9a542d0a6e13 100644 (file)
 #include "globals.h"
 #include "parser.h"
 #include "dfa.h"
+#include "enc.h"
 #include "mbo_getopt.h"
 
 namespace re2c
 {
 
 file_info sourceFileInfo;
-file_info outputFileInfo;
-file_info headerFileInfo;
 
 bool bFlag = false;
 bool cFlag = false;
@@ -35,16 +34,8 @@ bool sFlag = false;
 bool tFlag = false;
 
 bool bNoGenerationDate = false;
-
-bool bSinglePass = false;
-bool bFirstPass  = true;
-bool bLastPass   = false;
 bool bUsedYYBitmap  = false;
-
-bool bUsedYYAccept  = false;
-bool bUsedYYMaxFill = false;
 bool bUsedYYMarker  = true;
-
 bool bEmitYYCh       = true;
 bool bUseStartLabel  = false;
 bool bUseStateNext   = false;
@@ -71,7 +62,6 @@ std::string yyFillLength("@@");
 std::string yySetConditionParam("@@");
 std::string yySetStateParam("@@");
 std::string yySetupRule("");
-uint maxFill = 1;
 uint next_label = 0;
 uint cGotoThreshold = 9;
 
@@ -83,7 +73,6 @@ bool bWroteGetState = false;
 bool bWroteCondCheck = false;
 bool bCaseInsensitive = false;
 bool bCaseInverted = false;
-bool bTypesDone = false;
 
 Enc encoding;
 InputAPI input_api;
@@ -92,7 +81,6 @@ uint next_fill_index = 0;
 uint last_fill_index = 0;
 std::set<uint> vUsedLabels;
 CodeNames mapCodeName;
-std::string typesInline;
 
 free_list<RegExp*> RegExp::vFreeList;
 free_list<Range*>  Range::vFreeList;
@@ -125,7 +113,7 @@ static const mbo_opt_struct OPTIONS[] =
        mbo_opt_struct('w', 0, "wide-chars"),
        mbo_opt_struct('x', 0, "utf-16"),
        mbo_opt_struct('8', 0, "utf-8"),
-       mbo_opt_struct('1', 0, "single-pass"),
+       mbo_opt_struct('1', 0, "deprecated, single-pass"),
        mbo_opt_struct(10,  0, "no-generation-date"),
        mbo_opt_struct(11,  0, "case-insensitive"),
        mbo_opt_struct(12,  0, "case-inverted"),
@@ -200,7 +188,8 @@ static void usage()
        "                        re2c assumes that input character size is 1 byte. This switch is\n"
        "                        incompatible with -e, -w, -x and -u."
        "\n"
-       "-1     --single-pass    Force single pass generation, this cannot be combined\n"
+       "-1     --single-pass    Deprecated.\n"
+        "                        Force single pass generation, this cannot be combined\n"
        "                        with -f and disables YYMAXFILL generation prior to last\n"
        "                        re2c block.\n"
        "\n"
@@ -306,7 +295,6 @@ int main(int argc, char *argv[])
                        break;
                        
                        case '1':
-                       bSinglePass = true;
                        break;
 
                        case 'v':
@@ -416,10 +404,6 @@ int main(int argc, char *argv[])
                }
        }
 
-       if ((bFlag || fFlag) && bSinglePass) {
-               std::cerr << "re2c: error: Cannot combine -1 and -b or -f switch\n";
-               return 1;
-       }
        if (!cFlag && headerFileName)
        {
                std::cerr << "re2c: error: Can only output a header file when using -c switch\n";
@@ -462,58 +446,29 @@ int main(int argc, char *argv[])
                return 1;
        }
 
-       // set up the output stream
-       re2c::ofstream_lc output;
-       re2c::ofstream_lc header;
-
-       if (outputFileName == 0 || (sourceFileName[0] == '-' && sourceFileName[1] == '\0'))
+       // set up the output streams
+       if (outputFileName == NULL || (sourceFileName[0] == '-' && sourceFileName[1] == '\0'))
        {
                outputFileName = "<stdout>";
-               output.open(stdout);
        }
-       else if (!output.open(outputFileName).is_open())
+       re2c::Output output (outputFileName, headerFileName);
+       if (output.source.status == OutputFile::FAIL_OPEN)
        {
                cerr << "re2c: error: cannot open " << outputFileName << "\n";
                return 1;
        }
-       if (headerFileName)
+       if (output.header.status == OutputFile::FAIL_OPEN)
        {
-               if (!header.open(headerFileName).is_open())
-               {
-                       cerr << "re2c: error: cannot open " << headerFileName << "\n";
-                       return 1;
-               }
-               headerFileInfo = file_info(headerFileName, &header);
+               cerr << "re2c: error: cannot open " << headerFileName << "\n";
+               return 1;
        }
-       Scanner scanner(source, output);
-       sourceFileInfo = file_info(sourceFileName, &scanner);
-       outputFileInfo = file_info(outputFileName, &output);
-
-       if (!bSinglePass)
-       {
-               bUsedYYMarker = false;
 
-               re2c::ifstream_lc null_source;
-               
-               if (!null_source.open(sourceFileName).is_open())
-               {
-                       cerr << "re2c: error: cannot re-open " << sourceFileName << "\n";
-                       return 1;
-               }
+       Scanner scanner (source, output.source);
+       sourceFileInfo = file_info (sourceFileName, &scanner);
+       parse (scanner, output);
 
-               null_stream  null_dev;
-               Scanner null_scanner(null_source, null_dev);
-               parse(null_scanner, null_dev, NULL);
-               next_label = 0;
-               next_fill_index = 0;
-               bWroteGetState = false;
-               bWroteCondCheck = false;
-               bUsedYYMaxFill = false;
-               bFirstPass = false;
-               sourceFileInfo.set_fname(sourceFileName);
-       }
+       // output generated code
+       output.emit ();
 
-       bLastPass = true;
-       parse(scanner, output, header.is_open() ? &header : NULL);
        return 0;
 }
diff --git a/re2c/output.cc b/re2c/output.cc
new file mode 100644 (file)
index 0000000..51fb006
--- /dev/null
@@ -0,0 +1,239 @@
+#include <iomanip>
+#include <stdio.h>
+
+#include "output.h"
+#include "re.h"
+
+namespace re2c
+{
+
+uint OutputFragment::count_lines ()
+{
+       uint lines = 0;
+       const std::string content = str ();
+       const char * p = content.c_str ();
+       for (uint i = 0; i < content.size (); ++i)
+       {
+               if (p[i] == '\n')
+               {
+                       ++lines;
+               }
+       }
+       return lines;
+}
+
+OutputBlock::OutputBlock ()
+       : fragments ()
+       , used_yyaccept (false)
+{
+       fragments.push_back (new OutputFragment (OutputFragment::CODE, 0));
+}
+
+OutputBlock::~OutputBlock ()
+{
+       for (unsigned int i = 0; i < fragments.size (); ++i)
+       {
+               delete fragments[i];
+       }
+}
+
+OutputFile::OutputFile (const char * fn)
+       : status (NO_FILE)
+       , filename (fn)
+       , file (NULL)
+       , blocks ()
+       , prolog_label (0)
+{
+       if (filename != NULL)
+       {
+               if (strcmp (filename, "<stdout>") == 0)
+               {
+                       file = stdout;
+                       status = OK;
+               }
+               else
+               {
+                       file = fopen (filename, "wb");
+                       status = file == NULL
+                               ? FAIL_OPEN
+                               : OK;
+               }
+       }
+       new_block ();
+}
+
+OutputFile::~OutputFile ()
+{
+       if (file != NULL && file != stdout)
+       {
+               fclose (file);
+       }
+       for (unsigned int i = 0; i < blocks.size (); ++i)
+       {
+               delete blocks[i];
+       }
+}
+
+OutputFragment & OutputFile::fragment ()
+{
+       return * blocks.back ()->fragments.back ();
+}
+
+void OutputFile::write (const char * s, std::streamsize n)
+{
+       fragment ().write (s, n);
+}
+
+OutputFile & operator << (OutputFile & u, uint n)
+{
+       u.fragment () << n;
+       return u;
+}
+
+OutputFile & operator << (OutputFile & u, const std::string & s)
+{
+       u.fragment () << s;
+       return u;
+}
+
+OutputFile & operator << (OutputFile & u, const char * s)
+{
+       u.fragment () << s;
+       return u;
+}
+
+OutputFile & operator << (OutputFile & u, const file_info & i)
+{
+       u.fragment () << i;
+       return u;
+}
+
+OutputFile & operator << (OutputFile & u, const Str & s)
+{
+       u.fragment () << s;
+       return u;
+}
+
+OutputFile & operator << (OutputFile & u, const Setw & s)
+{
+       u.fragment () << std::setw (s.width);
+       return u;
+}
+
+void OutputFile::insert_code ()
+{
+       blocks.back ()->fragments.push_back (new OutputFragment (OutputFragment::CODE, 0));
+}
+
+void OutputFile::insert_line_info ()
+{
+       blocks.back ()->fragments.push_back (new OutputFragment (OutputFragment::LINE_INFO, 0));
+       insert_code ();
+}
+
+void OutputFile::insert_state_goto (uint ind, uint start_label)
+{
+       if (fFlag && !bWroteGetState)
+       {
+               prolog_label = start_label;
+               vUsedLabels.insert (start_label);
+               blocks.back ()->fragments.push_back (new OutputFragment (OutputFragment::STATE_GOTO, ind));
+               insert_code ();
+               bWroteGetState = true;
+       }
+}
+
+void OutputFile::insert_types ()
+{
+       blocks.back ()->fragments.push_back (new OutputFragment (OutputFragment::TYPES, 0));
+       insert_code ();
+}
+
+void OutputFile::insert_yyaccept_init (uint ind)
+{
+       blocks.back ()->fragments.push_back (new OutputFragment (OutputFragment::YYACCEPT_INIT, ind));
+       insert_code ();
+}
+
+void OutputFile::insert_yyaccept_selector (uint ind, uint selector)
+{
+       OutputFragment * p = new OutputFragment (OutputFragment::YYACCEPT_SELECTOR, ind);
+       p->info.yyaccept_selector = selector;
+       blocks.back ()->fragments.push_back (p);
+       insert_code ();
+}
+
+void OutputFile::insert_yymaxfill ()
+{
+       blocks.back ()->fragments.push_back (new OutputFragment (OutputFragment::YYMAXFILL, 0));
+       insert_code ();
+}
+
+void OutputFile::set_used_yyaccept ()
+{
+       blocks.back ()->used_yyaccept = true;
+}
+
+bool OutputFile::get_used_yyaccept () const
+{
+       return blocks.back ()->used_yyaccept;
+}
+
+void OutputFile::new_block ()
+{
+       blocks.push_back (new OutputBlock ());
+       insert_code ();
+}
+
+void OutputFile::emit
+       ( const std::vector<std::string> & types
+       , uint max_fill
+       )
+{
+       if (file != NULL)
+       {
+               unsigned int line_count = 1;
+               for (unsigned int j = 0; j < blocks.size (); ++j)
+               {
+                       OutputBlock & b = * blocks[j];
+                       for (unsigned int i = 0; i < b.fragments.size (); ++i)
+                       {
+                               OutputFragment & f = * b.fragments[i];
+                               switch (f.type)
+                               {
+                                       case OutputFragment::CODE:
+                                               break;
+                                       case OutputFragment::LINE_INFO:
+                                               output_line_info (f, line_count + 1, filename);
+                                               break;
+                                       case OutputFragment::STATE_GOTO:
+                                               output_state_goto (f, prolog_label);
+                                               break;
+                                       case OutputFragment::TYPES:
+                                               output_types (f, types);
+                                               break;
+                                       case OutputFragment::YYACCEPT_INIT:
+                                               output_yyaccept_init (f, b.used_yyaccept);
+                                               break;
+                                       case OutputFragment::YYACCEPT_SELECTOR:
+                                               output_yyaccept_selector (f, b.used_yyaccept);
+                                               break;
+                                       case OutputFragment::YYMAXFILL:
+                                               output_yymaxfill (f, max_fill);
+                                               break;
+                               }
+                               std::string content = f.str ();
+                               fwrite (content.c_str (), 1, content.size (), file);
+                               line_count += f.count_lines ();
+                       }
+               }
+       }
+}
+
+void Output::emit ()
+{
+       source.emit (types, max_fill);
+       header.emit (types, max_fill);
+}
+
+} // namespace re2c
diff --git a/re2c/output.h b/re2c/output.h
new file mode 100644 (file)
index 0000000..e24a3e2
--- /dev/null
@@ -0,0 +1,127 @@
+#ifndef _output_h
+#define _output_h
+
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "basics.h"
+
+namespace re2c
+{
+
+struct file_info;
+struct Str;
+
+struct Setw
+{
+       uint width;
+
+       Setw (uint n)
+               : width (n)
+       {}
+};
+
+struct OutputFragment : public std::ostringstream
+{
+       enum type_t
+               { CODE
+//             , COND_GOTO
+               , COND_TABLE
+//             , CONFIG
+               , LINE_INFO
+               , STATE_GOTO
+               , TYPES
+               , YYACCEPT_INIT
+               , YYACCEPT_SELECTOR
+               , YYMAXFILL
+               };
+
+       union info_t
+       {
+               uint yyaccept_selector;
+       };
+
+       type_t type;
+       info_t info;
+       uint indent;
+
+       OutputFragment (type_t t, uint i)
+               : std::ostringstream ()
+               , type (t)
+               , info ()
+               , indent (i)
+       {}
+
+       uint count_lines ();
+};
+
+OutputFragment & operator << (OutputFragment & f, const file_info & info);
+
+struct OutputBlock
+{
+       std::vector<OutputFragment *> fragments;
+       bool used_yyaccept;
+
+       OutputBlock ();
+       ~OutputBlock ();
+};
+
+struct OutputFile
+{
+       enum status_t
+               { NO_FILE
+               , OK
+               , FAIL_OPEN
+               } status;
+
+       OutputFile (const char * filename);
+       ~OutputFile ();
+       OutputFragment & fragment ();
+       void write (const char * s, std::streamsize n);
+       void insert_line_info ();
+       void insert_state_goto (uint ind, uint start_label);
+       void insert_types ();
+       void insert_yyaccept_init (uint ind);
+       void insert_yyaccept_selector (uint ind, uint selector);
+       void insert_yymaxfill ();
+       void new_block ();
+       void set_used_yyaccept ();
+       bool get_used_yyaccept () const;
+       void emit (const std::vector<std::string> & types, uint max_fill);
+       friend OutputFile & operator << (OutputFile & o, uint n);
+       friend OutputFile & operator << (OutputFile & o, const std::string & s);
+       friend OutputFile & operator << (OutputFile & o, const char * s);
+       friend OutputFile & operator << (OutputFile & o, const file_info & i);
+       friend OutputFile & operator << (OutputFile & o, const Str & s);
+       friend OutputFile & operator << (OutputFile & o, const Setw & s);
+
+private:
+       const char * filename;
+       FILE * file;
+       std::vector<OutputBlock *> blocks;
+       uint prolog_label;
+
+       void insert_code ();
+};
+
+struct Output
+{
+       OutputFile source;
+       OutputFile header;
+       std::vector<std::string> types;
+       uint max_fill;
+
+       Output (const char * source_name, const char * header_name)
+               : source (source_name)
+               , header (header_name)
+               , types ()
+               , max_fill (1)
+       {}
+
+       void emit ();
+};
+
+} // namespace re2c
+
+#endif // _output_h
index c6d3ffc1835578b305a898bb6259e54a30169bf4..b067d8ffcdef6ede5232949ddb4c4d7d402a592e 100644 (file)
@@ -2,9 +2,9 @@
 #ifndef _parser_h
 #define _parser_h
 
-#include "scanner.h"
+#include "output.h"
 #include "re.h"
-#include <iosfwd>
+#include "scanner.h"
 
 namespace re2c
 {
@@ -53,7 +53,7 @@ private:
 #endif
 };
 
-extern void parse(Scanner&, std::ostream&, std::ostream*);
+extern void parse(Scanner &, Output &);
 extern void parse_cleanup();
 
 } // end namespace re2c
index f0e7375e3170f75982a85375002b5f79e67c8de8..530785a2bee2bad73e8194953c9008ad6bcbc382 100644 (file)
@@ -116,16 +116,13 @@ void setup_rule(CondList *clist, Token *code)
        assert(clist);
        assert(code);
        context_check(clist);
-       if (bFirstPass)
+       for(CondList::const_iterator it = clist->begin(); it != clist->end(); ++it)
        {
-               for(CondList::const_iterator it = clist->begin(); it != clist->end(); ++it)
+               if (ruleSetupMap.find(*it) != ruleSetupMap.end())
                {
-                       if (ruleSetupMap.find(*it) != ruleSetupMap.end())
-                       {
-                               in->fatalf_at(code->line, "code to setup rule '%s' is already defined", it->c_str());
-                       }
-                       ruleSetupMap[*it] = std::make_pair(code->line, code->text.to_string());
+                       in->fatalf_at(code->line, "code to setup rule '%s' is already defined", it->c_str());
                }
+               ruleSetupMap[*it] = std::make_pair(code->line, code->text.to_string());
        }
        delete clist;
        delete code;
@@ -136,16 +133,13 @@ void default_rule(CondList *clist, Token *code)
        assert(clist);
        assert(code);
        context_check(clist);
-       if (bFirstPass)
+       for(CondList::const_iterator it = clist->begin(); it != clist->end(); ++it)
        {
-               for(CondList::const_iterator it = clist->begin(); it != clist->end(); ++it)
+               if (ruleDefaultMap.find(*it) != ruleDefaultMap.end())
                {
-                       if (ruleDefaultMap.find(*it) != ruleDefaultMap.end())
-                       {
-                               in->fatalf_at(code->line, "code to default rule '%s' is already defined", it->c_str());
-                       }
-                       ruleDefaultMap[*it] = code;
+                       in->fatalf_at(code->line, "code to default rule '%s' is already defined", it->c_str());
                }
+               ruleDefaultMap[*it] = code;
        }
        delete clist;
 }
@@ -511,27 +505,22 @@ int yylex(){
 namespace re2c
 {
 
-void parse(Scanner& i, std::ostream& o, std::ostream* h)
+void parse(Scanner& i, Output & o)
 {
        std::map<std::string, smart_ptr<DFA> >  dfa_map;
        ScannerState rules_state;
 
        in = &i;
 
-       o << "/* Generated by re2c " PACKAGE_VERSION;
-       if (!bNoGenerationDate)
-       {
-               o << " on ";
-               time_t now = time(&now);
-               o.write(ctime(&now), 24);
-       }
-       o << " */\n";
-       o << sourceFileInfo;
-       
+       output_version_time (o.source);
+       o.source << sourceFileInfo;
+       output_version_time (o.header);
+
        Enc encodingOld = encoding;
        
        while ((parseMode = i.echo()) != Scanner::Stop)
        {
+               o.source.new_block ();
                bool bPrologBrace = false;
                ScannerState curr_state;
 
@@ -668,16 +657,20 @@ void parse(Scanner& i, std::ostream& o, std::ostream* h)
                                                }
                                        }
                                        dfa_map[it->first] = genCode(it->second.second);
-                                       dfa_map[it->first]->prepare();
+                                       dfa_map[it->first]->prepare(o.max_fill);
                                }
                                if (parseMode != Scanner::Rules && dfa_map.find(it->first) != dfa_map.end())
                                {
                                        dfa_map[it->first]->emit(o, topIndent, &specMap, it->first, !--nCount, bPrologBrace);
                                }
                        }
-                       if (!h && !bTypesDone)
+
+                       genTypes (o, specMap);
+                       if (o.header.status != OutputFile::NO_FILE)
                        {
-                               genTypes(typesInline, 0, specMap);
+                               o.header.insert_line_info ();
+                               o.header << "\n";
+                               o.header.insert_types ();
                        }
                }
                else
@@ -692,7 +685,7 @@ void parse(Scanner& i, std::ostream& o, std::ostream* h)
                                if (parseMode != Scanner::Reuse)
                                {
                                        dfa_map[""] = genCode(spec);
-                                       dfa_map[""]->prepare();
+                                       dfa_map[""]->prepare(o.max_fill);
                                }
                                if (parseMode != Scanner::Rules && dfa_map.find("") != dfa_map.end())
                                {
@@ -700,7 +693,7 @@ void parse(Scanner& i, std::ostream& o, std::ostream* h)
                                }
                        }
                }
-               o << sourceFileInfo;
+               o.source << sourceFileInfo;
                /* restore original char handling mode*/
                encoding = encodingOld;
        }
@@ -727,11 +720,6 @@ void parse(Scanner& i, std::ostream& o, std::ostream* h)
                }
        }
 
-       if (h)
-       {
-               genHeader(*h, 0, specMap);
-       }
-       
        parse_cleanup();
        in = NULL;
 }
index 11431c5d53dc7ec8af29226fd175679e4af6975e..068ff69ef85d0fb9b2d4799b37784a61a19c3744 100644 (file)
--- a/re2c/re.h
+++ b/re2c/re.h
@@ -8,12 +8,14 @@
 #include <list>
 #include <vector>
 #include <string>
-#include "token.h"
-#include "ins.h"
+
 #include "free_list.h"
 #include "globals.h"
+#include "ins.h"
+#include "output.h"
 #include "range.h"
 #include "smart_ptr.h"
+#include "token.h"
 
 namespace re2c
 {
@@ -407,11 +409,17 @@ typedef std::map<std::string, Token*>   DefaultMap;
 class DFA;
 
 extern smart_ptr<DFA> genCode(RegExp*);
-extern void genGetStateGoto(std::ostream&, uint&, uint);
-extern void genCondTable(std::ostream&, uint, const RegExpMap&);
-extern void genCondGoto(std::ostream&, uint, const RegExpMap&);
-extern void genTypes(std::string&, uint, const RegExpMap&);
-extern void genHeader(std::ostream&, uint, const RegExpMap&);
+extern void genCondTable(OutputFile &, uint, const RegExpMap&);
+extern void genCondGoto(OutputFile &, uint, const RegExpMap&);
+extern void genTypes(Output &, const RegExpMap&);
+
+extern void output_state_goto (OutputFragment &, uint);
+extern void output_types (OutputFragment &, const std::vector<std::string> &);
+extern void output_version_time (OutputFile &);
+extern void output_yyaccept_init (OutputFragment &, bool);
+extern void output_yyaccept_selector (OutputFragment &, bool);
+extern void output_yymaxfill (OutputFragment &, uint);
+extern void output_line_info (OutputFragment &, uint, const char *);
 
 extern RegExp *mkDiff(RegExp*, RegExp*);
 extern RegExp *mkAlt(RegExp*, RegExp*);
index 8df3e5a6e96738dc05ac0504db8f31a5b686dfb0..5c1674bb08c88c957d541e8064deb031c88e27c7 100644 (file)
@@ -4,9 +4,11 @@
 
 #include <iosfwd>
 #include <string>
-#include "token.h"
-#include "re.h"
+
 #include "globals.h"
+#include "output.h"
+#include "re.h"
+#include "token.h"
 
 namespace re2c
 {
@@ -26,7 +28,7 @@ class Scanner:
 {
 private:
        std::istream&   in;
-       std::ostream&   out;
+       OutputFile & out;
 
 private:
        char *fill(char*, uint);
@@ -35,7 +37,7 @@ private:
        void set_sourceline(char *& cursor);
 
 public:
-       Scanner(std::istream&, std::ostream&);
+       Scanner(std::istream&, OutputFile &);
        ~Scanner();
 
        enum ParseMode {
index 3bcf10ab86ceb193433a893ce7a0d94386cc9c4d..805292d03efea25fc114b690d31a2862ee39bec6 100644 (file)
@@ -1,4 +1,3 @@
-/* $Id$ */
 #include <stdlib.h>
 #include <string.h>
 #include <iostream>
@@ -70,10 +69,6 @@ echo:
                                        {
                                                fatal("found standard 're2c' block while using -r flag");
                                        }
-                                       if (bUsedYYMaxFill && bSinglePass)
-                                       {
-                                               fatal("found scanner block after YYMAXFILL declaration");
-                                       }
                                        if (!DFlag)
                                        {
                                                out.write((const char*)(tok), (const char*)(&cursor[-7]) - (const char*)(tok));
@@ -90,10 +85,6 @@ echo:
                                        {
                                                fatal("found 'rules:re2c' block without -r flag");
                                        }
-                                       if (bUsedYYMaxFill && bSinglePass)
-                                       {
-                                               fatal("found scanner block after YYMAXFILL declaration");
-                                       }
                                        tok = cursor;
                                        RETURN(Rules);
                                }
@@ -103,10 +94,6 @@ echo:
                                                fatal("found 'use:re2c' block without -r flag");
                                        }
                                        reuse();
-                                       if (bUsedYYMaxFill && bSinglePass)
-                                       {
-                                               fatal("found scanner block after YYMAXFILL declaration");
-                                       }
                                        if (!DFlag)
                                        {
                                                out.write((const char*)(tok), (const char*)(&cursor[-11]) - (const char*)(tok));
@@ -115,22 +102,17 @@ echo:
                                        RETURN(Reuse);
                                }
        "/*!max:re2c" {
-                                       if (bUsedYYMaxFill)
-                                       {
-                                               fatal("cannot generate YYMAXFILL twice");
-                                       }
                                        if (!DFlag)
                                        {
-                                               out << "#define YYMAXFILL " << maxFill << std::endl;
+                                               out.insert_yymaxfill ();
                                        }
                                        tok = pos = cursor;
                                        ignore_eoc = true;
-                                       bUsedYYMaxFill = true;
                                        goto echo;
                                }
        "/*!getstate:re2c" {
                                        tok = pos = cursor;
-                                       genGetStateGoto(out, topIndent, 0);
+                                       out.insert_state_goto (topIndent, 0);
                                        ignore_eoc = true;
                                        goto echo;
                                }
@@ -140,17 +122,13 @@ echo:
                                        goto echo;
                                }
        "/*!types:re2c" {
-                                       if (bSinglePass)
-                                       {
-                                               fatal("cannot generate types inline in single pass mode");
-                                       }
                                        tok = pos = cursor;
                                        ignore_eoc = true;
-                                       if (bLastPass && !DFlag)
+                                       if (!DFlag)
                                        {
-                                               out << outputFileInfo;
+                                               out.insert_line_info ();
                                                out << "\n";
-                                               out << typesInline;
+                                               out.insert_types ();
                                                out << "\n";
                                                out << sourceFileInfo;
                                        }
index e44533a102b884a69abd39a03b9b48298a1f1100..0ab654c40cb851479c0c166cf11225116601d575 100755 (executable)
@@ -1,5 +1,51 @@
 /* Generated by re2c */
 #line 1 "error13.1.re"
-#define YYMAXFILL 1
+#define YYMAXFILL 3
+
+
+#line 7 "<stdout>"
+{
+       YYCTYPE yych;
+
+       if ((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
+       yych = *YYCURSOR;
+       switch (yych) {
+       case 'A':       goto yy2;
+       default:        goto yy4;
+       }
+yy2:
+       yych = *(YYMARKER = ++YYCURSOR);
+       switch (yych) {
+       case 'B':       goto yy5;
+       default:        goto yy3;
+       }
+yy3:
+#line 6 "error13.1.re"
+       { return 0; }
+#line 26 "<stdout>"
+yy4:
+       yych = *++YYCURSOR;
+       goto yy3;
+yy5:
+       yych = *++YYCURSOR;
+       switch (yych) {
+       case 'C':       goto yy7;
+       case 'D':       goto yy9;
+       default:        goto yy6;
+       }
+yy6:
+       YYCURSOR = YYMARKER;
+       goto yy3;
+yy7:
+       ++YYCURSOR;
+#line 4 "error13.1.re"
+       { return 1; }
+#line 44 "<stdout>"
+yy9:
+       ++YYCURSOR;
+#line 5 "error13.1.re"
+       { return 2; }
+#line 49 "<stdout>"
+}
+#line 7 "error13.1.re"
 
-re2c: error: line 3, column 1: found scanner block after YYMAXFILL declaration
index 23bdd383a06fb605e9472cdb267ea74ae84c639d..a21eaab6158449451a5a9bfd82c5d65d43030b7f 100755 (executable)
@@ -50,4 +50,4 @@ yy9:
 
 #define YYMAXFILL 3
 
-re2c: error: line 9, column 1: cannot generate YYMAXFILL twice
+#define YYMAXFILL 3
index 3583e1d632f2233ee5d79037e91013b9d519a3db..27ac5ff72ca78ddadbd70d2a4ab52163c256f3a9 100755 (executable)
@@ -1 +1,53 @@
-re2c: error: line 9, column 1: cannot generate YYMAXFILL twice
+/* Generated by re2c */
+#line 1 "error14.re"
+
+#line 5 "<stdout>"
+{
+       YYCTYPE yych;
+
+       if ((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
+       yych = *YYCURSOR;
+       switch (yych) {
+       case 'A':       goto yy2;
+       default:        goto yy4;
+       }
+yy2:
+       yych = *(YYMARKER = ++YYCURSOR);
+       switch (yych) {
+       case 'B':       goto yy5;
+       default:        goto yy3;
+       }
+yy3:
+#line 4 "error14.re"
+       { return 0; }
+#line 24 "<stdout>"
+yy4:
+       yych = *++YYCURSOR;
+       goto yy3;
+yy5:
+       yych = *++YYCURSOR;
+       switch (yych) {
+       case 'C':       goto yy7;
+       case 'D':       goto yy9;
+       default:        goto yy6;
+       }
+yy6:
+       YYCURSOR = YYMARKER;
+       goto yy3;
+yy7:
+       ++YYCURSOR;
+#line 2 "error14.re"
+       { return 1; }
+#line 42 "<stdout>"
+yy9:
+       ++YYCURSOR;
+#line 3 "error14.re"
+       { return 2; }
+#line 47 "<stdout>"
+}
+#line 5 "error14.re"
+
+
+#define YYMAXFILL 3
+
+#define YYMAXFILL 3