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
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
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;
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;
}
/* 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
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;
}
}
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
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())
{
}
}
}
- o << sourceFileInfo;
+ o.source << sourceFileInfo;
/* restore original char handling mode*/
encoding = encodingOld;
}
}
}
- if (h)
- {
- genHeader(*h, 0, specMap);
- }
-
parse_cleanup();
in = NULL;
}
-/* 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>
{
fatal("found 'rules:re2c' block without -r flag");
}
- if (bUsedYYMaxFill && bSinglePass)
- {
- fatal("found scanner block after YYMAXFILL declaration");
- }
tok = cursor;
RETURN(Rules);
}
{
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));
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));
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:
++YYCURSOR;
{
tok = pos = cursor;
- genGetStateGoto(out, topIndent, 0);
+ out.insert_state_goto (topIndent, 0);
ignore_eoc = true;
goto echo;
}
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;
}
#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"
return str;
}
-static void genYYFill(std::ostream &o, uint, uint need)
+static void genYYFill(OutputFile & o, uint, uint need)
{
if (bUseYYFillParam)
{
}
}
-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)
{
}
}
-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];
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"] << "[] = {";
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)
{
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)
}
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)
{
}
}
-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;
}
}
-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);
}
}
-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";
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)
}
}
-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)
{
;
}
-void Move::emit(std::ostream &, uint, bool &, const std::string&) const
+void Move::emit(Output &, uint, bool &, const std::string&) const
{
;
}
}
}
-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";
}
}
-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;
if (mapRules.size() > 1)
{
- bUsedYYAccept = true;
+ o.set_used_yyaccept ();
if (gFlag && mapRules.size() >= cGotoThreshold)
{
;
}
-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";
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 (;;)
{
}
}
-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=";
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;
else
{
o << indent(ind) << "case ";
- prtChOrHex(o, lb);
+ prtChOrHex(o.fragment (), lb);
o << ":";
if (dFlag && encoding.is(Enc::EBCDIC))
{
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;
}
}
-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)
{
}
}
-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)
{
}
}
-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)
{
}
}
-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;
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)
{
o << "if (" << mapCodeName["yybm"] << "[" << b->i << "+" << sYych << "] & ";
if (yybmHexTable)
{
- prtHex(o, b->m);
+ prtHex(o.fragment (), b->m);
}
else
{
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";
{
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)
delete [] span;
}
-void DFA::prepare()
+void DFA::prepare(uint & max_fill)
{
State *s;
uint i;
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)
{
}
-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.
// 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)
{
// 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())
{
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
{
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))
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);
}
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)
{
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())
{
}
}
-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)
{
}
}
-void genCondGoto(std::ostream &o, uint ind, const RegExpMap& specMap)
+void genCondGoto(OutputFile & o, uint ind, const RegExpMap& specMap)
{
if (cFlag && !bWroteCondCheck && specMap.size())
{
}
}
-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)
{
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 '";
{
}
-Scanner::Scanner(std::istream& i, std::ostream& o)
+Scanner::Scanner(std::istream& i, OutputFile & o)
: ScannerState(), in(i), out(o)
{
}
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;
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();
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;
{
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;
};
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
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;
};
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;
};
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
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
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
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*);
};
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*);
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*);
enum BUFFERSIZE { BSIZE = 8192};
extern file_info sourceFileInfo;
-extern file_info outputFileInfo;
-extern file_info headerFileInfo;
extern bool bFlag;
extern bool cFlag;
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;
extern std::string yySetConditionParam;
extern std::string yySetStateParam;
extern std::string yySetupRule;
-extern uint maxFill;
extern uint next_label;
extern uint cGotoThreshold;
extern bool bWroteCondCheck;
extern bool bCaseInsensitive;
extern bool bCaseInverted;
-extern bool bTypesDone;
extern const uint asc2asc[256];
extern const uint asc2ebc[256];
extern uint last_fill_index;
extern std::set<uint> vUsedLabels;
extern CodeNames mapCodeName;
-extern std::string typesInline;
extern Enc encoding;
extern InputAPI input_api;
#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;
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;
std::string yySetConditionParam("@@");
std::string yySetStateParam("@@");
std::string yySetupRule("");
-uint maxFill = 1;
uint next_label = 0;
uint cGotoThreshold = 9;
bool bWroteCondCheck = false;
bool bCaseInsensitive = false;
bool bCaseInverted = false;
-bool bTypesDone = false;
Enc encoding;
InputAPI input_api;
uint last_fill_index = 0;
std::set<uint> vUsedLabels;
CodeNames mapCodeName;
-std::string typesInline;
free_list<RegExp*> RegExp::vFreeList;
free_list<Range*> Range::vFreeList;
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"),
" 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"
break;
case '1':
- bSinglePass = true;
break;
case 'v':
}
}
- 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";
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;
}
--- /dev/null
+#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
--- /dev/null
+#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
#ifndef _parser_h
#define _parser_h
-#include "scanner.h"
+#include "output.h"
#include "re.h"
-#include <iosfwd>
+#include "scanner.h"
namespace re2c
{
#endif
};
-extern void parse(Scanner&, std::ostream&, std::ostream*);
+extern void parse(Scanner &, Output &);
extern void parse_cleanup();
} // end namespace re2c
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;
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;
}
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;
}
}
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
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())
{
}
}
}
- o << sourceFileInfo;
+ o.source << sourceFileInfo;
/* restore original char handling mode*/
encoding = encodingOld;
}
}
}
- if (h)
- {
- genHeader(*h, 0, specMap);
- }
-
parse_cleanup();
in = NULL;
}
#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
{
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*);
#include <iosfwd>
#include <string>
-#include "token.h"
-#include "re.h"
+
#include "globals.h"
+#include "output.h"
+#include "re.h"
+#include "token.h"
namespace re2c
{
{
private:
std::istream& in;
- std::ostream& out;
+ OutputFile & out;
private:
char *fill(char*, uint);
void set_sourceline(char *& cursor);
public:
- Scanner(std::istream&, std::ostream&);
+ Scanner(std::istream&, OutputFile &);
~Scanner();
enum ParseMode {
-/* $Id$ */
#include <stdlib.h>
#include <string.h>
#include <iostream>
{
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));
{
fatal("found 'rules:re2c' block without -r flag");
}
- if (bUsedYYMaxFill && bSinglePass)
- {
- fatal("found scanner block after YYMAXFILL declaration");
- }
tok = cursor;
RETURN(Rules);
}
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));
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;
}
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;
}
/* 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
#define YYMAXFILL 3
-re2c: error: line 9, column 1: cannot generate YYMAXFILL twice
+#define YYMAXFILL 3
-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