src/codegen/skeleton/control_flow.cc \
src/codegen/skeleton/generate_code.cc \
src/codegen/skeleton/generate_data.cc \
+ src/codegen/skeleton/match_empty.cc \
src/codegen/skeleton/maxlen.cc \
src/codegen/skeleton/skeleton.cc \
src/codegen/skeleton/unreachable.cc \
skeleton->warn_undefined_control_flow ();
skeleton->warn_unreachable_rules ();
+ skeleton->warn_match_empty ();
if (opts->target == opt_t::SKELETON)
{
default_state->action.set_accept (&accepts);
}
- const bool empty_rule = head->rule;
-
- std::vector<std::pair<uint32_t, uint32_t> > stray_cunits;
- uint32_t lb = 0;
- for (uint32_t i = 0; i < head->go.nSpans; ++i)
- {
- if (!head->go.span[i].to->rule)
- {
- stray_cunits.push_back (std::make_pair (lb, head->go.span[i].ub));
- }
- lb = head->go.span[i].ub;
- }
-
- // warn about not shadowed rule that matches empty string
- if (empty_rule && !stray_cunits.empty ())
- {
- warn.match_empty_string (head->rule->loc.line);
- }
-
// split ``base'' states into two parts
for (State * s = head; s; s = s->next)
{
// We only need some examples, the shorter the better.
Node::nakeds_t Node::naked_ways (const way_t & prefix, std::vector<way_t> & ways)
{
- if (!rule.is_none ())
+ if (!rule.rank.is_none ())
{
return nakeds_t (0u);
}
for (arcs_t::iterator i = arcs.begin (); i != arcs.end (); ++i)
{
multipath_t new_prefix = prefix;
- new_prefix.extend (i->first->rule, i->first->restorectx, i->first->ctx, &i->second);
+ new_prefix.extend (i->first->rule, i->first->ctx, &i->second);
i->first->permutate<cunit_t, key_t> (new_prefix, input, keys);
}
}
}
else if (end ())
{
- suffix = new path_t (rule, restorectx, ctx);
+ suffix = new path_t (rule, ctx);
}
else if (loop < 2)
{
for (arcs_t::iterator i = arcs.begin (); i != arcs.end (); ++i)
{
multipath_t new_prefix = prefix;
- new_prefix.extend (i->first->rule, i->first->restorectx, i->first->ctx, &i->second);
+ new_prefix.extend (i->first->rule, i->first->ctx, &i->second);
size = size + i->first->cover<cunit_t, key_t> (new_prefix, input, keys);
if (size.overflow ())
{
}
if (i->first->suffix != NULL && suffix == NULL)
{
- suffix = new path_t (rule, restorectx, ctx);
+ suffix = new path_t (rule, ctx);
suffix->append (i->second[0], i->first->suffix);
}
}
template <typename cunit_t, typename key_t>
void Skeleton::generate_paths_cunit_key (FILE * input, FILE * keys)
{
- multipath_t prefix (nodes->rule, nodes->restorectx, nodes->ctx);
+ multipath_t prefix (nodes->rule, nodes->ctx);
if (nodes->sizeof_permutate (Node::permuts_t (1u), Node::permuts_t (0u)).overflow ())
{
if (nodes->cover<cunit_t, key_t> (prefix, input, keys).overflow ())
--- /dev/null
+#include "src/codegen/skeleton/skeleton.h"
+
+namespace re2c
+{
+
+void Skeleton::warn_match_empty ()
+{
+ Node & head = nodes[0];
+
+ head.calc_reachable ();
+ const std::set<rule_t> & reach = head.reachable;
+
+ // warn about rules that match empty string
+ if (!head.rule.rank.is_none ())
+ {
+ bool reachable = head.end ();
+ for (std::set<rule_t>::const_iterator i = reach.begin ();
+ !reachable && i != reach.end (); ++i)
+ {
+ reachable |= i->rank.is_none ();
+ }
+ if (reachable)
+ {
+ warn.match_empty_string (rules[head.rule.rank].line);
+ }
+ }
+
+ // warn about rules that match empty string with nonempty trailing context
+ if (head.ctx)
+ {
+ for (std::set<rule_t>::const_iterator i = reach.begin (); i != reach.end (); ++i)
+ {
+ if (i->restorectx)
+ {
+ warn.match_empty_string (rules[i->rank].line);
+ }
+ }
+ }
+}
+
+} // namespace re2c
namespace re2c
{
+struct rule_t
+{
+ rule_rank_t rank;
+ bool restorectx;
+
+ rule_t (rule_rank_t r, bool c)
+ : rank (r)
+ , restorectx (c)
+ {}
+
+ // needed by STL containers
+ // same as 'std::pair' comparator
+ bool operator < (const rule_t & r) const
+ {
+ return rank < r.rank
+ || (!(r.rank < rank) && restorectx < r.restorectx);
+ }
+};
+
template <typename arc_t>
class generic_path_t
{
std::vector<arc_t> arcs;
- rule_rank_t rule;
- bool restorectx;
+ rule_t rule;
size_t rule_pos;
bool ctx;
size_t ctx_pos;
public:
- explicit generic_path_t (rule_rank_t r, bool rc, bool c)
+ explicit generic_path_t (rule_t r, bool c)
: arcs ()
, rule (r)
- , restorectx (rc)
, rule_pos (0)
, ctx (c)
, ctx_pos (0)
}
size_t len_matching () const
{
- return restorectx
+ return rule.restorectx
? ctx_pos
: rule_pos;
}
rule_rank_t match () const
{
- return rule;
+ return rule.rank;
}
const arc_t & operator [] (size_t i) const
{
return arcs[i];
}
- void extend (rule_rank_t r, bool rc, bool c, const arc_t & a)
+ void extend (rule_t r, bool c, const arc_t & a)
{
arcs.push_back (a);
- if (!r.is_none ())
+ if (!r.rank.is_none ())
{
rule = r;
- restorectx = rc;
rule_pos = arcs.size ();
}
if (c)
void append (const arc_t & a, const generic_path_t<arc_t> * p)
{
arcs.push_back (a);
- if (!p->rule.is_none ())
+ if (!p->rule.rank.is_none ())
{
rule = p->rule;
- restorectx = p->restorectx;
rule_pos = arcs.size () + p->rule_pos;
}
if (p->ctx)
template <typename arc1_t, typename arc2_t>
size_t len_matching (const generic_path_t<arc1_t> & prefix, const generic_path_t<arc2_t> & suffix)
{
- const bool none = suffix.rule.is_none ();
+ const bool none = suffix.rule.rank.is_none ();
bool restorectx = none
- ? prefix.restorectx
- : suffix.restorectx;
+ ? prefix.rule.restorectx
+ : suffix.rule.restorectx;
const size_t rule_pos = none
? prefix.rule_pos
: prefix.arcs.size () + suffix.rule_pos;
template <typename arc1_t, typename arc2_t>
rule_rank_t match (const generic_path_t<arc1_t> & prefix, const generic_path_t<arc2_t> & suffix)
{
- return suffix.rule.is_none ()
- ? prefix.rule
- : suffix.rule;
+ return suffix.rule.rank.is_none ()
+ ? prefix.rule.rank
+ : suffix.rule.rank;
}
typedef generic_path_t<uint32_t> path_t;
: arcs ()
, arcsets ()
, loop (0)
- , rule (rule_rank_t::none ())
- , restorectx (false)
+ , rule (rule_rank_t::none (), false)
, ctx (false)
, dist (DIST_ERROR)
, reachable ()
const bool is_accepting = s && s->rule;
if (is_accepting)
{
- rule = s->rule->rank;
- restorectx = s->rule->ctx->fixedLength () != 0;
+ rule.rank = s->rule->rank;
+ rule.restorectx = s->rule->ctx->fixedLength () != 0;
}
ctx = s && s->isPreCtxt;
uint32_t maxrule = 0;
for (uint32_t i = 0; i < nodes_count; ++i)
{
- const rule_rank_t r = nodes[i].rule;
+ const rule_rank_t r = nodes[i].rule.rank;
if (!r.is_none ())
{
maxrule = std::max (maxrule, r.uint32 ());
// (controls looping in graph traversals)
uint8_t loop;
- // rule number for corresponding DFA state (if any)
- rule_rank_t rule;
- // whether this rule must rollback input position to the beginnig of trailing context
- bool restorectx;
+ // rule for corresponding DFA state (if any)
+ rule_t rule;
// start of trailing context
bool ctx;
uint32_t dist;
// rules reachable from this node (including absent rule)
- std::set<rule_rank_t> reachable;
+ std::set<rule_t> reachable;
// path to end node (for constructing path cover)
path_t * suffix;
~Skeleton ();
void warn_undefined_control_flow ();
void warn_unreachable_rules ();
+ void warn_match_empty ();
void emit_data (const char * fname);
static void emit_prolog (OutputFile & o);
void emit_start
nodes->calc_reachable ();
for (uint32_t i = 0; i < nodes_count; ++i)
{
- const rule_rank_t r1 = nodes[i].rule;
- const std::set<rule_rank_t> & rs = nodes[i].reachable;
- for (std::set<rule_rank_t>::const_iterator j = rs.begin (); j != rs.end (); ++j)
+ const rule_rank_t r1 = nodes[i].rule.rank;
+ const std::set<rule_t> & rs = nodes[i].reachable;
+ for (std::set<rule_t>::const_iterator j = rs.begin (); j != rs.end (); ++j)
{
- const rule_rank_t r2 = *j;
+ const rule_rank_t r2 = j->rank;
if (r1 == r2 || r2.is_none ())
{
rules[r1].reachable = true;
re2c: warning: line 3: control flow is undefined for strings that match '[\x0-\x60\x62-\xFF]', use default rule '*' [-Wundefined-control-flow]
+re2c: warning: line 2: rule matches empty string [-Wmatch-empty-string]
/* Generated by re2c */
#line 1 "bug116.re"
+re2c: warning: line 253: rule matches empty string [-Wmatch-empty-string]
re2c: error: line 288, column 1: empty character class
+re2c: warning: line 253: rule matches empty string [-Wmatch-empty-string]
re2c: warning: line 288: empty character class [-Wempty-character-class]
+re2c: warning: line 289: rule matches empty string [-Wmatch-empty-string]
/* Generated by re2c */
#line 1 "rexx.--empty-class(match-empty).re"
#include "scanio.h"
+re2c: warning: line 253: rule matches empty string [-Wmatch-empty-string]
re2c: warning: line 288: empty character class [-Wempty-character-class]
re2c: warning: line 290: control flow is undefined for strings that match
'[\x0-\x8\xA-\xC\xE-\x1F\x21-\x2E\x30-\xFF]'
+re2c: warning: line 253: rule matches empty string [-Wmatch-empty-string]
re2c: warning: line 288: empty character class [-Wempty-character-class]
+re2c: warning: line 289: rule matches empty string [-Wmatch-empty-string]
/* Generated by re2c */
#line 1 "rexx.re"
#include "scanio.h"