src/dfa/dfa.h \
src/dfa/ins.h \
src/dfa/re.h \
+ src/dfa/rule_rank.h \
src/dfa/state.h \
src/globals.h \
src/mbo_getopt.h \
src/parse/token.h \
src/util/allocate.h \
src/util/c99_stdint.h \
+ src/util/counter.h \
src/util/forbid_copy.h \
src/util/free_list.h \
src/util/local_increment.h \
src/dfa/encoding/utf8/utf8_range.cc \
src/dfa/encoding/utf8/utf8_regexp.cc \
src/dfa/dfa.cc \
+ src/dfa/rule_rank.cc \
src/main.cc \
src/mbo_getopt.cc \
src/parse/input.cc \
o << indent(ind);
if (flag_skeleton)
{
- o << "{ if (cursor == &data[result[i].endpos] && result[i].rule == " << rule->accept << ") ";
+ o << "{ if (cursor == &data[result[i].endpos] && result[i].rule == " << rule->rank << ") ";
o << "{ cursor = &data[result[i].startpos]; continue; }";
o << " else ";
o << "{ printf (\"error: %lu/%u, %u/%u, '%s'\\n\", cursor - data, result[i].endpos, result[i].rule, "
- << rule->accept
+ << rule->rank
<< ", &data[result[i].startpos]); return 1; } }";
}
else if (rule->code->autogen)
// In '-f' mode, default state is always state 0
if (fFlag)
{
- used.insert (label_counter_t::FIRST);
+ used.insert (label_t::first ());
}
if (force_start)
{
label_t CpgotoTable::max_label () const
{
- label_t max = label_counter_t::FIRST;
+ label_t max = label_t::first ();
for (uint32_t i = 0; i < TABLE_SIZE; ++i)
{
if (max < table[i]->label)
{
o << indent (ind) << "static void *" << mapCodeName["yytarget"] << "[256] = {\n";
o << indent (++ind);
- const uint32_t max_digits = width (max_label ());
+ const uint32_t max_digits = max_label ().width ();
for (uint32_t i = 0; i < TABLE_SIZE; ++i)
{
o << "&&" << labelPrefix << table[i]->label;
}
else
{
- const uint32_t padding = max_digits - width (table[i]->label) + 1;
+ const uint32_t padding = max_digits - table[i]->label.width () + 1;
o << "," << std::string (padding, ' ');
}
}
namespace re2c {
-const label_t label_counter_t::FIRST (0);
+const uint32_t label_t::FIRST = 0;
-std::ostream & operator << (std::ostream & o, label_t l)
+label_t::label_t ()
+ : value (FIRST)
+{}
+
+void label_t::inc ()
{
- o << l.value;
- return o;
+ ++value;
+}
+
+label_t label_t::first ()
+{
+ return label_t ();
}
-bool operator < (const label_t & l1, const label_t & l2)
+bool label_t::operator < (const label_t & l) const
{
- return l1.value < l2.value;
+ return value < l.value;
}
-uint32_t width (label_t l)
+uint32_t label_t::width () const
{
- uint32_t digits = 0;
- while (l.value /= 10) ++digits;
- return digits;
+ uint32_t v = value;
+ uint32_t n = 0;
+ while (v /= 10) ++n;
+ return n;
+}
+
+std::ostream & operator << (std::ostream & o, label_t l)
+{
+ o << l.value;
+ return o;
}
} // namespace re2c
#include <iosfwd>
#include "src/util/c99_stdint.h"
+#include "src/util/counter.h"
namespace re2c {
+// label public API:
+// - get first label
+// - compare labels
+// - get label width
+// - output label to std::ostream
+//
+// label private API (for label counter):
+// - get initial label
+// - get next label
class label_t
{
+ static const uint32_t FIRST;
uint32_t value;
- explicit label_t (uint32_t v)
- : value (v)
- {}
- friend class label_counter_t;
- friend std::ostream & operator << (std::ostream & o, label_t l);
- friend bool operator < (const label_t & l1, const label_t & l2);
- friend uint32_t width (label_t l);
-};
+ label_t ();
+ void inc ();
-class label_counter_t
-{
public:
- static const label_t FIRST;
-
-private:
- label_t label;
+ static label_t first ();
+ bool operator < (const label_t & l) const;
+ uint32_t width () const;
+ friend std::ostream & operator << (std::ostream & o, label_t l);
-public:
- label_counter_t ()
- : label (FIRST)
- {}
- label_t next ()
- {
- label_t l = label;
- ++label.value;
- return l;
- }
- void reset ()
- {
- label = FIRST;
- }
+ friend class counter_t<label_t>;
};
} // namespace re2c
return u;
}
+OutputFile & operator << (OutputFile & u, rule_rank_t r)
+{
+ u.stream () << r;
+ return u;
+}
+
void OutputFile::insert_code ()
{
blocks.back ()->fragments.push_back (new OutputFragment (OutputFragment::CODE, 0));
#include <vector>
#include "src/codegen/label.h"
+#include "src/dfa/rule_rank.h"
#include "src/util/c99_stdint.h"
#include "src/util/forbid_copy.h"
std::vector<OutputBlock *> blocks;
public:
- label_counter_t label_counter;
+ counter_t<label_t> label_counter;
private:
std::ostream & stream ();
friend OutputFile & operator << (OutputFile & o, const std::string & s);
friend OutputFile & operator << (OutputFile & o, const char * s);
friend OutputFile & operator << (OutputFile & o, label_t l);
+ friend OutputFile & operator << (OutputFile & o, rule_rank_t l);
void insert_line_info ();
void insert_state_goto (uint32_t ind);
}
// create rule states
- std::map<uint32_t, State *> rules;
+ std::map<rule_rank_t, State *> rules;
for (State * s = head; s; s = s->next)
{
if (s->rule)
{
- if (rules.find (s->rule->accept) == rules.end ())
+ if (rules.find (s->rule->rank) == rules.end ())
{
State *n = new State;
n->action.set_rule (s->rule);
- rules[s->rule->accept] = n;
+ rules[s->rule->rank] = n;
addState(&s->next, n);
}
for (uint32_t i = 0; i < s->go.nSpans; ++i)
{
if (!s->go.span[i].to)
{
- s->go.span[i].to = rules[s->rule->accept];
+ s->go.span[i].to = rules[s->rule->rank];
}
}
}
{
if (!s->go.span[i].to->rule && s->go.span[i].to->action.type != Action::RULE)
{
- const uint32_t accept = accepts.find_or_add (rules[s->rule->accept]);
+ const uint32_t accept = accepts.find_or_add (rules[s->rule->rank]);
s->action.set_save (accept);
}
}
namespace skeleton
{
-Path::Path (const chars_t & cs, uint32_t l, uint32_t r)
+Path::Path (const chars_t & cs, uint32_t l, rule_rank_t r)
: chars (cs)
, length (l)
, rule (r)
{}
-void Path::update (uint32_t r)
+void Path::update (rule_rank_t r)
{
- if (r != NO_RULE)
+ if (!r.is_none ())
{
length = chars.size ();
rule = r;
}
}
-void Path::extend (uint32_t r, uint32_t c)
+void Path::extend (rule_rank_t r, uint32_t c)
{
update (r);
chars.push_back (c);
void Path::append (const Path * p)
{
- if (p->rule != NO_RULE)
+ if (!p->rule.is_none ())
{
length = chars.size () + p->length;
rule = p->rule;
#include <vector>
+#include "src/dfa/rule_rank.h"
#include "src/util/c99_stdint.h"
namespace re2c
namespace skeleton
{
-const uint32_t NO_RULE = 0xFFFFffff;
-
struct Path
{
typedef std::vector<uint32_t> chars_t;
chars_t chars;
uint32_t length;
- uint32_t rule;
+ rule_rank_t rule;
- Path (const chars_t & cs, uint32_t l, uint32_t r);
- void update (uint32_t r);
- void extend (uint32_t r, uint32_t c);
+ Path (const chars_t & cs, uint32_t l, rule_rank_t r);
+ void update (rule_rank_t r);
+ void extend (rule_rank_t r, uint32_t c);
void append (const Path * p);
};
Node::Node (const State * s, const s2n_map & s2n)
: arcs ()
, loop (0)
- , rule (NO_RULE)
+ , rule (rule_rank_t::none ())
, path_len (UNKNOWN_LEN)
, path (NULL)
{
const bool is_accepting = s && s->rule;
if (is_accepting)
{
- rule = s->rule->accept;
+ rule = s->rule->rank;
}
const bool is_final = !s || (s->go.nSpans == 1 && !s->go.span[0].to);
void Skeleton::generate_paths (std::vector<Path> & results)
{
std::vector<Path> prefixes;
- prefixes.push_back (Path (Path::chars_t (), 0, NO_RULE));
+ prefixes.push_back (Path (Path::chars_t (), 0, rule_rank_t::none ()));
if (nodes->estimate_size_all (1, 0) == DATA_LIMIT)
{
uint8_t loop;
// rule number for corresponding DFA state (if any)
- uint32_t rule;
+ rule_rank_t rule;
// stuff for constructing path cover (for large graphs)
static const uint32_t UNKNOWN_LEN;
break;
case TERM:
- o << "term " << ((RuleOp*) i.i.link)->accept;
+ o << "term " << ((RuleOp*) i.i.link)->rank;
break;
}
return new MatchOp(def);
}
-RuleOp::RuleOp(RegExp *e, RegExp *c, Token *t, uint32_t a, InsAccess access)
+RuleOp::RuleOp(RegExp *e, RegExp *c, Token *t, rule_rank_t r, InsAccess access)
: exp(e)
, ctx(c)
, ins(NULL)
- , accept(a)
+ , rank(r)
, code(t)
, line(0)
{
}
else if (i->i.tag == TERM)
{
- if (!s->rule || ((RuleOp*) i->i.link)->accept < s->rule->accept)
+ if (!s->rule || ((RuleOp*) i->i.link)->rank < s->rule->rank)
s->rule = (RuleOp*) i->i.link;
}
else if (i->i.tag == CTXT)
#include <string>
#include "src/dfa/ins.h"
+#include "src/dfa/rule_rank.h"
#include "src/globals.h"
#include "src/parse/token.h"
#include "src/util/range.h"
public:
RegExp *ctx;
Ins *ins;
- uint32_t accept;
+ rule_rank_t rank;
Token *code;
uint32_t line;
public:
- RuleOp(RegExp*, RegExp*, Token*, uint32_t, InsAccess);
+ RuleOp(RegExp*, RegExp*, Token*, rule_rank_t, InsAccess);
~RuleOp()
{
--- /dev/null
+#include <ostream>
+
+#include "src/dfa/rule_rank.h"
+
+namespace re2c
+{
+
+const uint32_t rule_rank_t::NONE = 0xFFFFffff;
+
+rule_rank_t::rule_rank_t ()
+ : value (0)
+{}
+
+void rule_rank_t::inc ()
+{
+ ++value;
+}
+
+rule_rank_t rule_rank_t::none ()
+{
+ rule_rank_t r;
+ r.value = NONE;
+ return r;
+}
+
+bool rule_rank_t::is_none () const
+{
+ return value == NONE;
+}
+
+bool rule_rank_t::operator < (const rule_rank_t & r) const
+{
+ return value < r.value;
+}
+
+std::ostream & operator << (std::ostream & o, rule_rank_t r)
+{
+ o << r.value;
+ return o;
+}
+
+} // namespace re2c
--- /dev/null
+#ifndef __RULE_RANK__
+#define __RULE_RANK__
+
+#include <iosfwd>
+
+#include "src/util/c99_stdint.h"
+#include "src/util/counter.h"
+
+namespace re2c
+{
+
+// rule rank public API:
+// - get rule rank corresponding to nonexistent rule
+// - check if rank corresponds to nonexistent rule
+// - compare ranks
+// - output rank to std::ostream
+//
+// rule rank private API (for rule rank counter):
+// - get first rank
+// - get next rank
+class rule_rank_t
+{
+ static const uint32_t NONE;
+ uint32_t value;
+ rule_rank_t ();
+ void inc ();
+
+public:
+ static rule_rank_t none ();
+ bool is_none () const;
+ bool operator < (const rule_rank_t & r) const;
+ friend std::ostream & operator << (std::ostream & o, rule_rank_t r);
+
+ friend class counter_t<rule_rank_t>;
+};
+
+} // namespace re2c
+
+#endif // __RULE_RANK__
Action action;
State ()
- : label (label_counter_t::FIRST)
+ : label (label_t::first ())
, rule (NULL)
, next (0)
, link (NULL)
void yyerror(const char*);
}
-static uint32_t accept;
+static counter_t<rule_rank_t> rank_counter;
static re2c::RegExpMap specMap;
static RegExp *spec = NULL, *specNone = NULL;
static RuleOpList specStar;
for(CondList::const_iterator it = clist->begin(); it != clist->end(); ++it)
{
Token *token = new Token(code, in->get_fname (), in->get_cline (), newcond);//condcpy);
- RuleOp *rule = new RuleOp(expr, look, token, accept++, ins_access);
+ RuleOp *rule = new RuleOp(expr, look, token, rank_counter.next (), ins_access);
RegExpMap::iterator itRE = specMap.find(*it);
{
in->fatal("condition or '<*>' required when using -c switch");
}
- $$ = new RuleOp($1, $2, $3, accept++, RegExp::SHARED);
+ $$ = new RuleOp($1, $2, $3, rank_counter.next (), RegExp::SHARED);
spec = spec? mkAlt(spec, $$) : $$;
}
| STAR CODE /* default rule */
Token *token = new Token($7, $7->source, $7->line, $6);
delete $7;
delete $6;
- specStar.push_back(new RuleOp($4, $5, token, accept++, RegExp::PRIVATE));
+ specStar.push_back(new RuleOp($4, $5, token, rank_counter.next (), RegExp::PRIVATE));
}
| '<' STAR '>' expr look ':' newcond
{
context_check(NULL);
Token *token = new Token(NULL, in->get_fname (), in->get_cline (), $7);
delete $7;
- specStar.push_back(new RuleOp($4, $5, token, accept++, RegExp::PRIVATE));
+ specStar.push_back(new RuleOp($4, $5, token, rank_counter.next (), RegExp::PRIVATE));
}
| '<' STAR '>' look newcond CODE
{
Token *token = new Token($3, $3->source, $3->line, $2);
delete $2;
delete $3;
- $$ = specNone = new RuleOp(new NullOp(), new NullOp(), token, accept++, RegExp::SHARED);
+ $$ = specNone = new RuleOp(new NullOp(), new NullOp(), token, rank_counter.next (), RegExp::SHARED);
}
| NOCOND ':' newcond
{
}
Token *token = new Token(NULL, in->get_fname (), in->get_cline (), $3);
delete $3;
- $$ = specNone = new RuleOp(new NullOp(), new NullOp(), token, accept++, RegExp::SHARED);
+ $$ = specNone = new RuleOp(new NullOp(), new NullOp(), token, rank_counter.next (), RegExp::SHARED);
}
| SETUP STAR '>' CODE
{
{
dfa_map.clear();
}
- accept = 0;
+ rank_counter.reset ();
spec = NULL;
ruleDefault = NULL;
in->set_in_parse(true);
dfa_map.clear();
parse_cleanup();
spec = NULL;
- accept = 0;
+ rank_counter.reset ();
ruleDefault = NULL;
in->set_in_parse(true);
yyparse();
// now that all rules have been parsed, we can fix it
for (RuleOpList::const_iterator itOp = specStar.begin(); itOp != specStar.end(); ++itOp)
{
- (*itOp)->accept = accept++;
+ (*itOp)->rank = rank_counter.next ();
}
// merge <*> rules to all conditions
// note that all conditions use the same regexp for <*> rules,
itRuleDefault = ruleDefaultMap.find(it->first);
if (itRuleDefault != ruleDefaultMap.end())
{
- RuleOp * def = new RuleOp(in->mkDefault(), new NullOp(), itRuleDefault->second, accept++, RegExp::SHARED);
+ RuleOp * def = new RuleOp(in->mkDefault(), new NullOp(), itRuleDefault->second, rank_counter.next (), RegExp::SHARED);
it->second.second = it->second.second ? mkAlt(def, it->second.second) : def;
}
else
itRuleDefault = ruleDefaultMap.find("*");
if (itRuleDefault != ruleDefaultMap.end())
{
- RuleOp * def = new RuleOp(in->mkDefault(), new NullOp(), itRuleDefault->second, accept++, RegExp::SHARED);
+ RuleOp * def = new RuleOp(in->mkDefault(), new NullOp(), itRuleDefault->second, rank_counter.next (), RegExp::SHARED);
it->second.second = it->second.second ? mkAlt(def, it->second.second) : def;
}
}
{
if (ruleDefault != NULL && parseMode != Scanner::Reuse)
{
- RuleOp * def = new RuleOp(in->mkDefault(), new NullOp(), ruleDefault, accept++, RegExp::SHARED);
+ RuleOp * def = new RuleOp(in->mkDefault(), new NullOp(), ruleDefault, rank_counter.next (), RegExp::SHARED);
spec = spec ? mkAlt(def, spec) : def;
}
if (spec || !dfa_map.empty())
--- /dev/null
+#ifndef __RE2C_UTIL_COUNTER__
+#define __RE2C_UTIL_COUNTER__
+
+namespace re2c {
+
+template <typename num_t>
+class counter_t
+{
+ num_t num;
+
+public:
+ counter_t ()
+ : num ()
+ {}
+ num_t next ()
+ {
+ num_t n = num;
+ num.inc ();
+ return n;
+ }
+ void reset ()
+ {
+ num = num_t ();
+ }
+};
+
+} // namespace re2c
+
+#endif // __RE2C_UTIL_COUNTER__