src/ir/regexp/encoding/utf16/utf16_regexp.cc \
src/ir/regexp/encoding/utf16/utf16.cc \
src/ir/regexp/encoding/utf16/utf16_range.cc \
- src/ir/regexp/nullable.cc \
src/ir/regexp/regexp.cc \
src/ir/regexp/split_charset.cc \
src/ir/compile.cc \
// skeleton must be constructed after DFA construction
// but prior to any other DFA transformations
Skeleton *skeleton = new Skeleton(dfa, cs, spec.rules, name, cond, line);
- nullable_rules(spec.re, skeleton->nullable_rules);
minimization(dfa);
+++ /dev/null
-#include "src/ir/regexp/regexp.h"
-
-namespace re2c
-{
-
-static bool nullable(const RegExp *re)
-{
- switch (re->tag) {
- default:
- case RegExp::NIL:
- return true;
- case RegExp::SYM:
- return false;
- case RegExp::ALT:
- return nullable(re->pld.alt.re1)
- || nullable(re->pld.alt.re2);
- case RegExp::CAT:
- return nullable(re->pld.cat.re1)
- && nullable(re->pld.cat.re2);
- case RegExp::ITER:
- return true;
- case RegExp::RULE:
- return nullable(re->pld.rule.re);
- }
-}
-
-void nullable_rules(const RegExp *re, std::vector<RuleInfo*> &rs)
-{
- switch (re->tag) {
- case RegExp::ALT:
- nullable_rules(re->pld.alt.re1, rs);
- nullable_rules(re->pld.alt.re2, rs);
- break;
- case RegExp::RULE:
- if (nullable(re->pld.rule.re)) {
- rs.push_back(re->pld.rule.info);
- }
- break;
- default:
- break;
- }
-}
-
-} // end namespace re2c
-
{
static uint32_t fixlen(const RegExp *re);
+static bool nullable(const RegExp *re);
free_list<RegExp*> RegExp::flist;
ctx_len = ~0u;
}
- re->pld.rule.info = new RuleInfo(loc, rank, code, newcond, ctx_len);
+ re->pld.rule.info = new RuleInfo(loc, rank, code, newcond, ctx_len, nullable(r1));
return re;
}
re->pld.rule.re = rule->pld.rule.re;
re->pld.rule.ctx = rule->pld.rule.ctx;
const RuleInfo *info = rule->pld.rule.info;
- re->pld.rule.info = new RuleInfo(info->loc, rank,
- info->code, &info->newcond, info->ctx_len);
+ re->pld.rule.info = new RuleInfo(info->loc, rank, info->code,
+ &info->newcond, info->ctx_len, info->nullable);
return re;
}
}
}
+bool nullable(const RegExp *re)
+{
+ switch (re->tag) {
+ default:
+ case RegExp::NIL:
+ return true;
+ case RegExp::SYM:
+ return false;
+ case RegExp::ALT:
+ return nullable(re->pld.alt.re1)
+ || nullable(re->pld.alt.re2);
+ case RegExp::CAT:
+ return nullable(re->pld.cat.re1)
+ && nullable(re->pld.cat.re2);
+ case RegExp::ITER:
+ return true;
+ case RegExp::RULE:
+ return nullable(re->pld.rule.re);
+ }
+}
+
} // namespace re2c
};
void split(const RegExp *re, std::set<uint32_t> &cs);
-void nullable_rules(const RegExp *re, std::vector<RuleInfo*> &rs);
-
const RegExp *mkAlt(const RegExp *re1, const RegExp *re2);
const RegExp *doAlt(const RegExp *re1, const RegExp *re2);
const RegExp *doCat(const RegExp *re1, const RegExp *re2);
, nodes (new Node [nodes_count + 1]) // +1 for default state
, sizeof_key (4)
, rules (rs)
- , nullable_rules ()
{
const size_t nc = cs.size() - 1;
Node * nodes;
size_t sizeof_key;
rules_t rules;
- std::vector<RuleInfo*> nullable_rules;
Skeleton
( const dfa_t &dfa
// - rules that match empty strins with nonempty trailing context
// false positives on partially shadowed (yet reachable) rules, e.g.:
// [^]?
- for (std::vector<RuleInfo*>::const_iterator i = nullable_rules.begin();
- i != nullable_rules.end(); ++i)
+ for (rules_t::const_iterator i = rules.begin(); i != rules.end(); ++i)
{
- const RuleInfo *ri = *i;
- if (ri->reachable)
+ const RuleInfo *r = *i;
+ if (r->nullable && r->reachable)
{
- warn.match_empty_string(ri->loc.line);
+ warn.match_empty_string(r->loc.line);
}
}
}
std::set<uint32_t> shadow;
bool reachable;
+ bool nullable;
RuleInfo
( const Loc & l
, const Code * c
, const std::string * cond
, uint32_t cl
+ , bool nl
)
: loc (l)
, ctx_len (cl)
, newcond (cond ? *cond : "")
, shadow ()
, reachable (false)
+ , nullable (nl)
{}
FORBID_COPY(RuleInfo);