src/codegen/skeleton/control_flow.cc \
src/codegen/skeleton/generate_code.cc \
src/codegen/skeleton/generate_data.cc \
+ src/codegen/skeleton/maxlen.cc \
src/codegen/skeleton/skeleton.cc \
src/codegen/skeleton/way.cc \
src/conf/msg.cc \
it->second = it->second ? mkAlt (def_rule, it->second) : def_rule;
}
- dfa_map[it->first] = genCode(it->second, o);
+ dfa_map[it->first] = genCode(it->second, o, it->first);
}
if (parseMode != Scanner::Rules && dfa_map.find(it->first) != dfa_map.end())
{
- dfa_map[it->first]->emit(o, topIndent, it->first, !--nCount, bPrologBrace);
+ dfa_map[it->first]->emit(o, topIndent, !--nCount, bPrologBrace);
}
}
}
{
if (parseMode != Scanner::Reuse)
{
- dfa_map[""] = genCode(spec, o);
+ dfa_map[""] = genCode(spec, o, "");
}
if (parseMode != Scanner::Rules && dfa_map.find("") != dfa_map.end())
{
- dfa_map[""]->emit(o, topIndent, "", 0, bPrologBrace);
+ dfa_map[""]->emit(o, topIndent, 0, bPrologBrace);
}
}
}
}
}
-void DFA::emit(Output & output, uint32_t& ind, const std::string& condName, bool isLastCond, bool& bPrologBrace)
+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 (o.get_block_line (), condName);
+ skeleton->warn_undefined_control_flow ();
if (flag_skeleton)
{
- skeleton->emit_data (o.get_block_line (), condName, o.file_name);
+ skeleton->emit_data (o.file_name);
Skeleton::emit_prolog (o, ind, output.max_fill);
}
if (bProlog)
}
}
- if (cFlag && !condName.empty())
+ if (cFlag && !cond.empty())
{
if (condDivider.length())
{
- o << replaceParam(condDivider, condDividerParam, condName) << "\n";
+ o << replaceParam(condDivider, condDividerParam, cond) << "\n";
}
if (DFlag)
{
- o << condName << " -> " << head->label << "\n";
+ o << cond << " -> " << head->label << "\n";
}
else
{
- o << condPrefix << condName << ":\n";
+ o << condPrefix << cond << ":\n";
}
}
if (cFlag && bFlag && BitMap::first)
{
bool readCh = false;
emit_state (o, ind, s, used_labels.count (s->label));
- emit_action (s->action, o, ind, readCh, s, condName, used_labels, save_yyaccept);
+ emit_action (s->action, o, ind, readCh, s, cond, used_labels, save_yyaccept);
s->go.emit(o, ind, readCh);
}
}
}
-void Skeleton::warn_undefined_control_flow (uint32_t line, const std::string & cond)
+void Skeleton::warn_undefined_control_flow ()
{
way_t prefix;
std::vector<way_t> ways;
*
* Two things contribute to size calculation: path length and the number
* of outgoing arcs in each node. Some considerations on why these values
- * will probably not overflow before they are converted to truncated type:
+ * will not overflow before they are converted to truncated type:
*
* - Maximal number of outgoing arcs in each node cannot exceed 32 bits:
* it is bounded by the number of code units in current encoding, and
* re2c doesn't support any encoding with more than 2^32 code units.
* Conversion is safe.
*
- * - Path length is unlikely to exceed maximal value of 'size_t'. It is
- * possible, but in that case re2c will crash anyway: path is stored
- * in 'std::vector' and if path length exceeds 'size_t', STL will
- * throw an exception.
+ * - Maximal path length cannot exceed 32 bits: we estimate it right
+ * after skeleton construction and check for overflow. If path length
+ * does overflow, an error is reported and re2c aborts.
*
*/
arccount_t Node::sizeof_permutate (arccount_t wid, arccount_t len)
return size;
}
-void Skeleton::generate_paths (uint32_t line, const std::string & cond, FILE * input, std::ofstream & keys)
+void Skeleton::generate_paths (FILE * input, std::ofstream & keys)
{
multipath_t prefix (nodes->rule);
if (nodes->sizeof_permutate (arccount_t (1u), arccount_t (0u)).overflow ())
}
}
-void Skeleton::emit_data (uint32_t line, const std::string & cond, const char * fname)
+void Skeleton::emit_data (const char * fname)
{
const std::string input_name = std::string (fname) + ".input";
FILE * input = fopen (input_name.c_str (), "wb");
keys << "Result result [] =\n";
keys << "{\n";
- generate_paths (line, cond, input, keys);
+ generate_paths (input, keys);
fclose (input);
--- /dev/null
+#include <stdlib.h> // exit
+
+#include "src/codegen/skeleton/skeleton.h"
+#include "src/conf/msg.h"
+
+namespace re2c
+{
+
+// 0 < DIST_MAX < DIST_ERROR <= UINT32_MAX
+const uint32_t Node::DIST_ERROR = UINT32_MAX;
+const uint32_t Node::DIST_MAX = DIST_ERROR - 1;
+
+// different from YYMAXFILL calculation
+// in the way it handles loops and empty regexp
+void Node::calc_dist ()
+{
+ if (dist != DIST_ERROR)
+ {
+ return;
+ }
+ else if (end ())
+ {
+ dist = 0;
+ }
+ else if (loop < 2)
+ {
+ local_inc _ (loop);
+ for (arcs_t::iterator i = arcs.begin (); i != arcs.end (); ++i)
+ {
+ i->first->calc_dist ();
+ if (i->first->dist != DIST_ERROR)
+ {
+ dist = std::max (dist, i->first->dist);
+ }
+ }
+ dist = std::min (dist + 1, DIST_MAX);
+ }
+}
+
+void Skeleton::calc_maxlen ()
+{
+ nodes->calc_dist ();
+ maxlen = nodes->dist;
+ if (maxlen == Node::DIST_MAX)
+ {
+ error ("DFA path %sis too long", incond (cond).c_str ());
+ exit (1);
+ }
+}
+
+} // namespace re2c
, arcsets ()
, loop (0)
, rule (rule_rank_t::none ())
+ , dist (DIST_ERROR)
, suffix (NULL)
{}
Skeleton::Skeleton (const DFA & dfa)
// +1 for default DFA state (NULL)
- : nodes (new Node [dfa.nStates + 1])
+ : cond (dfa.cond)
+ , line (dfa.line)
+ , nodes (new Node [dfa.nStates + 1])
+ , maxlen (Node::DIST_MAX)
{
Node * n;
n->init (s, s2n);
}
n->init (NULL, s2n);
+
+ calc_maxlen ();
}
Skeleton::~Skeleton ()
// rule number for corresponding DFA state (if any)
rule_rank_t rule;
+ // maximal distance to end node (assuming one iteration per loop)
+ static const uint32_t DIST_ERROR;
+ static const uint32_t DIST_MAX;
+ uint32_t dist;
+
// path to end node (for constructing path cover)
path_t * suffix;
void init (const State * s, const s2n_map & s2n);
~Node ();
bool end () const;
+ void calc_dist ();
arccount_t sizeof_permutate (arccount_t inarcs, arccount_t len);
void permutate (const multipath_t & prefix, FILE * input, std::ofstream & keys);
arccount_t cover (const multipath_t & prefix, FILE * input, std::ofstream & keys);
struct Skeleton
{
+ const std::string cond;
+ const uint32_t line;
+
Node * nodes;
+ uint32_t maxlen;
Skeleton (const DFA & dfa);
~Skeleton ();
- void warn_undefined_control_flow (uint32_t line, const std::string & cond);
- void emit_data (uint32_t line, const std::string & cond, const char * fname);
+ void warn_undefined_control_flow ();
+ void emit_data (const char * fname);
static void emit_prolog (OutputFile & o, uint32_t ind, uint32_t maxfill);
static void emit_epilog (OutputFile & o, uint32_t ind);
private:
- void generate_paths (uint32_t line, const std::string & cond, FILE * input, std::ofstream & keys);
+ void calc_maxlen ();
+ void generate_paths (FILE * input, std::ofstream & keys);
FORBID_COPY (Skeleton);
};
static void optimize (Ins * i);
-smart_ptr<DFA> genCode (RegExp *re, Output & output)
+smart_ptr<DFA> genCode (RegExp *re, Output & output, const std::string & cond)
{
CharSet cs;
re->split(cs);
}
}
- smart_ptr<DFA> dfa = make_smart_ptr(new DFA(ins, size, 0, encoding.nCodeUnits(), rep));
+ smart_ptr<DFA> dfa = make_smart_ptr (new DFA
+ ( cond
+ , output.source.get_block_line ()
+ , ins
+ , size
+ , 0
+ , encoding.nCodeUnits()
+ , rep
+ ));
dfa->prepare (output.source, output.max_fill);
namespace re2c
{
-smart_ptr<DFA> genCode (RegExp * re, Output & output);
+smart_ptr<DFA> genCode (RegExp * re, Output & output, const std::string & cond);
} // namespace re2c
void *to;
};
-DFA::DFA(Ins *ins, uint32_t ni, uint32_t lb, uint32_t ub, const Char *rep)
+DFA::DFA
+ ( const std::string & c
+ , uint32_t l
+ , Ins * ins
+ , uint32_t ni
+ , uint32_t lb
+ , uint32_t ub
+ , const Char * rep
+ )
: accepts ()
, skeleton (NULL)
+ , cond (c)
+ , line (l)
, lbChar(lb)
, ubChar(ub)
, nStates(0)
Skeleton * skeleton;
public:
+ const std::string cond;
+ const uint32_t line;
+
uint32_t lbChar;
uint32_t ubChar;
uint32_t nStates;
const Char * free_rep;
public:
- DFA (Ins *, uint32_t, uint32_t, uint32_t, const Char *);
+ DFA
+ ( const std::string &
+ , uint32_t
+ , Ins *
+ , uint32_t
+ , uint32_t
+ , uint32_t
+ , const Char *
+ );
~DFA ();
void addState (State **, State *);
State * findState (Ins **, Ins **);
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 (Output &, uint32_t &, const std::string &, bool, bool &);
+ void emit (Output &, uint32_t &, bool, bool &);
friend std::ostream & operator << (std::ostream &, const DFA &);
it->second = it->second ? mkAlt (def_rule, it->second) : def_rule;
}
- dfa_map[it->first] = genCode(it->second, o);
+ dfa_map[it->first] = genCode(it->second, o, it->first);
}
if (parseMode != Scanner::Rules && dfa_map.find(it->first) != dfa_map.end())
{
- dfa_map[it->first]->emit(o, topIndent, it->first, !--nCount, bPrologBrace);
+ dfa_map[it->first]->emit(o, topIndent, !--nCount, bPrologBrace);
}
}
}
{
if (parseMode != Scanner::Reuse)
{
- dfa_map[""] = genCode(spec, o);
+ dfa_map[""] = genCode(spec, o, "");
}
if (parseMode != Scanner::Rules && dfa_map.find("") != dfa_map.end())
{
- dfa_map[""]->emit(o, topIndent, "", 0, bPrologBrace);
+ dfa_map[""]->emit(o, topIndent, 0, bPrologBrace);
}
}
}
-re2c: warning: line 22: control flow in condition 'r1' is undefined for strings that match '[\x0-\x30\x33-\x60\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
-re2c: warning: line 22: control flow in condition 'r2' is undefined for strings that match '[\x0-\x30\x33-\x61\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
-re2c: warning: line 34: control flow in condition 'r1' is undefined for strings that match '[\x0-\x30\x33-\x60\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
-re2c: warning: line 34: control flow in condition 'r2' is undefined for strings that match '[\x0-\x30\x33-\x61\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
-re2c: warning: line 46: control flow in condition 'r1' is undefined for strings that match '[\x0-\x30\x33-\x60\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
-re2c: warning: line 46: control flow in condition 'r2' is undefined for strings that match '[\x0-\x30\x33-\x61\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
+re2c: warning: line 13: control flow in condition 'r1' is undefined for strings that match '[\x0-\x30\x33-\x60\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
+re2c: warning: line 13: control flow in condition 'r2' is undefined for strings that match '[\x0-\x30\x33-\x61\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
+re2c: warning: line 13: control flow in condition 'r1' is undefined for strings that match '[\x0-\x30\x33-\x60\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
+re2c: warning: line 13: control flow in condition 'r2' is undefined for strings that match '[\x0-\x30\x33-\x61\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
+re2c: warning: line 13: control flow in condition 'r1' is undefined for strings that match '[\x0-\x30\x33-\x60\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
+re2c: warning: line 13: control flow in condition 'r2' is undefined for strings that match '[\x0-\x30\x33-\x61\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
/* Generated by re2c */
// multiple scanners
-re2c: warning: line 20: control flow in condition 'r1' is undefined for strings that match '[\x0-\x30\x33-\x60\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
-re2c: warning: line 20: control flow in condition 'r2' is undefined for strings that match '[\x0-\x30\x33-\x61\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
-re2c: warning: line 32: control flow in condition 'r1' is undefined for strings that match '[\x0-\x30\x33-\x60\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
-re2c: warning: line 32: control flow in condition 'r2' is undefined for strings that match '[\x0-\x30\x33-\x61\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
-re2c: warning: line 44: control flow in condition 'r1' is undefined for strings that match '[\x0-\x30\x33-\x60\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
-re2c: warning: line 44: control flow in condition 'r2' is undefined for strings that match '[\x0-\x30\x33-\x61\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
+re2c: warning: line 13: control flow in condition 'r1' is undefined for strings that match '[\x0-\x30\x33-\x60\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
+re2c: warning: line 13: control flow in condition 'r2' is undefined for strings that match '[\x0-\x30\x33-\x61\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
+re2c: warning: line 13: control flow in condition 'r1' is undefined for strings that match '[\x0-\x30\x33-\x60\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
+re2c: warning: line 13: control flow in condition 'r2' is undefined for strings that match '[\x0-\x30\x33-\x61\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
+re2c: warning: line 13: control flow in condition 'r1' is undefined for strings that match '[\x0-\x30\x33-\x60\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
+re2c: warning: line 13: control flow in condition 'r2' is undefined for strings that match '[\x0-\x30\x33-\x61\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
/* Generated by re2c */
// multiple scanners
-re2c: warning: line 18: control flow in condition 'r1' is undefined for strings that match '[\x0-\x30\x33-\x60\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
-re2c: warning: line 18: control flow in condition 'r2' is undefined for strings that match '[\x0-\x30\x33-\x61\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
+re2c: warning: line 14: control flow in condition 'r1' is undefined for strings that match '[\x0-\x30\x33-\x60\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
+re2c: warning: line 14: control flow in condition 'r2' is undefined for strings that match '[\x0-\x30\x33-\x61\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
re2c: error: line 20, column 1: cannot have a second 'rules:re2c' block