// // 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; } ~Any() { delete content_; } template T& get() { assert(content_); return dynamic_cast*>(content_)->value_; } template const T& get() const { assert(content_); return dynamic_cast*>(content_)->value_; } 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_; }; /*----------------------------------------------------------------------------- * Variant *---------------------------------------------------------------------------*/ #if defined(_MSC_VER) && _MSC_VER < 1900 // Less than Visual Studio 2015 #define static_max(a, b) (a > b ? a : b) #define alignof _alignof #else template constexpr T static_max(T a, T b) { return a > b ? a : b; } #endif /* * For debug */ static int VARINT_COUNT = 0; template void log_copy_construct() { VARINT_COUNT++; } template void log_move_construct() { VARINT_COUNT++; } template void log_destruct() { VARINT_COUNT--; } void log_variant_count() { std::cout << "VARIANT COUNT (" << VARINT_COUNT << ")" << std::endl; }; /* * Type list */ template struct typelist; template struct typelist { static const size_t max_elem_size = static_max(sizeof(T), typelist::max_elem_size); static const size_t max_elem_align = static_max(alignof(T), typelist::max_elem_align); }; template <> struct typelist<> { static const size_t max_elem_size = 0; static const size_t max_elem_align = 0; }; template struct typelist_index; template struct typelist_index { static const size_t value = 1 + typelist_index::value; }; template struct typelist_index { static const size_t value = 0; }; template struct typelist_index { static const size_t value = 0; }; /* * Variant helper */ template struct variant_helper; template struct variant_helper { template static void copy_construct(size_t type_index, void* data, const VT& vt) { if (N == type_index) { log_copy_construct(); new (data) T(vt.template get()); return; } variant_helper::copy_construct(type_index, data, vt); } template static void move_construct(size_t type_index, void* data, VT&& vt) { if (N == type_index) { log_move_construct(); new (data) T(std::move(vt.template get())); return; } variant_helper::move_construct(type_index, data, vt); } static void destruct(size_t type_index, void* data) { if (N == type_index) { log_destruct(); reinterpret_cast(data)->~T(); return; } variant_helper::destruct(type_index, data); } }; template struct variant_helper { template static void copy_construct(size_t type_index, void* data, const VT& vt) {} template static void move_construct(size_t type_index, void* data, VT&& vt) {} static void destruct(size_t type_index, void* data) {} }; /* * Variant */ template struct Variant { typedef typelist tlist; typedef typename std::aligned_storage::type data_type; data_type data; size_t type_index; template explicit Variant(const T& val) : type_index(typelist_index::value) { static_assert(typelist_index::value < sizeof...(Ts), "Invalid variant type."); log_copy_construct(); new (&data) T(val); } template explicit Variant(T&& val) : type_index(typelist_index::value) { static_assert(typelist_index::value < sizeof...(Ts), "Invalid variant type."); log_move_construct(); new (&data) T(std::move(val)); } Variant() : type_index(sizeof...(Ts)) {} Variant(const Variant& rhs) : type_index(rhs.type_index) { variant_helper<0, Ts...>::copy_construct(type_index, &data, rhs); } Variant(Variant&& rhs) : type_index(rhs.type_index) { variant_helper<0, Ts...>::move_construct(type_index, &data, rhs); } Variant& operator=(const Variant& rhs) { if (this != &rhs) { variant_helper<0, Ts...>::destruct(type_index, &data); type_index = rhs.type_index; variant_helper<0, Ts...>::copy_construct(type_index, &data, rhs); } return *this; } Variant& operator=(Variant&& rhs) { if (this != &rhs) { variant_helper<0, Ts...>::destruct(type_index, &data); type_index = rhs.type_index; variant_helper<0, Ts...>::move_construct(type_index, &data, rhs); } return *this; } ~Variant() { variant_helper<0, Ts...>::destruct(type_index, &data); } template T& get() { if (type_index != typelist_index::value) { throw std::invalid_argument("Invalid template argument."); } return *reinterpret_cast(&data); } template const T& get() const { if (type_index != typelist_index::value) { throw std::invalid_argument("Invalid template argument."); } return *reinterpret_cast(&data); } }; #if _MSC_VER < 1900 // Less than Visual Studio 2015 #undef static_max #undef alignof #endif /*----------------------------------------------------------------------------- * PEG *---------------------------------------------------------------------------*/ /* * Forward declalations */ class Rule; class Definition; template struct SemanticActions; template struct SemanticStack; /* * 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 Sequence { 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)) {} template Match parse(const char* s, size_t l, const SemanticActions* sa, SemanticStack* ss) const; private: std::vector> rules_; }; class PrioritizedChoice { 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)) {} template Match parse(const char* s, size_t l, const SemanticActions* sa, SemanticStack* ss) const; private: std::vector> rules_; }; class ZeroOrMore { public: ZeroOrMore(const std::shared_ptr& rule) : rule_(rule) {} template Match parse(const char* s, size_t l, const SemanticActions* sa, SemanticStack* ss) const; private: std::shared_ptr rule_; }; class OneOrMore { public: OneOrMore(const std::shared_ptr& rule) : rule_(rule) {} template Match parse(const char* s, size_t l, const SemanticActions* sa, SemanticStack* ss) const; private: std::shared_ptr rule_; }; class Option { public: Option(const std::shared_ptr& rule) : rule_(rule) {} template Match parse(const char* s, size_t l, const SemanticActions* sa, SemanticStack* ss) const; private: std::shared_ptr rule_; }; class AndPredicate { public: AndPredicate(const std::shared_ptr& rule) : rule_(rule) {} template Match parse(const char* s, size_t l, const SemanticActions* sa, SemanticStack* ss) const; private: std::shared_ptr rule_; }; class NotPredicate { public: NotPredicate(const std::shared_ptr& rule) : rule_(rule) {} template Match parse(const char* s, size_t l, const SemanticActions* sa, SemanticStack* ss) const; private: std::shared_ptr rule_; }; class LiteralString { public: LiteralString(const char* s) : lit_(s) {} template Match parse(const char* s, size_t l, const SemanticActions* sa, SemanticStack* ss) 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: CharacterClass(const char* chars) : chars_(chars) {} template Match parse(const char* s, size_t l, const SemanticActions* sa, SemanticStack* ss) 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: Character(char ch) : ch_(ch) {} template Match parse(const char* s, size_t l, const SemanticActions* sa, SemanticStack* ss) const { if (l < 1 || s[0] != ch_) { return fail(); } return success(1); } private: char ch_; }; class AnyCharacter { public: template Match parse(const char* s, size_t l, const SemanticActions* sa, SemanticStack* ss) const { if (l < 1) { return fail(); } return success(1); } }; class Grouping { public: Grouping(const std::shared_ptr& rule) : rule_(rule) {} template Match parse(const char* s, size_t l, const SemanticActions* sa, SemanticStack* ss) const; private: std::shared_ptr rule_; }; class NonTerminal { public: NonTerminal(Definition* outer) : outer_(outer) {}; template Match parse(const char* s, size_t l, const SemanticActions* sa, SemanticStack* ss) const; private: friend class Definition; template void reduce(SemanticStack& ss, const char* s, size_t l, Action action) const; template T reduce(const char* s, size_t l, const std::vector& v, const std::vector& n, Action action) const; std::shared_ptr rule_; Definition* outer_; }; class DefinitionReference { public: DefinitionReference( const std::map& grammar, const std::string& name) : grammar_(grammar) , name_(name) {} template Match parse(const char* s, size_t l, const SemanticActions* sa, SemanticStack* ss) const; private: const std::map& grammar_; std::string name_; }; class WeakHolder { public: WeakHolder(const std::shared_ptr& rule) : weak_(rule) {} template Match parse(const char* s, size_t l, const SemanticActions* sa, SemanticStack* ss) const; private: std::weak_ptr weak_; }; /* * Rule */ template class TRule { public: template TRule(const T& val) : vt(val) {} template TRule(T&& val) : vt(std::move(val)) {} template Match parse(const char* s, size_t l, const SemanticActions* sa, SemanticStack* ss) const { switch (vt.type_index) { case 0: return vt.template get().template parse(s, l, sa, ss); case 1: return vt.template get().template parse(s, l, sa, ss); case 2: return vt.template get().template parse(s, l, sa, ss); case 3: return vt.template get().template parse(s, l, sa, ss); case 4: return vt.template get