pull/219/head
yhirose 2 years ago
parent 159d5e097c
commit 93d0489098
  1. 68
      peglib.h
  2. 10
      test/test2.cc

@ -1953,23 +1953,7 @@ struct HasEmptyElement : public Ope::Visitor {
HasEmptyElement(std::vector<std::pair<const char *, std::string>> &refs)
: refs_(refs) {}
void visit(Sequence &ope) override {
auto save_is_empty = false;
const char *save_error_s = nullptr;
std::string save_error_name;
for (auto op : ope.opes_) {
op->accept(*this);
if (!is_empty) { return; }
save_is_empty = is_empty;
save_error_s = error_s;
save_error_name = error_name;
is_empty = false;
error_name.clear();
}
is_empty = save_is_empty;
error_s = save_error_s;
error_name = save_error_name;
}
void visit(Sequence &ope) override;
void visit(PrioritizedChoice &ope) override {
for (auto op : ope.opes_) {
op->accept(*this);
@ -2012,10 +1996,15 @@ private:
};
struct DetectInfiniteLoop : public Ope::Visitor {
DetectInfiniteLoop(const char *s, const std::string &name) {
DetectInfiniteLoop(const char *s, const std::string &name,
std::vector<std::pair<const char *, std::string>> &refs)
: refs_(refs) {
refs_.emplace_back(s, name);
}
DetectInfiniteLoop(std::vector<std::pair<const char *, std::string>> &refs)
: refs_(refs) {}
void visit(Sequence &ope) override {
for (auto op : ope.opes_) {
op->accept(*this);
@ -2059,7 +2048,7 @@ struct DetectInfiniteLoop : public Ope::Visitor {
std::string error_name;
private:
std::vector<std::pair<const char *, std::string>> refs_;
std::vector<std::pair<const char *, std::string>> &refs_;
std::unordered_map<std::string, bool> has_error_cache_;
};
@ -2974,6 +2963,44 @@ inline void DetectLeftRecursion::visit(Reference &ope) {
done_ = true;
}
inline void HasEmptyElement::visit(Sequence &ope) {
auto save_is_empty = false;
const char *save_error_s = nullptr;
std::string save_error_name;
auto it = ope.opes_.begin();
while (it != ope.opes_.end()) {
(*it)->accept(*this);
if (!is_empty) {
++it;
while (it != ope.opes_.end()) {
DetectInfiniteLoop vis(refs_);
(*it)->accept(vis);
if (vis.has_error) {
std::cout << "infinite loop!" << std::endl;
is_empty = true;
error_s = vis.error_s;
error_name = vis.error_name;
}
++it;
}
return;
}
save_is_empty = is_empty;
save_error_s = error_s;
save_error_name = error_name;
is_empty = false;
error_name.clear();
++it;
}
is_empty = save_is_empty;
error_s = save_error_s;
error_name = save_error_name;
}
inline void HasEmptyElement::visit(Reference &ope) {
auto it = std::find_if(refs_.begin(), refs_.end(),
[&](const std::pair<const char *, std::string> &ref) {
@ -3956,7 +3983,8 @@ private:
bool detect_infiniteLoop(const Data &data, Definition &rule, const Log &log,
const char *s) const {
DetectInfiniteLoop vis(data.start_pos, rule.name);
std::vector<std::pair<const char *, std::string>> refs;
DetectInfiniteLoop vis(data.start_pos, rule.name, refs);
rule.accept(vis);
if (vis.has_error) {
if (log) {

@ -223,6 +223,16 @@ TEST(InfiniteLoopTest, word) {
EXPECT_FALSE(pg);
}
TEST(InfiniteLoopTest, in_sequence) {
parser pg(R"(
S <- A*
A <- 'a' B
B <- 'a' ''*
)");
EXPECT_FALSE(pg);
}
TEST(PrecedenceTest, Precedence_climbing) {
parser parser(R"(
START <- _ EXPRESSION

Loading…
Cancel
Save