5 #include <boost/range/algorithm/mismatch.hpp> 6 #include <boost/algorithm/string/predicate.hpp> 7 #include <boost/optional.hpp> 22 template <
typename GenSet>
23 class wordset:
public detail::genset_labelset<GenSet>
32 using word_t =
typename genset_t::word_t;
43 :
wordset{std::make_shared<const genset_t>(gs)}
46 wordset(std::initializer_list<letter_t> letters)
63 auto gs = genset_t::make(is);
73 return this->
genset()->open(o);
82 template <
typename... Args>
85 return value_t{std::forward<Args>(args)...};
125 return genset_t::less(l, r);
139 return genset_t::less(l, r);
145 return genset_t::template special<value_t>();
163 static constexpr
bool 169 static constexpr
bool 175 static constexpr
bool 184 return genset_t::empty_word();
190 return genset_t::is_empty_word(l);
211 template <
typename GenSet_>
222 *
this,
": conv: invalid label: ",
str_escape(v));
227 template <
typename LabelSet_>
240 conv(std::istream& i,
bool =
true)
const 242 return this->
genset()->get_word(i);
254 template <
typename Fun>
255 void convs(std::istream& i, Fun fun)
const 269 this->
genset()->print(l, o, fmt);
279 this->
genset()->print_set(o, fmt);
284 this->
genset()->print_set(o, fmt);
289 this->genset()->print_set(o, fmt); 300 static value_t lgcd(const value_t& w1, const value_t& w2) 302 return {w1.begin(), boost::mismatch(w1, w2).first}; 307 value_t ldivide(const value_t& w1, const value_t& w2) const 309 auto res = maybe_ldivide(w1, w2); 311 *this, ": ldivide: invalid arguments: ", 312 to_string(*this, w1), 313 ", ", to_string(*this, w2)); 317 boost::optional<value_t> 318 maybe_ldivide(const value_t& w1, const value_t& w2) const 320 using boost::algorithm::starts_with; 321 if (starts_with(w2, w1)) 322 return value_t{begin(w2) + size(w1), end(w2)}; 328 value_t& ldivide_here(const value_t& w1, value_t& w2) const 330 w2 = ldivide(w1, w2); 336 value_t rdivide(const value_t& w1, const value_t& w2) const 338 auto res = maybe_rdivide(w1, w2); 340 *this, ": rdivide: invalid arguments: ", 341 to_string(*this, w1), 342 ", ", to_string(*this, w2)); 346 boost::optional<value_t> 347 maybe_rdivide(const value_t& w1, const value_t& w2) const 349 using boost::algorithm::ends_with; 350 if (ends_with(w1, w2)) 351 return value_t{begin(w1), end(w1) - size(w2)}; 357 value_t& rdivide_here(value_t& w1, const value_t& w2) const 359 w1 = rdivide(w1, w2); 363 const value_t& conjunction(const value_t& l, const value_t& r) const 369 ": conjunction: invalid operation (lhs and rhs are not equal): ", 370 to_string(*this, l), ", ", to_string(*this, r)); 377 template <typename GenSet> 378 struct letterized_traits<wordset<GenSet>> 380 static constexpr bool is_letterized = false; 382 using labelset_t = nullableset<letterset<GenSet>>; 384 static labelset_t labelset(const wordset<GenSet>& ls) 386 return {ls.genset()}; 391 template <typename GenSet> 392 struct nullableset_traits<wordset<GenSet>> 394 using type = wordset<GenSet>; 395 static type value(const wordset<GenSet>& ls) 401 template <typename GenSet> 402 struct law_traits<wordset<GenSet>> 404 using type = wordset<GenSet>; 405 static type value(const wordset<GenSet>& ls) 416 #define DEFINE(Lhs, Rhs) \ 417 template <typename GenSet> \ 418 struct join_impl<Lhs, Rhs> \ 421 static type join(const Lhs& lhs, const Rhs& rhs) \ 423 return {set_union(*lhs.genset(), *rhs.genset())}; \ 428 DEFINE(letterset<GenSet>, wordset<GenSet>); 429 DEFINE(nullableset<letterset<GenSet>>, wordset<GenSet>); 430 DEFINE(wordset<GenSet>, wordset<GenSet>); 435 // FIXME: Factor in genset_labelset? 436 template <typename GenSet> 438 meet(const wordset<GenSet>& lhs, const wordset<GenSet>& rhs) 440 return {set_intersection(*lhs.genset(), *rhs.genset())}; 449 template <typename GenSet, 450 typename RandomGenerator = std::default_random_engine> 451 typename wordset<GenSet>::value_t 452 random_label(const wordset<GenSet>& ls, 453 RandomGenerator& gen = RandomGenerator()) 455 require(!ls.generators().empty(), 456 "random_label: the alphabet needs at least 1 letter"); 457 auto dis = std::uniform_int_distribution<>(0, 5); 458 auto res_label = ls.one(); 459 auto pick = make_random_selector(gen); 460 for (auto _: detail::irange(dis(gen))) 461 res_label = ls.mul(res_label, ls.value(pick(ls.generators()))); value_t conv(const letterset< GenSet_ > &ls, typename letterset< GenSet_ >::value_t v) const
weightset_mixin< detail::r_impl > r
Implementation of labels are letters.
static constexpr bool is_expressionset()
static bool equal(const value_t &l, const value_t &r)
Whether l == r.
value_t conv(std::istream &i, bool=true) const
Read a word from this stream.
static bool is_one(const value_t &l) ATTRIBUTE_PURE
std::shared_ptr< const genset_t > genset_ptr
This class has no modeling purpose, it only serves to factor code common to letterset and wordset...
wordset(const genset_ptr &gs)
bool open(bool o) const
Whether unknown letters should be added, or rejected.
bool is_valid(const value_t &v) const
wordset(const genset_t &gs={})
static word_t letters_of_padded(const value_t &v, letter_t)
Prepare to iterate over the letters of v.
void convs(std::istream &i, Fun fun) const
Process a label class.
Print as a parsable type string.
static bool less(const letter_t &l, const letter_t &r)
Whether l < r.
static bool less(const value_t &l, const value_t &r)
Whether l < r.
static constexpr bool has_one()
auto hash_value(const T &v) -> decltype(std::hash< T >
Following the naming convention of Boost.
#define VCSN_REQUIRE(Cond,...)
A macro similar to require.
static size_t size(const value_t &v)
ATTRIBUTE_PURE auto has(Args &&... args) const -> decltype(this->genset() -> has(std::forward< Args >(args)...))
value_t conv(self_t, const value_t &v) const
static bool is_special(const value_t &v)
char eat(std::istream &is, char c)
Check lookahead character and advance.
Implementation of labels are words.
std::ostream & print_set(std::ostream &o, format fmt={}) const
static size_t hash(const value_t &v)
typename genset_t::letter_t letter_t
value_t conv(const nullableset< LabelSet_ > &ls, const typename nullableset< LabelSet_ >::value_t &v) const
value_t value(Args &&... args) const
Value constructor.
static wordset make(std::istream &is)
Build from the description in is.
word_t word(const value_t &v) const
Convert to a word.
static bool is_special(value_t v) ATTRIBUTE_PURE
const labelset_ptr labelset() const
static labelset_t::value_t get_value(const value_t &v)
The (inner) value when it (the outer value) is not one.
Print as rich UTF-8 text, escaped.
typename helper_t::value_t value_t
wordset(std::initializer_list< letter_t > letters)
static word_t letters_of(const value_t &v)
Prepare to iterate over the letters of v.
static int compare(const value_t &l, const value_t &r)
Three-way comparison between l and r.
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
An input/output format for valuesets.
Provide a variadic mul on top of a binary mul(), and one().
static constexpr bool is_free()
Implementation of labels are nullables (letter or empty).
genset_ptr genset() const
int compare(const Lhs &lhs, const Rhs &rhs)
Comparison between lhs and rhs.
std::ostream & str_escape(std::ostream &os, const std::string &str, const char *special=nullptr)
Output a string, escaping special characters.
void convs_(std::istream &i, Fun fun) const
Read and process a class of letters.
typename genset_t::word_t word_t
static constexpr bool is_letterized()
static ATTRIBUTE_PURE bool is_one(value_t l)
std::ostream & print(const value_t &l, std::ostream &o=std::cout, format fmt={}) const