// // peglib.h // // Copyright (c) 2015 Yuji Hirose. All rights reserved. // MIT License // #ifndef _CPPEXPATLIB_PEGLIB_H_ #define _CPPEXPATLIB_PEGLIB_H_ #include #include #include #include #include #include #include #include namespace peglib { 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; } template Any& operator=(const T& value) { if (content_) { delete content_; } content_ = new holder(value); return *this; } ~Any() { delete content_; } bool is_undefined() const { return content_ == nullptr; } template < typename T, typename std::enable_if::value>::type*& = enabler > T& get() { assert(content_); return dynamic_cast*>(content_)->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_); return dynamic_cast*>(content_)->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 *---------------------------------------------------------------------------*/ /* * Forward declalations */ class Definition; /* * Semantic values */ struct SemanticValues { std::vector names; std::vector values; }; /* * Match */ struct Match { Match(bool _ret, size_t _len) : ret(_ret), len(_len) {} bool ret; size_t len; }; Match success(size_t len) { return Match(true, len); } Match fail() { return Match(false, 0); } /* * Rules */ class Rule { public: virtual ~Rule() {}; virtual Match parse(const char* s, size_t l, SemanticValues& sv) const = 0; }; class Sequence : public Rule { public: Sequence(const Sequence& rhs) : rules_(rhs.rules_) {} #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) { rules_ = std::vector>{ static_cast>(args)... }; } #else template Sequence(const Args& ...args) : rules_{ static_cast>(args)... } {} #endif Sequence(const std::vector>& rules) : rules_(rules) {} Sequence(std::vector>&& rules) : rules_(std::move(rules)) {} Match parse(const char* s, size_t l, SemanticValues& sv) const { size_t i = 0; for (const auto& rule : rules_) { auto m = rule->parse(s + i, l - i, sv); if (!m.ret) { return fail(); } i += m.len; } return success(i); } private: std::vector> rules_; }; class PrioritizedChoice : public Rule { 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) { rules_ = std::vector>{ static_cast>(args)... }; } #else template PrioritizedChoice(const Args& ...args) : rules_{ static_cast>(args)... } {} #endif PrioritizedChoice(const std::vector>& rules) : rules_(rules) {} PrioritizedChoice(std::vector>&& rules) : rules_(std::move(rules)) {} Match parse(const char* s, size_t l, SemanticValues& sv) const { for (const auto& rule : rules_) { auto m = rule->parse(s, l, sv); if (m.ret) { return success(m.len); } } return fail(); } private: std::vector> rules_; }; class ZeroOrMore : public Rule { public: ZeroOrMore(const std::shared_ptr& rule) : rule_(rule) {} Match parse(const char* s, size_t l, SemanticValues& sv) const { auto i = 0; while (l - i > 0) { auto m = rule_->parse(s + i, l - i, sv); if (!m.ret) { break; } i += m.len; } return success(i); } private: std::shared_ptr rule_; }; class OneOrMore : public Rule { public: OneOrMore(const std::shared_ptr& rule) : rule_(rule) {} Match parse(const char* s, size_t l, SemanticValues& sv) const { auto m = rule_->parse(s, l, sv); if (!m.ret) { return fail(); } auto i = m.len; while (l - i > 0) { auto m = rule_->parse(s + i, l - i, sv); if (!m.ret) { break; } i += m.len; } return success(i); } private: std::shared_ptr rule_; }; class Option : public Rule { public: Option(const std::shared_ptr& rule) : rule_(rule) {} Match parse(const char* s, size_t l, SemanticValues& sv) const { auto m = rule_->parse(s, l, sv); return success(m.ret ? m.len : 0); } private: std::shared_ptr rule_; }; class AndPredicate : public Rule { public: AndPredicate(const std::shared_ptr& rule) : rule_(rule) {} Match parse(const char* s, size_t l, SemanticValues& sv) const { auto m = rule_->parse(s, l, sv); if (m.ret) { return success(0); } else { return fail(); } } private: std::shared_ptr rule_; }; class NotPredicate : public Rule { public: NotPredicate(const std::shared_ptr& rule) : rule_(rule) {} Match parse(const char* s, size_t l, SemanticValues& sv) const { auto m = rule_->parse(s, l, sv); if (m.ret) { return fail(); } else { return success(0); } } private: std::shared_ptr rule_; }; class LiteralString : public Rule { public: LiteralString(const char* s) : lit_(s) {} Match parse(const char* s, size_t l, SemanticValues& sv) const { auto i = 0u; for (; i < lit_.size(); i++) { if (i >= l || s[i] != lit_[i]) { return fail(); } } return success(i); } private: std::string lit_; }; class CharacterClass : public Rule { public: CharacterClass(const char* chars) : chars_(chars) {} Match parse(const char* s, size_t l, SemanticValues& sv) const { if (l < 1) { return fail(); } 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 success(1); } i += 3; } else { if (chars_[i] == ch) { return success(1); } i += 1; } } return fail(); } private: std::string chars_; }; class Character : public Rule { public: Character(char ch) : ch_(ch) {} Match parse(const char* s, size_t l, SemanticValues& sv) const { if (l < 1 || s[0] != ch_) { return fail(); } return success(1); } private: char ch_; }; class AnyCharacter : public Rule { public: Match parse(const char* s, size_t l, SemanticValues& sv) const { if (l < 1) { return fail(); } return success(1); } }; class Grouping : public Rule { public: Grouping(const std::shared_ptr& rule) : rule_(rule) {} Grouping(const std::shared_ptr& rule, std::function match) : rule_(rule), match_(match) {} Match parse(const char* s, size_t l, SemanticValues& sv) const { assert(rule_); auto m = rule_->parse(s, l, sv); if (m.ret && match_) { match_(s, m.len); } return m; } private: std::shared_ptr rule_; std::function match_; }; class WeakHolder : public Rule { public: WeakHolder(const std::shared_ptr& rule) : weak_(rule) {} Match parse(const char* s, size_t l, SemanticValues& sv) const { auto rule = weak_.lock(); assert(rule); return rule->parse(s, l, sv); } private: std::weak_ptr weak_; }; /* * Semantic action */ template < typename R, typename F, typename std::enable_if::value>::type*& = enabler, typename... Args> Any call(F fn, Args&&... args) { return Any(fn(std::forward(args)...)); } 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(); } class SemanticAction { public: operator bool() const { return (bool)fn_; } Any operator()(const char* s, size_t l, const std::vector& v, const std::vector& n) const { return fn_(s, l, v, n); } template ::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); } private: template struct TypeAdaptor { TypeAdaptor(std::function& v, const std::vector& n)> fn) : fn_(fn) {} Any operator()(const char* s, size_t l, const std::vector& v, const std::vector& n) { return call(fn_, s, l, v, n); } std::function& v, const std::vector& n)> fn_; }; template struct TypeAdaptor_s_l_v { TypeAdaptor_s_l_v(std::function& v)> fn) : fn_(fn) {} Any operator()(const char* s, size_t l, const std::vector& v, const std::vector& n) { return call(fn_, s, l, v); } std::function& v)> fn_; }; template struct TypeAdaptor_s_l { TypeAdaptor_s_l(std::function fn) : fn_(fn) {} Any operator()(const char* s, size_t l, const std::vector& v, const std::vector& n) { return call(fn_, s, l); } std::function fn_; }; template struct TypeAdaptor_v_n { TypeAdaptor_v_n(std::function& v, const std::vector& n)> fn) : fn_(fn) {} Any operator()(const char* s, size_t l, const std::vector& v, const std::vector& n) { return call(fn_, v, n); } std::function& v, const std::vector& n)> fn_; }; template struct TypeAdaptor_v { TypeAdaptor_v(std::function& v)> fn) : fn_(fn) {} Any operator()(const char* s, size_t l, const std::vector& v, const std::vector& n) { return call(fn_, v); } std::function& v)> fn_; }; template struct TypeAdaptor_empty { TypeAdaptor_empty(std::function fn) : fn_(fn) {} Any operator()(const char* s, size_t l, const std::vector& v, const std::vector& n) { return call(fn_); } std::function fn_; }; typedef std::function& v, const std::vector& n)> Fty; template Fty make_adaptor(F fn, R (F::*mf)(const char*, size_t, const std::vector& v, const std::vector& n) const) { return TypeAdaptor(fn); } template Fty make_adaptor(F fn, R(*mf)(const char*, size_t, const std::vector& v, const std::vector& n)) { return TypeAdaptor(fn); } template Fty make_adaptor(F fn, R (F::*mf)(const char*, size_t, const std::vector& v) const) { return TypeAdaptor_s_l_v(fn); } template Fty make_adaptor(F fn, R(*mf)(const char*, size_t, const std::vector& v)) { return TypeAdaptor_s_l_v(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 (*mf)(const char*, size_t)) { return TypeAdaptor_s_l(fn); } template Fty make_adaptor(F fn, R (F::*mf)(const std::vector& v, const std::vector& n) const) { return TypeAdaptor_v_n(fn); } template Fty make_adaptor(F fn, R (*mf)(const std::vector& v, const std::vector& n)) { return TypeAdaptor_v_n(fn); } template Fty make_adaptor(F fn, R (F::*mf)(const std::vector& v) const) { return TypeAdaptor_v(fn); } template Fty make_adaptor(F fn, R (*mf)(const std::vector& v)) { return TypeAdaptor_v(fn); } template Fty make_adaptor(F fn, R (F::*mf)() const) { return TypeAdaptor_empty(fn); } template Fty make_adaptor(F fn, R (*mf)()) { return TypeAdaptor_empty(fn); } Fty fn_; }; /* * Definition */ class Definition { public: Definition() : rule_(std::make_shared(this)) {} Definition(const Definition& rhs) : name(rhs.name) , rule_(rhs.rule_) { non_terminal().outer_ = this; } Definition(Definition&& rhs) : name(std::move(rhs.name)) , rule_(std::move(rhs.rule_)) { non_terminal().outer_ = this; } Definition(const std::shared_ptr& rule) : rule_(std::make_shared(this)) { set_rule(rule); } operator std::shared_ptr() { return std::make_shared(rule_); } Definition& operator<=(const std::shared_ptr& rule) { set_rule(rule); return *this; } template bool parse(const char* s, size_t l, T& val) const { SemanticValues sv; auto m = rule_->parse(s, l, sv); auto ret = m.ret && m.len == l; if (ret && !sv.values.empty() && !sv.values.front().is_undefined()) { val = sv.values[0].get(); } return ret; } template bool parse(const char* s, T& val) const { return parse(s, strlen(s), val); } bool parse(const char* s, size_t l) const { SemanticValues sv; auto m = rule_->parse(s, l, sv); return m.ret && m.len == l; } bool parse(const char* s) const { return parse(s, strlen(s)); } template void operator,(F fn) { action = fn; } std::string name; SemanticAction action; private: friend class DefinitionReference; class NonTerminal : public Rule { public: NonTerminal(Definition* outer) : outer_(outer) {}; Match parse(const char* s, size_t l, SemanticValues& sv) const { if (!rule_) { throw std::logic_error("Uninitialized definition rule was used..."); } SemanticValues chldsv; auto m = rule_->parse(s, l, chldsv); if (m.ret) { sv.names.push_back(outer_->name); auto val = reduce(s, m.len, chldsv, outer_->action); sv.values.push_back(val); } return m; } private: friend class Definition; template Any reduce(const char* s, size_t l, const SemanticValues& sv, Action action) const { if (action) { return action(s, l, sv.values, sv.names); } else if (sv.values.empty()) { return Any(); } else { return sv.values.front(); } } std::shared_ptr rule_; Definition* outer_; }; Definition& operator=(const Definition& rhs); Definition& operator=(Definition&& rhs); NonTerminal& non_terminal() { return *dynamic_cast(rule_.get()); } void set_rule(const std::shared_ptr& rule) { non_terminal().rule_ = rule; } std::shared_ptr rule_; }; class DefinitionReference : public Rule { public: DefinitionReference( const std::map& grammar, const std::string& name) : grammar_(grammar) , name_(name) {} Match parse(const char* s, size_t l, SemanticValues& sv) const { auto rule = grammar_.at(name_).rule_; return rule->parse(s, l, sv); } private: const std::map& grammar_; std::string name_; }; /* * Factories */ template std::shared_ptr seq(Args&& ...args) { return std::make_shared(static_cast>(args)...); } inline std::shared_ptr seq_v(const std::vector>& rules) { return std::make_shared(rules); } inline std::shared_ptr seq_v(std::vector>&& rules) { return std::make_shared(std::move(rules)); } template std::shared_ptr cho(Args&& ...args) { return std::make_shared(static_cast>(args)...); } inline std::shared_ptr cho_v(const std::vector>& rules) { return std::make_shared(rules); } inline std::shared_ptr cho_v(std::vector>&& rules) { return std::make_shared(std::move(rules)); } inline std::shared_ptr zom(const std::shared_ptr& rule) { return std::make_shared(rule); } inline std::shared_ptr oom(const std::shared_ptr& rule) { return std::make_shared(rule); } inline std::shared_ptr opt(const std::shared_ptr& rule) { return std::make_shared