, bool & readCh
, const State * const s
, const std::string & condName
+ , const std::string & name
, const std::set<label_t> & used_labels
, bool save_yyaccept
);
static void emit_save (OutputFile & o, uint32_t ind, bool & readCh, const State * const s, uint32_t save, bool save_yyaccept);
static void emit_accept_binary (OutputFile & o, uint32_t ind, bool & readCh, const State * const s, const accept_t & accept, uint32_t l, uint32_t r);
static void emit_accept (OutputFile & o, uint32_t ind, bool & readCh, const State * const s, const accept_t & accept);
-static void emit_rule (OutputFile & o, uint32_t ind, const State * const s, const RuleOp * const rule, const std::string & condName);
+static void emit_rule (OutputFile & o, uint32_t ind, const State * const s, const RuleOp * const rule, const std::string & condName, const std::string & name);
static void genYYFill (OutputFile & o, uint32_t need);
static void genSetCondition (OutputFile & o, uint32_t ind, const std::string & newcond);
, bool & readCh
, const State * const s
, const std::string & condName
+ , const std::string & name
, const std::set<label_t> & used_labels
, bool save_yyaccept
)
emit_accept (o, ind, readCh, s, * action.info.accepts);
break;
case Action::RULE:
- emit_rule (o, ind, s, action.info.rule, condName);
+ emit_rule (o, ind, s, action.info.rule, condName, name);
break;
}
}
}
}
-void emit_rule (OutputFile & o, uint32_t ind, const State * const s, const RuleOp * const rule, const std::string & condName)
+void emit_rule (OutputFile & o, uint32_t ind, const State * const s, const RuleOp * const rule, const std::string & condName, const std::string & name)
{
if (DFlag)
{
if (flag_skeleton)
{
- Skeleton::emit_action (o, ind, rule->rank);
+ Skeleton::emit_action (o, ind, rule->rank, name);
}
else
{
}
}
+void DFA::emit_body (OutputFile & o, uint32_t& ind, const std::set<label_t> & used_labels) const
+{
+ const bool save_yyaccept = accepts.size () > 1;
+ for (State * s = head; s; s = s->next)
+ {
+ bool readCh = false;
+ emit_state (o, ind, s, used_labels.count (s->label));
+ emit_action (s->action, o, ind, readCh, s, cond, name, used_labels, save_yyaccept);
+ s->go.emit(o, ind, readCh);
+ }
+}
+
void DFA::emit(Output & output, uint32_t& ind, bool isLastCond, bool& bPrologBrace)
{
OutputFile & o = output.source;
head->action.set_initial (initial_label, head->action.type == Action::SAVE);
- // Generate prolog
skeleton->warn_undefined_control_flow ();
+
if (flag_skeleton)
{
skeleton->emit_data (o.file_name);
- skeleton->emit_prolog (o, output.max_fill);
+ skeleton->emit_start (o, output.max_fill);
+ uint32_t i = 2;
+ emit_body (o, i, used_labels);
+ skeleton->emit_end (o);
}
- if (bProlog)
+ else
{
- o << "\n";
- o.insert_line_info ();
-
- if (DFlag)
- {
- bPrologBrace = true;
- o << "digraph re2c {\n";
- }
- else if ((!fFlag && o.get_used_yyaccept ())
- || (!fFlag && bEmitYYCh)
- || (bFlag && !cFlag && BitMap::first)
- || (cFlag && !bWroteCondCheck && gFlag)
- || (fFlag && !bWroteGetState && gFlag)
- )
- {
- bPrologBrace = true;
- o << indent(ind++) << "{\n";
- }
- else if (ind == 0)
+ // Generate prolog
+ if (bProlog)
{
- ind = 1;
- }
-
- if (!fFlag && !DFlag)
- {
- if (bEmitYYCh)
+ o << "\n";
+ o.insert_line_info ();
+ if (DFlag)
+ {
+ bPrologBrace = true;
+ o << "digraph re2c {\n";
+ }
+ else if ((!fFlag && o.get_used_yyaccept ())
+ || (!fFlag && bEmitYYCh)
+ || (bFlag && !cFlag && BitMap::first)
+ || (cFlag && !bWroteCondCheck && gFlag)
+ || (fFlag && !bWroteGetState && gFlag)
+ )
+ {
+ bPrologBrace = true;
+ o << indent(ind++) << "{\n";
+ }
+ else if (ind == 0)
+ {
+ ind = 1;
+ }
+ if (!fFlag && !DFlag)
+ {
+ if (bEmitYYCh)
+ {
+ o << indent(ind) << mapCodeName["YYCTYPE"] << " " << mapCodeName["yych"] << ";\n";
+ }
+ o.insert_yyaccept_init (ind);
+ }
+ else
{
- o << indent(ind) << mapCodeName["YYCTYPE"] << " " << mapCodeName["yych"] << ";\n";
+ o << "\n";
}
- o.insert_yyaccept_init (ind);
}
- else
+ if (bFlag && !cFlag && BitMap::first)
{
- o << "\n";
+ BitMap::gen(o, ind, lbChar, ubChar <= 256 ? ubChar : 256);
}
- }
- if (bFlag && !cFlag && BitMap::first)
- {
- BitMap::gen(o, ind, lbChar, ubChar <= 256 ? ubChar : 256);
- }
- if (bProlog)
- {
- if (cFlag && !bWroteCondCheck && gFlag)
+ if (bProlog)
{
- genCondTable(o, ind, output.types);
+ if (cFlag && !bWroteCondCheck && gFlag)
+ {
+ genCondTable(o, ind, output.types);
+ }
+ o.insert_state_goto (ind);
+ if (cFlag && !DFlag)
+ {
+ if (used_labels.count(start_label))
+ {
+ o << labelPrefix << start_label << ":\n";
+ }
+ }
+ o.write_user_start_label ();
+ if (cFlag && !bWroteCondCheck)
+ {
+ genCondGoto(o, ind, output.types);
+ }
}
- o.insert_state_goto (ind);
- if (cFlag && !DFlag)
+ if (cFlag && !cond.empty())
{
- if (used_labels.count(start_label))
+ if (condDivider.length())
+ {
+ o << replaceParam(condDivider, condDividerParam, cond) << "\n";
+ }
+ if (DFlag)
+ {
+ o << cond << " -> " << head->label << "\n";
+ }
+ else
{
- o << labelPrefix << start_label << ":\n";
+ o << condPrefix << cond << ":\n";
}
}
- o.write_user_start_label ();
- if (cFlag && !bWroteCondCheck)
+ if (cFlag && bFlag && BitMap::first)
{
- genCondGoto(o, ind, output.types);
+ o << indent(ind++) << "{\n";
+ BitMap::gen(o, ind, lbChar, ubChar <= 256 ? ubChar : 256);
}
- }
-
- if (cFlag && !cond.empty())
- {
- if (condDivider.length())
+ // If DFA has transitions to initial state, then initial state
+ // has a piece of code that advances input position. Wee must
+ // skip it when entering DFA.
+ if (used_labels.count(head->label))
{
- o << replaceParam(condDivider, condDividerParam, cond) << "\n";
+ o << indent(ind) << "goto " << labelPrefix << initial_label << ";\n";
}
-
- if (DFlag)
+ // Generate code
+ emit_body (o, ind, used_labels);
+ if (cFlag && bFlag && BitMap::first)
{
- o << cond << " -> " << head->label << "\n";
+ o << indent(--ind) << "}\n";
}
- else
+ // Generate epilog
+ if ((!cFlag || isLastCond) && bPrologBrace)
{
- o << condPrefix << cond << ":\n";
+ o << indent(--ind) << "}\n";
}
}
- if (cFlag && bFlag && BitMap::first)
- {
- o << indent(ind++) << "{\n";
- BitMap::gen(o, ind, lbChar, ubChar <= 256 ? ubChar : 256);
- }
-
- // If DFA has transitions to initial state, then initial state
- // has a piece of code that advances input position. Wee must
- // skip it when entering DFA.
- if (used_labels.count(head->label))
- {
- o << indent(ind) << "goto " << labelPrefix << initial_label << ";\n";
- }
-
- // Generate code
- const bool save_yyaccept = accepts.size () > 1;
- for (State * s = head; s; s = s->next)
- {
- bool readCh = false;
- emit_state (o, ind, s, used_labels.count (s->label));
- emit_action (s->action, o, ind, readCh, s, cond, used_labels, save_yyaccept);
- s->go.emit(o, ind, readCh);
- }
-
- if (cFlag && bFlag && BitMap::first)
- {
- o << indent(--ind) << "}\n";
- }
- // Generate epilog
- if ((!cFlag || isLastCond) && bPrologBrace)
- {
- o << indent(--ind) << "}\n";
- }
- if (flag_skeleton)
- {
- Skeleton::emit_epilog (o);
- }
// Cleanup
if (BitMap::first)
Output::Output (const char * source_name, const char * header_name)
: source (source_name)
, header (header_name)
+ , names ()
, types ()
, max_fill (1)
{}
{
OutputFile source;
HeaderFile header;
+ std::vector<std::string> names;
std::vector<std::string> types;
uint32_t max_fill;
+#include "src/codegen/bitmap.h"
#include "src/codegen/indent.h"
#include "src/codegen/skeleton/skeleton.h"
+#include "src/conf/msg.h"
namespace re2c
{
}
}
-void Skeleton::emit_prolog (OutputFile & o, uint32_t maxfill) const
+void Skeleton::emit_prolog (OutputFile & o)
{
- const uint32_t default_rule = maxkey ();
-
o << "\n" << "#include <stdio.h>";
o << "\n" << "#include <stdlib.h> // malloc, free";
o << "\n" << "#include <string.h> // memset";
o << "\n";
+ o << "\n" << "static size_t filesize (FILE * f)";
+ o << "\n" << "{";
+ o << "\n" << indString << "const long pos = ftell (f);";
+ o << "\n" << indString << "fseek (f, 0, SEEK_END);";
+ o << "\n" << indString << "const long size = ftell (f);";
+ o << "\n" << indString << "fseek (f, pos, SEEK_SET);";
+ o << "\n" << indString << "return (size_t) size;";
+ o << "\n" << "}";
+ o << "\n";
+}
- o << "\n" << "typedef ";
- exact_uint (o, encoding.szCodeUnit ());
- o << " YYCTYPE;";
+void Skeleton::emit_start (OutputFile & o, uint32_t maxfill) const
+{
+ const uint32_t default_rule = maxkey ();
- o << "\n" << "typedef ";
+ o << "\n" << "#define YYCTYPE ";
+ exact_uint (o, encoding.szCodeUnit ());
+ o << "\n" << "#define YYKEYTYPE ";
exact_uint (o, sizeof_key);
- o << " YYKEYTYPE;";
-
- o << "\n";
o << "\n" << "#define YYPEEK() *cursor";
o << "\n" << "#define YYSKIP() ++cursor";
o << "\n" << "#define YYBACKUP() marker = cursor";
o << "\n" << "#define YYLESSTHAN(n) (limit - cursor) < n";
o << "\n" << "#define YYFILL(n) { break; }";
o << "\n";
- o << "\n" << "static inline YYKEYTYPE length (const YYKEYTYPE * keys, unsigned int i) { return keys [3 * i]; }";
- o << "\n" << "static inline YYKEYTYPE match_length (const YYKEYTYPE * keys, unsigned int i) { return keys [3 * i + 1]; }";
- o << "\n" << "static inline YYKEYTYPE rule (const YYKEYTYPE * keys, unsigned int i) { return keys [3 * i + 2]; }";
- o << "\n";
- o << "\n" << "static inline int action";
+ o << "\n" << "static int action_" << name;
o << "\n" << indString << "( unsigned int i";
o << "\n" << indString << ", const YYKEYTYPE * keys";
o << "\n" << indString << ", const YYCTYPE * start";
o << "\n" << "{";
o << "\n" << indString << "const long pos = token - start;";
o << "\n" << indString << "const long len_act = *cursor - token;";
- o << "\n" << indString << "const long len_exp = (long) match_length (keys, i);";
- o << "\n" << indString << "const YYKEYTYPE rule_exp = rule (keys, i);";
+ o << "\n" << indString << "const long len_exp = (long) keys [3 * i + 1];";
+ o << "\n" << indString << "const YYKEYTYPE rule_exp = keys [3 * i + 2];";
o << "\n" << indString << "if (rule_exp == " << default_rule << ")";
o << "\n" << indString << "{";
o << "\n" << indString << indString << "fprintf";
o << "\n" << indString << indString << indString << "( stderr";
- o << "\n" << indString << indString << indString << ", \"warning: control flow is undefined for input\"";
+ o << "\n" << indString << indString << indString << ", \"warning: " << incond (cond) << "control flow is undefined for input\"";
o << "\n" << indString << indString << indString << indString << "\" at position %ld, rerun re2c with '-W'\\n\"";
o << "\n" << indString << indString << indString << ", pos";
o << "\n" << indString << indString << indString << ");";
o << "\n" << indString << "}";
o << "\n" << indString << "if (len_act == len_exp && rule_act == rule_exp)";
o << "\n" << indString << "{";
- o << "\n" << indString << indString << "*cursor = token + length (keys, i);";
+ o << "\n" << indString << indString << "const YYKEYTYPE offset = keys[3 * i];";
+ o << "\n" << indString << indString << "*cursor = token + offset;";
o << "\n" << indString << indString << "return 0;";
o << "\n" << indString << "}";
o << "\n" << indString << "else";
o << "\n" << indString << "{";
o << "\n" << indString << indString << "fprintf";
o << "\n" << indString << indString << indString << "( stderr";
- o << "\n" << indString << indString << indString << ", \"error: at position %ld (iteration %u):\\n\"";
+ o << "\n" << indString << indString << indString << ", \"error: " << incond (cond) << "at position %ld (iteration %u):\\n\"";
o << "\n" << indString << indString << indString << indString << "\"\\texpected: match length %ld, rule %u\\n\"";
o << "\n" << indString << indString << indString << indString << "\"\\tactual: match length %ld, rule %u\\n\"";
o << "\n" << indString << indString << indString << ", pos";
o << "\n" << indString << "}";
o << "\n" << "}";
o << "\n";
- o << "\n" << "static inline size_t filesize (FILE * f)";
+ o << "\n" << "int lex_" << name << " ()";
o << "\n" << "{";
- o << "\n" << indString << "const long pos = ftell (f);";
- o << "\n" << indString << "fseek (f, 0, SEEK_END);";
- o << "\n" << indString << "const long size = ftell (f);";
- o << "\n" << indString << "fseek (f, pos, SEEK_SET);";
- o << "\n" << indString << "return (size_t) size;";
- o << "\n" << "}";
- o << "\n";
- o << "\n" << "int main ()";
- o << "\n" << "{";
- o << "\n" << indString << "FILE * finput = fopen (\"" << o.file_name << ".input" << "\", \"rb\");";
+ o << "\n" << indString << "FILE * finput = fopen (\"" << o.file_name << "." << name << ".input" << "\", \"rb\");";
o << "\n" << indString << "if (!finput)";
o << "\n" << indString << "{";
- o << "\n" << indString << indString << "fprintf (stderr, \"cannot open file '%s'\\n\", \"" << o.file_name << ".input\");";
+ o << "\n" << indString << indString << "fprintf (stderr, \"cannot open file '%s'\\n\", \"" << o.file_name << "." << name << ".input\");";
o << "\n" << indString << indString << "return 1;";
o << "\n" << indString << "}";
- o << "\n" << indString << "FILE * fkeys = fopen (\"" << o.file_name << ".keys" << "\", \"rb\");";
+ o << "\n" << indString << "FILE * fkeys = fopen (\"" << o.file_name << "." << name << ".keys" << "\", \"rb\");";
o << "\n" << indString << "if (!fkeys)";
o << "\n" << indString << "{";
- o << "\n" << indString << indString << "fprintf (stderr, \"cannot open file '%s'\\n\", \"" << o.file_name << ".keys\");";
+ o << "\n" << indString << indString << "fprintf (stderr, \"cannot open file '%s'\\n\", \"" << o.file_name << "." << name << ".keys\");";
o << "\n" << indString << indString << "return 1;";
o << "\n" << indString << "}";
o << "\n";
o << "\n" << indString << "for (i = 0; status == 0 && cursor < eof && i < keys_count; ++i)";
o << "\n" << indString << "{";
o << "\n" << indString << indString << "const YYCTYPE * token = cursor;";
+ o << "\n" << indString << indString << "YYCTYPE yych;";
+ o.insert_yyaccept_init (2);
+ o << "\n";
+ if (bFlag && BitMap::first)
+ {
+ BitMap::gen (o, 2, 0, std::min (0xFFu, encoding.nCodeUnits ()));
+ }
o << "\n";
}
-void Skeleton::emit_epilog (OutputFile & o)
+void Skeleton::emit_end (OutputFile & o) const
{
o << "\n" << indString << "}";
o << "\n" << indString << "if (status == 0)";
o << "\n" << indString << indString << "if (cursor != eof)";
o << "\n" << indString << indString << "{";
o << "\n" << indString << indString << indString << "status = 1;";
- o << "\n" << indString << indString << indString << "fprintf (stderr, \"error: unused input strings left\\n\");";
+ o << "\n" << indString << indString << indString << "fprintf (stderr, \"error: " << incond (cond) << "unused input strings left\\n\");";
o << "\n" << indString << indString << "}";
o << "\n" << indString << indString << "if (i != keys_count)";
o << "\n" << indString << indString << "{";
o << "\n" << indString << indString << indString << "status = 1;";
- o << "\n" << indString << indString << indString << "fprintf (stderr, \"error: unused keys left\\n\");";
+ o << "\n" << indString << indString << indString << "fprintf (stderr, \"error: " << incond (cond) << "unused keys left\\n\");";
o << "\n" << indString << indString << "}";
o << "\n" << indString << "}";
o << "\n" << indString << "free (input);";
o << "\n" << "}";
o << "\n";
o << "\n" << "#undef YYCTYPE";
+ o << "\n" << "#undef YYKEYTYPE";
o << "\n" << "#undef YYPEEK";
o << "\n" << "#undef YYSKIP";
o << "\n" << "#undef YYBACKUP";
o << "\n";
}
-void Skeleton::emit_action (OutputFile & o, uint32_t ind, rule_rank_t rank)
+void Skeleton::emit_epilog (OutputFile & o, const std::vector<std::string> & names)
+{
+ o << "\n" << "int main ()";
+ o << "\n" << "{";
+
+ const size_t names_count = names.size ();
+ for (size_t i = 0; i < names_count; ++i)
+ {
+ o << "\n" << indString << "if (lex_" << names[i] << " () != 0) return 1;";
+ }
+
+ o << "\n" << indString << "return 0;";
+ o << "\n" << "}";
+ o << "\n";
+}
+
+void Skeleton::emit_action (OutputFile & o, uint32_t ind, rule_rank_t rank, const std::string & name)
{
- o << indent (ind) << "status = action (i, keys, input, token, &cursor, " << rank << ");\n";
+ o << indent (ind) << "status = action_" << name << " (i, keys, input, token, &cursor, " << rank << ");\n";
o << indent (ind) << "continue;\n";
}
void Skeleton::emit_data (const char * fname)
{
- const std::string input_name = std::string (fname) + ".input";
+ const std::string input_name = std::string (fname) + "." + name + ".input";
FILE * input = fopen (input_name.c_str (), "wb");
if (!input)
{
error ("cannot open file: %s", input_name.c_str ());
exit (1);
}
- const std::string keys_name = std::string (fname) + ".keys";
+ const std::string keys_name = std::string (fname) + "." + name + ".keys";
FILE * keys = fopen (keys_name.c_str (), "wb");
if (!keys)
{
Skeleton::Skeleton (const DFA & dfa)
// +1 for default DFA state (NULL)
- : cond (dfa.cond)
+ : name (dfa.name)
+ , cond (dfa.cond)
, line (dfa.line)
, nodes_count (dfa.nStates + 1) // +1 for default state
, nodes (new Node [nodes_count])
struct Skeleton
{
- const std::string cond;
+ const std::string & name;
+ const std::string & cond;
const uint32_t line;
const uint32_t nodes_count;
~Skeleton ();
void warn_undefined_control_flow ();
void emit_data (const char * fname);
- void emit_prolog (OutputFile & o, uint32_t maxfill) const;
- static void emit_epilog (OutputFile & o);
- static void emit_action (OutputFile & o, uint32_t ind, rule_rank_t rank);
+ static void emit_prolog (OutputFile & o);
+ void emit_start (OutputFile & o, uint32_t maxfill) const;
+ void emit_end (OutputFile & o) const;
+ static void emit_epilog (OutputFile & o, const std::vector<std::string> & names);
+ static void emit_action (OutputFile & o, uint32_t ind, rule_rank_t rank, const std::string & name);
template <typename key_t>
static key_t maxkey ();
, rep
));
+ output.names.push_back (dfa->name);
dfa->prepare (output.source, output.max_fill);
return dfa;
)
: accepts ()
, skeleton (NULL)
+ , name (c)
, cond (c)
, line (l)
, lbChar(lb)
, free_ins(ins)
, free_rep(rep)
{
+ if (name.empty ())
+ {
+ std::ostringstream s;
+ s << "line" << line;
+ name = s.str ();
+ }
+
Ins **work = new Ins * [ni + 1];
uint32_t nc = ub - lb;
GoTo *goTo = new GoTo[nc];
Skeleton * skeleton;
public:
+ std::string name;
const std::string cond;
const uint32_t line;
void findBaseState ();
void prepare (OutputFile & o, uint32_t &);
void count_used_labels (std::set<label_t> & used, label_t prolog, label_t start, bool force_start) const;
+ void emit_body (OutputFile &, uint32_t &, const std::set<label_t> & used_labels) const;
void emit (Output &, uint32_t &, bool, bool &);
friend std::ostream & operator << (std::ostream &, const DFA &);
#include <set>
#include "config.h"
+#include "src/codegen/skeleton/skeleton.h"
#include "src/ir/bytecode/bytecode.h"
#include "src/ir/regexp/encoding/enc.h"
#include "src/ir/regexp/encoding/range_suffix.h"
o.source.write_version_time ();
o.source.write_line_info (in->get_cline (), in->get_fname ().c_str ());
+ if (flag_skeleton)
+ {
+ Skeleton::emit_prolog (o.source);
+ }
Enc encodingOld = encoding;
}
}
+ if (flag_skeleton)
+ {
+ Skeleton::emit_epilog (o.source, o.names);
+ }
+
parse_cleanup();
in = NULL;
}