// // peglib.h // // Copyright (c) 2015 Yuji Hirose. All rights reserved. // MIT License // #ifndef _CPPPEGLIB_PEGLIB_H_ #define _CPPPEGLIB_PEGLIB_H_ #include #include #include #include #include #include #include #include #include #include #include #include #include namespace peglib { extern void* enabler; /*----------------------------------------------------------------------------- * any *---------------------------------------------------------------------------*/ class any { public: any() : content_(nullptr) {} any(const any& rhs) : content_(rhs.clone()) {} any(any&& rhs) : content_(rhs.content_) { rhs.content_ = nullptr; } template any(const T& value) : content_(new holder(value)) {} any& operator=(const any& rhs) { if (this != &rhs) { if (content_) { delete content_; } content_ = rhs.clone(); } return *this; } any& operator=(any&& rhs) { if (this != &rhs) { if (content_) { delete content_; } content_ = rhs.content_; rhs.content_ = nullptr; } return *this; } ~any() { delete content_; } bool is_undefined() const { return content_ == nullptr; } template < typename T, typename std::enable_if::value>::type*& = enabler > T& get() { if (!content_) { throw std::bad_cast(); } auto p = dynamic_cast*>(content_); assert(p); if (!p) { throw std::bad_cast(); } return p->value_; } template < typename T, typename std::enable_if::value>::type*& = enabler > T& get() { return *this; } template < typename T, typename std::enable_if::value>::type*& = enabler > const T& get() const { assert(content_); auto p = dynamic_cast*>(content_); assert(p); if (!p) { throw std::bad_cast(); } return p->value_; } template < typename T, typename std::enable_if::value>::type*& = enabler > const any& get() const { return *this; } private: struct placeholder { virtual ~placeholder() {}; virtual placeholder* clone() const = 0; }; template struct holder : placeholder { holder(const T& value) : value_(value) {} placeholder* clone() const override { return new holder(value_); } T value_; }; placeholder* clone() const { return content_ ? content_->clone() : nullptr; } placeholder* content_; }; /*----------------------------------------------------------------------------- * PEG *---------------------------------------------------------------------------*/ /* * Semantic values */ struct SemanticValue { SemanticValue() : s(nullptr), n(0) {} SemanticValue(const any& _val, const char* _name, const char* _s, size_t _n) : val(_val), name(_name), s(_s), n(_n) {} template T& get() { return val.get(); } template const T& get() const { return val.get(); } std::string str() const { return std::string(s, n); } any val; const char* name; const char* s; size_t n; }; struct SemanticValues : protected std::vector { const char* s; size_t n; size_t choice; SemanticValues() : s(nullptr), n(0), choice(0) {} std::string str(size_t i = 0) const { if (i > 0) { return (*this)[i].str(); } return std::string(s, n); } typedef SemanticValue T; using std::vector::iterator; using std::vector::const_iterator; using std::vector::size; using std::vector::empty; using std::vector::assign; using std::vector::begin; using std::vector::end; using std::vector::rbegin; using std::vector::rend; using std::vector::operator[]; using std::vector::at; using std::vector::resize; using std::vector::front; using std::vector::back; using std::vector::push_back; using std::vector::pop_back; using std::vector::insert; using std::vector::erase; using std::vector::clear; using std::vector::swap; using std::vector::emplace; using std::vector::emplace_back; template auto map(F f) const -> vector::type> { vector::type> r; for (const auto& v: *this) { r.push_back(f(v)); } return r; } template auto map(size_t beg, size_t end, F f) const -> vector::type> { vector::type> r; end = std::min(end, size()); for (size_t i = beg; i < end; i++) { r.push_back(f((*this)[i])); } return r; } template auto map(size_t beg = 0, size_t end = -1) const -> vector { return this->map(beg, end, [](const SemanticValue& v) { return v.get(); }); } }; /* * Semantic action */ template < typename R, typename F, typename std::enable_if::value>::type*& = enabler, typename... Args> any call(F fn, Args&&... args) { fn(std::forward(args)...); return any(); } template < typename R, typename F, typename std::enable_if::type, any>::value>::type*& = enabler, typename... Args> any call(F fn, Args&&... args) { return fn(std::forward(args)...); } template < typename R, typename F, typename std::enable_if::type, SemanticValue>::value>::type*& = enabler, typename... Args> any call(F fn, Args&&... args) { return fn(std::forward(args)...).val; } template < typename R, typename F, typename std::enable_if< !std::is_void::value && !std::is_same::type, any>::value && !std::is_same::type, SemanticValue>::value>::type*& = enabler, typename... Args> any call(F fn, Args&&... args) { return any(fn(std::forward(args)...)); } /* * Predicate */ typedef std::function Predicate; class Action { public: Action() = default; Action(const Action& rhs) : fn_(rhs.fn_) {} template ::value && !std::is_same::value>::type*& = enabler> Action(F fn) : fn_(make_adaptor(fn, &F::operator())) {} template ::value>::type*& = enabler> Action(F fn) : fn_(make_adaptor(fn, fn)) {} template ::value>::type*& = enabler> Action(F fn) {} template ::value && !std::is_same::value>::type*& = enabler> void operator=(F fn) { fn_ = make_adaptor(fn, &F::operator()); } template ::value>::type*& = enabler> void operator=(F fn) { fn_ = make_adaptor(fn, fn); } template ::value>::type*& = enabler> void operator=(F fn) {} operator bool() const { return (bool)fn_; } any operator()(const SemanticValues& sv, any& dt) const { return fn_(sv, dt); } private: template struct TypeAdaptor { TypeAdaptor(std::function fn) : fn_(fn) {} any operator()(const SemanticValues& sv, any& dt) { return call(fn_, sv); } std::function fn_; }; template struct TypeAdaptor_c { TypeAdaptor_c(std::function fn) : fn_(fn) {} any operator()(const SemanticValues& sv, any& dt) { return call(fn_, sv, dt); } std::function fn_; }; template struct TypeAdaptor_s_l { TypeAdaptor_s_l(std::function fn) : fn_(fn) {} any operator()(const SemanticValues& sv, any& dt) { return call(fn_, sv.s, sv.n); } std::function fn_; }; template struct TypeAdaptor_empty { TypeAdaptor_empty(std::function fn) : fn_(fn) {} any operator()(const SemanticValues& sv, any& dt) { return call(fn_); } std::function fn_; }; typedef std::function Fty; template Fty make_adaptor(F fn, R (F::*mf)(const SemanticValues& sv) const) { return TypeAdaptor(fn); } template Fty make_adaptor(F fn, R (F::*mf)(const SemanticValues& sv)) { return TypeAdaptor(fn); } template Fty make_adaptor(F fn, R(*mf)(const SemanticValues& sv)) { return TypeAdaptor(fn); } template Fty make_adaptor(F fn, R (F::*mf)(const SemanticValues& sv, any& dt) const) { return TypeAdaptor_c(fn); } template Fty make_adaptor(F fn, R (F::*mf)(const SemanticValues& sv, any& dt)) { return TypeAdaptor_c(fn); } template Fty make_adaptor(F fn, R(*mf)(const SemanticValues& sv, any& dt)) { return TypeAdaptor_c(fn); } template Fty make_adaptor(F fn, R (F::*mf)(const char*, size_t) const) { return TypeAdaptor_s_l(fn); } template Fty make_adaptor(F fn, R (F::*mf)(const char*, size_t)) { return TypeAdaptor_s_l(fn); } template Fty make_adaptor(F fn, R (*mf)(const char*, size_t)) { return TypeAdaptor_s_l(fn); } template Fty make_adaptor(F fn, R (F::*mf)() const) { return TypeAdaptor_empty(fn); } template Fty make_adaptor(F fn, R (F::*mf)()) { return TypeAdaptor_empty(fn); } template Fty make_adaptor(F fn, R (*mf)()) { return TypeAdaptor_empty(fn); } Fty fn_; }; /* * Match action */ typedef std::function MatchAction; /* * Result */ inline bool success(size_t len) { return len != -1; } inline bool fail(size_t len) { return len == -1; } /* * Context */ struct Context { const char* s; size_t l; const char* error_pos; const char* message_pos; std::string message; // TODO: should be `int`. size_t def_count; std::vector cache_register; std::vector cache_success; std::map, std::tuple> cache_result; std::vector> stack; size_t stack_size; Context(const char* _s, size_t _l, size_t _def_count, bool enablePackratParsing) : s(_s) , l(_l) , error_pos(nullptr) , message_pos(nullptr) , def_count(_def_count) , cache_register(enablePackratParsing ? def_count * (l + 1) : 0) , cache_success(enablePackratParsing ? def_count * (l + 1) : 0) , stack_size(0) { } template void packrat(const char* s, size_t def_id, size_t& len, any& val, T fn) { if (cache_register.empty()) { fn(val); return; } auto col = s - this->s; auto has_cache = cache_register[def_count * col + def_id]; if (has_cache) { if (cache_success[def_count * col + def_id]) { const auto& key = std::make_pair(s - this->s, def_id); std::tie(len, val) = cache_result[key]; return; } else { len = -1; return; } } else { fn(val); cache_register[def_count * col + def_id] = true; cache_success[def_count * col + def_id] = success(len); if (success(len)) { const auto& key = std::make_pair(s - this->s, def_id); cache_result[key] = std::make_pair(len, val); } return; } } inline SemanticValues& push() { assert(stack_size <= stack.size()); if (stack_size == stack.size()) { stack.push_back(std::make_shared()); } auto& sv = *stack[stack_size++]; if (!sv.empty()) { sv.clear(); } sv.s = nullptr; sv.n = 0; return sv; } void pop() { stack_size--; } void set_error_pos(const char* s) { if (error_pos < s) error_pos = s; } }; /* * Parser operators */ class Ope { public: struct Visitor; virtual ~Ope() {}; virtual size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const = 0; virtual void accept(Visitor& v) = 0; }; class Sequence : public Ope { public: Sequence(const Sequence& rhs) : opes_(rhs.opes_) {} #if defined(_MSC_VER) && _MSC_VER < 1900 // Less than Visual Studio 2015 // NOTE: Compiler Error C2797 on Visual Studio 2013 // "The C++ compiler in Visual Studio does not implement list // initialization inside either a member initializer list or a non-static // data member initializer. Before Visual Studio 2013 Update 3, this was // silently converted to a function call, which could lead to bad code // generation. Visual Studio 2013 Update 3 reports this as an error." template Sequence(const Args& ...args) { opes_ = std::vector>{ static_cast>(args)... }; } #else template Sequence(const Args& ...args) : opes_{ static_cast>(args)... } {} #endif Sequence(const std::vector>& opes) : opes_(opes) {} Sequence(std::vector>&& opes) : opes_(std::move(opes)) {} size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override { size_t i = 0; for (const auto& ope : opes_) { const auto& rule = *ope; auto len = rule.parse(s + i, n - i, sv, c, dt); if (fail(len)) { return -1; } i += len; } return i; } void accept(Visitor& v) override; //private: std::vector> opes_; }; class PrioritizedChoice : public Ope { public: #if defined(_MSC_VER) && _MSC_VER < 1900 // Less than Visual Studio 2015 // NOTE: Compiler Error C2797 on Visual Studio 2013 // "The C++ compiler in Visual Studio does not implement list // initialization inside either a member initializer list or a non-static // data member initializer. Before Visual Studio 2013 Update 3, this was // silently converted to a function call, which could lead to bad code // generation. Visual Studio 2013 Update 3 reports this as an error." template PrioritizedChoice(const Args& ...args) { opes_ = std::vector>{ static_cast>(args)... }; } #else template PrioritizedChoice(const Args& ...args) : opes_{ static_cast>(args)... } {} #endif PrioritizedChoice(const std::vector>& opes) : opes_(opes) {} PrioritizedChoice(std::vector>&& opes) : opes_(std::move(opes)) {} size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override { size_t id = 0; for (const auto& ope : opes_) { const auto& rule = *ope; auto& chldsv = c.push(); auto len = rule.parse(s, n, chldsv, c, dt); if (len != -1) { if (!chldsv.empty()) { sv.insert(sv.end(), chldsv.begin(), chldsv.end()); } sv.s = chldsv.s; sv.n = chldsv.n; sv.choice = id; c.pop(); return len; } id++; c.pop(); } return -1; } void accept(Visitor& v) override; size_t size() const { return opes_.size(); } //private: std::vector> opes_; }; class ZeroOrMore : public Ope { public: ZeroOrMore(const std::shared_ptr& ope) : ope_(ope) {} size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override { auto i = 0; while (n - i > 0) { const auto& rule = *ope_; auto len = rule.parse(s + i, n - i, sv, c, dt); if (fail(len)) { break; } i += len; } return i; } void accept(Visitor& v) override; //private: std::shared_ptr ope_; }; class OneOrMore : public Ope { public: OneOrMore(const std::shared_ptr& 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 len = rule.parse(s, n, sv, c, dt); if (fail(len)) { return -1; } auto i = len; while (n - i > 0) { const auto& rule = *ope_; auto len = rule.parse(s + i, n - i, sv, c, dt); if (fail(len)) { break; } i += len; } return i; } void accept(Visitor& v) override; //private: std::shared_ptr ope_; }; class Option : public Ope { public: Option(const std::shared_ptr& 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 len = rule.parse(s, n, sv, c, dt); return success(len) ? len : 0; } void accept(Visitor& v) override; //private: std::shared_ptr ope_; }; class AndPredicate : public Ope { public: AndPredicate(const std::shared_ptr& 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 len = rule.parse(s, n, sv, c, dt); if (success(len)) { return 0; } else { return -1; } } void accept(Visitor& v) override; //private: std::shared_ptr ope_; }; class NotPredicate : public Ope { public: NotPredicate(const std::shared_ptr& 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 error_pos = c.error_pos; auto len = rule.parse(s, n, sv, c, dt); if (success(len)) { c.set_error_pos(s); return -1; } else { c.error_pos = error_pos; return 0; } } void accept(Visitor& v) override; //private: std::shared_ptr ope_; }; class LiteralString : public Ope { public: LiteralString(const std::string& s) : lit_(s) {} size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override { auto i = 0u; for (; i < lit_.size(); i++) { if (i >= n || s[i] != lit_[i]) { c.set_error_pos(s); return -1; } } return i; } void accept(Visitor& v) override; //private: std::string lit_; }; class CharacterClass : public Ope { public: CharacterClass(const std::string& chars) : chars_(chars) {} size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override { // TODO: UTF8 support if (n < 1) { c.set_error_pos(s); return -1; } auto ch = s[0]; auto i = 0u; while (i < chars_.size()) { if (i + 2 < chars_.size() && chars_[i + 1] == '-') { if (chars_[i] <= ch && ch <= chars_[i + 2]) { return 1; } i += 3; } else { if (chars_[i] == ch) { return 1; } i += 1; } } c.set_error_pos(s); return -1; } void accept(Visitor& v) override; //private: std::string chars_; }; class Character : public Ope { public: Character(char ch) : ch_(ch) {} size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override { // TODO: UTF8 support if (n < 1 || s[0] != ch_) { c.set_error_pos(s); return -1; } return 1; } void accept(Visitor& v) override; //private: char ch_; }; class AnyCharacter : public Ope { public: size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override { // TODO: UTF8 support if (n < 1) { c.set_error_pos(s); return -1; } return 1; } void accept(Visitor& v) override; }; class Capture : public Ope { public: Capture(const std::shared_ptr& ope, MatchAction ma, size_t n, const std::string& s) : 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_) { match_action_(s, len, id, name); } return len; } void accept(Visitor& v) override; //private: std::shared_ptr ope_; MatchAction match_action_; size_t id; std::string name; }; class Anchor : public Ope { public: Anchor(const std::shared_ptr& 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)) { sv.s = s; sv.n = len; } return len; } void accept(Visitor& v) override; //private: std::shared_ptr ope_; }; typedef std::function Parser; class User : public Ope { public: User(Parser fn) : fn_(fn) {} size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override { assert(fn_); return fn_(s, n, sv, dt); } void accept(Visitor& v) override; //private: std::function fn_; }; class WeakHolder : public Ope { public: WeakHolder(const std::shared_ptr& ope) : weak_(ope) {} size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override { auto ope = weak_.lock(); assert(ope); const auto& rule = *ope; return rule.parse(s, n, sv, c, dt); } void accept(Visitor& v) override; //private: std::weak_ptr weak_; }; class Definition; class Holder : public Ope { public: Holder(Definition* outer) : outer_(outer) {} size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override; void accept(Visitor& v) override; //private: friend class Definition; any reduce(const SemanticValues& sv, any& dt, const Action& action) const; std::shared_ptr ope_; Definition* outer_; }; class DefinitionReference : public Ope { public: DefinitionReference( const std::unordered_map& grammar, const std::string& name) : grammar_(grammar) , name_(name) {} size_t parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const override; void accept(Visitor& v) override; std::shared_ptr get_rule() const; private: const std::unordered_map& grammar_; const std::string name_; mutable std::once_flag init_; mutable std::shared_ptr rule_; }; /* * Visitor */ struct Ope::Visitor { virtual void visit(Sequence& ope) = 0; virtual void visit(PrioritizedChoice& ope) = 0; virtual void visit(ZeroOrMore& ope) = 0; virtual void visit(OneOrMore& ope) = 0; virtual void visit(Option& ope) = 0; virtual void visit(AndPredicate& ope) = 0; virtual void visit(NotPredicate& ope) = 0; virtual void visit(LiteralString& ope) = 0; virtual void visit(CharacterClass& ope) = 0; virtual void visit(Character& ope) = 0; virtual void visit(AnyCharacter& ope) = 0; virtual void visit(Capture& ope) = 0; virtual void visit(Anchor& ope) = 0; virtual void visit(User& ope) = 0; virtual void visit(WeakHolder& ope) = 0; virtual void visit(Holder& ope) = 0; virtual void visit(DefinitionReference& ope) = 0; }; struct AssignIDToDefinition : public Ope::Visitor { void visit(Sequence& ope) override { for (auto op: ope.opes_) { op->accept(*this); } } void visit(PrioritizedChoice& ope) override { for (auto op: ope.opes_) { op->accept(*this); } } 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(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 { ope.ope_->accept(*this); } void visit(User& ope) override {} void visit(WeakHolder& ope) override { ope.weak_.lock()->accept(*this); } void visit(Holder& ope) override; void visit(DefinitionReference& ope) override { ope.get_rule()->accept(*this); } std::unordered_map ids; }; struct IsToken : public Ope::Visitor { IsToken() : has_anchor(false), has_rule(false) {} void visit(Sequence& ope) override { for (auto op: ope.opes_) { op->accept(*this); } } void visit(PrioritizedChoice& ope) override { for (auto op: ope.opes_) { op->accept(*this); } } 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(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(User& ope) override {} void visit(WeakHolder& ope) override { ope.weak_.lock()->accept(*this); } void visit(Holder& ope) override {} void visit(DefinitionReference& ope) override { has_rule = true; } bool is_token() const { return has_anchor || !has_rule; } bool has_anchor; bool has_rule; }; /* * Definition */ class Definition { public: struct Result { bool ret; size_t len; const char* error_pos; const char* message_pos; const std::string message; }; Definition() : actions(1) , ignoreSemanticValue(false) , enablePackratParsing(false) , is_token(false) , holder_(std::make_shared(this)) {} Definition(const Definition& rhs) : name(rhs.name) , actions(1) , ignoreSemanticValue(false) , enablePackratParsing(false) , is_token(false) , holder_(rhs.holder_) { holder_->outer_ = this; } Definition(Definition&& rhs) : name(std::move(rhs.name)) , actions(1) , ignoreSemanticValue(rhs.ignoreSemanticValue) , enablePackratParsing(rhs.enablePackratParsing) , is_token(rhs.is_token) , holder_(std::move(rhs.holder_)) { holder_->outer_ = this; } Definition(const std::shared_ptr& ope) : actions(1) , ignoreSemanticValue(false) , enablePackratParsing(false) , is_token(false) , holder_(std::make_shared(this)) { *this <= ope; } operator std::shared_ptr() { return std::make_shared(holder_); } Definition& operator<=(const std::shared_ptr& ope) { IsToken isToken; ope->accept(isToken); is_token = isToken.is_token(); holder_->ope_ = ope; return *this; } Result parse(const char* s, size_t n) const { SemanticValues sv; any dt; return parse_core(s, n, sv, dt); } Result parse(const char* s) const { auto n = strlen(s); return parse(s, n); } Result parse(const char* s, size_t n, any& dt) const { SemanticValues sv; return parse_core(s, n, sv, dt); } Result parse(const char* s, any& dt) const { auto n = strlen(s); return parse(s, n, dt); } template Result parse_and_get_value(const char* s, size_t n, T& val) const { SemanticValues sv; any dt; auto r = parse_core(s, n, sv, dt); if (r.ret && !sv.empty() && !sv.front().val.is_undefined()) { val = sv[0].val.get(); } return r; } template Result parse_and_get_value(const char* s, T& val) const { auto n = strlen(s); return parse_and_get_value(s, n, val); } template Result parse_and_get_value(const char* s, size_t n, any& dt, T& val) const { SemanticValues sv; auto r = parse_core(s, n, sv, dt); if (r.ret && !sv.empty() && !sv.front().val.is_undefined()) { val = sv[0].val.get(); } return r; } template Result parse_and_get_value(const char* s, any& dt, T& val) const { auto n = strlen(s); return parse_and_get_value(s, n, dt, val); } Definition& operator=(Action action) { assert(!actions.empty()); actions[0] = action; return *this; } Definition& operator=(std::initializer_list ini) { actions = ini; return *this; } template Definition& operator,(T fn) { operator=(fn); return *this; } Definition& operator~() { ignoreSemanticValue = true; return *this; } void accept(Ope::Visitor& v) { holder_->accept(v); } std::string name; size_t id; Predicate predicate; std::vector actions; std::function error_message; bool ignoreSemanticValue; bool enablePackratParsing; bool is_token; private: friend class DefinitionReference; Definition& operator=(const Definition& rhs); Definition& operator=(Definition&& rhs); Result parse_core(const char* s, size_t n, SemanticValues& sv, any& dt) const { AssignIDToDefinition assignId; holder_->accept(assignId); Context cxt(s, n, assignId.ids.size(), enablePackratParsing); auto len = holder_->parse(s, n, sv, cxt, dt); return Result{ success(len), len, cxt.error_pos, cxt.message_pos, cxt.message }; } std::shared_ptr holder_; }; /* * Implementations */ inline size_t Holder::parse(const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const { if (!ope_) { throw std::logic_error("Uninitialized definition ope was used..."); } size_t len; any val; const char* anchors = s; size_t anchorn = n; c.packrat(s, outer_->id, len, val, [&](any& val) { auto& chldsv = c.push(); const auto& rule = *ope_; len = rule.parse(s, n, chldsv, c, dt); anchorn = len; // Invoke action if (success(len) && !outer_->ignoreSemanticValue) { assert(!outer_->actions.empty()); auto i = chldsv.choice + 1; // Index 0 is for the default action const auto& action = (i < outer_->actions.size() && outer_->actions[i]) ? outer_->actions[i] : outer_->actions[0]; if (chldsv.s) { anchors = chldsv.s; anchorn = chldsv.n; } else { chldsv.s = s; chldsv.n = len; } val = reduce(chldsv, dt, action); } // Predicate check if (success(len) && outer_->predicate && !outer_->predicate(anchors, anchorn, val, dt)) { len = -1; } c.pop(); }); if (success(len) && !outer_->ignoreSemanticValue) { sv.emplace_back(val, outer_->name.c_str(), anchors, anchorn); } if (fail(len) && outer_->error_message && !c.message_pos) { c.message_pos = s; c.message = outer_->error_message(); } return len; } inline any Holder::reduce(const SemanticValues& sv, any& dt, const Action& action) const { if (action) { return action(sv, dt); } else if (sv.empty()) { return any(); } else { return sv.front().val; } } inline size_t DefinitionReference::parse( const char* s, size_t n, SemanticValues& sv, Context& c, any& dt) const { const auto& rule = *get_rule(); return rule.parse(s, n, sv, c, dt); } inline std::shared_ptr DefinitionReference::get_rule() const { if (!rule_) { std::call_once(init_, [this]() { rule_ = grammar_.at(name_).holder_; }); } assert(rule_); return rule_; }; inline void Sequence::accept(Visitor& v) { v.visit(*this); } inline void PrioritizedChoice::accept(Visitor& v) { v.visit(*this); } inline void ZeroOrMore::accept(Visitor& v) { v.visit(*this); } inline void OneOrMore::accept(Visitor& v) { v.visit(*this); } inline void Option::accept(Visitor& v) { v.visit(*this); } inline void AndPredicate::accept(Visitor& v) { v.visit(*this); } inline void NotPredicate::accept(Visitor& v) { v.visit(*this); } inline void LiteralString::accept(Visitor& v) { v.visit(*this); } inline void CharacterClass::accept(Visitor& v) { v.visit(*this); } 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 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); } inline void DefinitionReference::accept(Visitor& v) { v.visit(*this); } inline void AssignIDToDefinition::visit(Holder& ope) { auto p = (void*)ope.outer_; if (ids.find(p) != ids.end()) { return; } auto id = ids.size(); ids[p] = id; ope.outer_->id = id; ope.ope_->accept(*this); } /* * Factories */ template std::shared_ptr seq(Args&& ...args) { return std::make_shared(static_cast>(args)...); } template std::shared_ptr cho(Args&& ...args) { return std::make_shared(static_cast>(args)...); } inline std::shared_ptr zom(const std::shared_ptr& ope) { return std::make_shared(ope); } inline std::shared_ptr oom(const std::shared_ptr& ope) { return std::make_shared(ope); } inline std::shared_ptr opt(const std::shared_ptr& ope) { return std::make_shared