mirror of
https://github.com/yhirose/cpp-peglib.git
synced 2024-12-22 11:55:30 +00:00
Added Ignore operator.
This commit is contained in:
parent
fdf10521c6
commit
50768de875
53
peglib.h
53
peglib.h
@ -737,11 +737,8 @@ public:
|
||||
size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||
const auto& rule = *ope_;
|
||||
auto error_pos = c.error_pos;
|
||||
auto& chldsv = c.push();
|
||||
auto len = rule.parse(s, n, sv, c, dt);
|
||||
c.pop();
|
||||
if (success(len))
|
||||
{
|
||||
if (success(len)) {
|
||||
c.set_error_pos(s);
|
||||
return -1;
|
||||
} else {
|
||||
@ -856,7 +853,6 @@ public:
|
||||
: ope_(ope), match_action_(ma), id(n), name(s) {}
|
||||
|
||||
size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||
assert(ope_);
|
||||
const auto& rule = *ope_;
|
||||
auto len = rule.parse(s, n, sv, c, dt);
|
||||
if (success(len) && match_action_) {
|
||||
@ -880,7 +876,6 @@ public:
|
||||
Anchor(const std::shared_ptr<Ope>& ope) : ope_(ope) {}
|
||||
|
||||
size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||
assert(ope_);
|
||||
const auto& rule = *ope_;
|
||||
auto len = rule.parse(s, n, sv, c, dt);
|
||||
if (success(len)) {
|
||||
@ -896,6 +891,25 @@ public:
|
||||
std::shared_ptr<Ope> ope_;
|
||||
};
|
||||
|
||||
class Ignore : public Ope
|
||||
{
|
||||
public:
|
||||
Ignore(const std::shared_ptr<Ope>& ope) : ope_(ope) {}
|
||||
|
||||
size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override {
|
||||
const auto& rule = *ope_;
|
||||
auto& chldsv = c.push();
|
||||
auto len = rule.parse(s, n, chldsv, c, dt);
|
||||
c.pop();
|
||||
return len;
|
||||
}
|
||||
|
||||
void accept(Visitor& v) override;
|
||||
|
||||
//private:
|
||||
std::shared_ptr<Ope> ope_;
|
||||
};
|
||||
|
||||
typedef std::function<size_t(const char* s, size_t n, SemanticValues& sv, any& dt)> Parser;
|
||||
|
||||
class User : public Ope
|
||||
@ -992,6 +1006,7 @@ struct Ope::Visitor
|
||||
virtual void visit(AnyCharacter& ope) = 0;
|
||||
virtual void visit(Capture& ope) = 0;
|
||||
virtual void visit(Anchor& ope) = 0;
|
||||
virtual void visit(Ignore& ope) = 0;
|
||||
virtual void visit(User& ope) = 0;
|
||||
virtual void visit(WeakHolder& ope) = 0;
|
||||
virtual void visit(Holder& ope) = 0;
|
||||
@ -1021,6 +1036,7 @@ struct AssignIDToDefinition : public Ope::Visitor
|
||||
void visit(AnyCharacter& ope) override {}
|
||||
void visit(Capture& ope) override { ope.ope_->accept(*this); }
|
||||
void visit(Anchor& ope) override { ope.ope_->accept(*this); }
|
||||
void visit(Ignore& ope) override { ope.ope_->accept(*this); }
|
||||
void visit(User& ope) override {}
|
||||
void visit(WeakHolder& ope) override { ope.weak_.lock()->accept(*this); }
|
||||
void visit(Holder& ope) override;
|
||||
@ -1046,14 +1062,15 @@ struct IsToken : public Ope::Visitor
|
||||
void visit(ZeroOrMore& ope) override { ope.ope_->accept(*this); }
|
||||
void visit(OneOrMore& ope) override { ope.ope_->accept(*this); }
|
||||
void visit(Option& ope) override { ope.ope_->accept(*this); }
|
||||
void visit(AndPredicate& ope) override { ope.ope_->accept(*this); }
|
||||
void visit(NotPredicate& ope) override { ope.ope_->accept(*this); }
|
||||
void visit(AndPredicate& ope) override {}
|
||||
void visit(NotPredicate& ope) override {}
|
||||
void visit(LiteralString& ope) override {}
|
||||
void visit(CharacterClass& ope) override {}
|
||||
void visit(Character& ope) override {}
|
||||
void visit(AnyCharacter& ope) override {}
|
||||
void visit(Capture& ope) override { ope.ope_->accept(*this); }
|
||||
void visit(Anchor& ope) override { has_anchor = true; }
|
||||
void visit(Ignore& ope) override { ope.ope_->accept(*this); }
|
||||
void visit(User& ope) override {}
|
||||
void visit(WeakHolder& ope) override { ope.weak_.lock()->accept(*this); }
|
||||
void visit(Holder& ope) override {}
|
||||
@ -1342,6 +1359,7 @@ inline void Character::accept(Visitor& v) { v.visit(*this); }
|
||||
inline void AnyCharacter::accept(Visitor& v) { v.visit(*this); }
|
||||
inline void Capture::accept(Visitor& v) { v.visit(*this); }
|
||||
inline void Anchor::accept(Visitor& v) { v.visit(*this); }
|
||||
inline void Ignore::accept(Visitor& v) { v.visit(*this); }
|
||||
inline void User::accept(Visitor& v) { v.visit(*this); }
|
||||
inline void WeakHolder::accept(Visitor& v) { v.visit(*this); }
|
||||
inline void Holder::accept(Visitor& v) { v.visit(*this); }
|
||||
@ -1419,6 +1437,10 @@ inline std::shared_ptr<Ope> anc(const std::shared_ptr<Ope>& ope) {
|
||||
return std::make_shared<Anchor>(ope);
|
||||
}
|
||||
|
||||
inline std::shared_ptr<Ope> ign(const std::shared_ptr<Ope>& ope) {
|
||||
return std::make_shared<Ignore>(ope);
|
||||
}
|
||||
|
||||
inline std::shared_ptr<Ope> usr(std::function<size_t (const char* s, size_t n, SemanticValues& sv, any& dt)> fn) {
|
||||
return std::make_shared<User>(fn);
|
||||
}
|
||||
@ -1518,7 +1540,7 @@ private:
|
||||
g["Sequence"] <= zom(g["Prefix"]);
|
||||
g["Prefix"] <= seq(opt(cho(g["AND"], g["NOT"])), g["Suffix"]);
|
||||
g["Suffix"] <= seq(g["Primary"], opt(cho(g["QUESTION"], g["STAR"], g["PLUS"])));
|
||||
g["Primary"] <= cho(seq(g["Identifier"], npd(g["LEFTARROW"])),
|
||||
g["Primary"] <= cho(seq(opt(g["IGNORE"]), g["Identifier"], npd(g["LEFTARROW"])),
|
||||
seq(g["OPEN"], g["Expression"], g["CLOSE"]),
|
||||
seq(g["Begin"], g["Expression"], g["End"]),
|
||||
seq(g["BeginCap"], g["Expression"], g["EndCap"]),
|
||||
@ -1660,9 +1682,18 @@ private:
|
||||
// Reference
|
||||
[&](const SemanticValues& sv, any& dt) {
|
||||
Data& data = *dt.get<Data*>();
|
||||
const auto& ident = sv[0].val.get<std::string>();
|
||||
|
||||
auto ignore = (sv.size() == 2);
|
||||
auto baseId = ignore ? 1 : 0;
|
||||
|
||||
const auto& ident = sv[baseId].val.get<std::string>();
|
||||
data.references[ident] = sv.s; // for error handling
|
||||
return ref(*data.grammar, ident);
|
||||
|
||||
if (ignore) {
|
||||
return ign(ref(*data.grammar, ident));
|
||||
} else {
|
||||
return ref(*data.grammar, ident);
|
||||
}
|
||||
},
|
||||
// (Expression)
|
||||
[&](const SemanticValues& sv) {
|
||||
|
39
test/test.cc
39
test/test.cc
@ -505,6 +505,45 @@ TEST_CASE("Predicate test", "[general]")
|
||||
REQUIRE(ret == false);
|
||||
}
|
||||
|
||||
TEST_CASE("Ignore semantic value test", "[general]")
|
||||
{
|
||||
peg parser(
|
||||
" START <- ~HELLO WORLD "
|
||||
" HELLO <- 'Hello' _ "
|
||||
" WORLD <- 'World' _ "
|
||||
" _ <- [ \t\r\n]* "
|
||||
);
|
||||
|
||||
parser.enable_ast(false);
|
||||
|
||||
shared_ptr<Ast> ast;
|
||||
auto ret = parser.parse("Hello World", ast);
|
||||
|
||||
REQUIRE(ret == true);
|
||||
REQUIRE(ast->nodes.size() == 1);
|
||||
REQUIRE(ast->nodes[0]->name == "WORLD");
|
||||
}
|
||||
|
||||
TEST_CASE("Ignore semantic value of 'or' predicate test", "[general]")
|
||||
{
|
||||
peg parser(
|
||||
" START <- _ !DUMMY HELLO_WORLD '.' "
|
||||
" HELLO_WORLD <- HELLO 'World' _ "
|
||||
" HELLO <- 'Hello' _ "
|
||||
" DUMMY <- 'dummy' _ "
|
||||
" ~_ <- [ \t\r\n]* "
|
||||
);
|
||||
|
||||
parser.enable_ast(false);
|
||||
|
||||
shared_ptr<Ast> ast;
|
||||
auto ret = parser.parse("Hello World.", ast);
|
||||
|
||||
REQUIRE(ret == true);
|
||||
REQUIRE(ast->nodes.size() == 1);
|
||||
REQUIRE(ast->nodes[0]->name == "HELLO_WORLD");
|
||||
}
|
||||
|
||||
TEST_CASE("Ignore semantic value of 'and' predicate test", "[general]")
|
||||
{
|
||||
peg parser(
|
||||
|
Loading…
Reference in New Issue
Block a user