4 #ifndef LEXY_DSL_CHAR_CLASS_HPP_INCLUDED
5 #define LEXY_DSL_CHAR_CLASS_HPP_INCLUDED
20 template <
typename Fn>
21 constexpr
void visit(Fn fn)
const
23 for (
auto i = 0; i != 128; ++i)
28 template <
typename Fn>
31 auto range_begin = -1;
32 auto last_char = range_begin;
34 if (range_begin == -1)
39 else if (last_char + 1 == c)
45 fn(range_begin, last_char);
50 if (range_begin != -1)
51 fn(range_begin, last_char);
73 template <std::
size_t RangeCount, std::
size_t SingleCount>
78 char singles[SingleCount == 0 ? 1 : SingleCount];
93 constexpr
auto set = T::char_class_ascii();
95 constexpr
auto count = [&set] {
98 std::size_t range_count;
99 std::size_t single_count;
104 ++result.range_count;
106 ++result.single_count;
115 auto cur_single = 0u;
119 result.range_lower[cur_range] = char(
lower);
120 result.range_upper[cur_range] = char(
upper);
125 result.singles[cur_single] = char(
lower);
136 template <
const auto& CompressedAsciiSet,
140 template <
const auto& CompressedAsciiSet, std::size_t... RangeIdx, std::size_t... SingleIdx>
144 template <
typename Encoding>
150 template <
typename Encoding>
155 ((to_int_type<Encoding>(CompressedAsciiSet.range_lower[RangeIdx]) <= cur
156 && cur <= to_int_type<Encoding>(CompressedAsciiSet.range_upper[RangeIdx]))
159 || ((cur == to_int_type<Encoding>(CompressedAsciiSet.singles[SingleIdx])) || ...);
166 template <
typename CharSet>
167 constexpr
auto _cas = lexy::_detail::compress_ascii_set<CharSet>();
169 template <
typename Derived>
186 template <
typename Reader,
typename Context>
190 constexpr
auto name = Derived::char_class_name();
197 template <
typename Encoding>
200 return std::false_type{};
204 template <
typename Reader>
207 typename Reader::marker
end;
209 constexpr
explicit tp(
const Reader& reader) :
end(reader.current()) {}
213 static_assert(lexy::is_char_encoding<typename Reader::encoding>);
216 if (matcher::template match<typename Reader::encoding>(reader.peek()))
219 end = reader.current();
223 if constexpr (std::is_same_v<decltype(Derived::char_class_match_cp(char32_t())),
228 else if constexpr (lexy::is_unicode_encoding<typename Reader::encoding>)
230 static_assert(Derived::char_class_unicode(),
231 "cannot use this character class with Unicode encoding");
238 if (!Derived::char_class_match_cp(result.cp))
246 static_assert(!Derived::char_class_unicode(),
247 "cannot use this character class with non-Unicode char encodings");
252 auto cp =
static_cast<char32_t
>(reader.peek());
255 if (!Derived::char_class_match_cp(cp))
258 end = reader.current();
263 template <
typename Context>
266 Derived::template char_class_report_error<Reader>(context, reader.position());
272 #define LEXY_CHAR_CLASS(Name, Rule) \
274 static_assert(::lexy::is_char_class_rule<LEXY_DECAY_DECLTYPE(Rule)>); \
275 struct c : ::lexyd::char_class_base<c> \
277 static constexpr auto char_class_unicode() \
279 return (Rule).char_class_unicode(); \
281 static LEXY_CONSTEVAL auto char_class_name() \
285 static LEXY_CONSTEVAL auto char_class_ascii() \
287 return (Rule).char_class_ascii(); \
289 static constexpr auto char_class_match_cp(char32_t cp) \
291 return (Rule).char_class_match_cp(cp); \
299 template <
typename CharT, CharT... C>
301 template <char32_t... Cp>
305 template <
char32_t Cp>
316 if constexpr (Cp <= 0x7F)
323 if constexpr (Cp <= 0x7F)
324 return std::false_type{};
329 template <
unsigned char Byte>
345 if constexpr (Byte <= 0x7F)
352 if constexpr (Byte <= 0x7F)
353 return std::false_type{};
359 template <
typename C,
typename = std::enable_if_t<lexy::is_
char_
class_rule<C>>>
364 template <
typename CharT, CharT C,
365 typename = std::enable_if_t<C <= 0x7F || std::is_same_v<CharT, char32_t>
366 || std::is_same_v<CharT, unsigned char>>>
369 if constexpr (std::is_same_v<CharT, unsigned char>)
372 return _ccp<static_cast<char32_t>(C)>{};
374 template <
char32_t CP>
383 template <
typename... Cs>
386 static_assert(
sizeof...(Cs) > 1);
390 constexpr
auto non_unicode = (!Cs::char_class_unicode() || ...);
391 static_assert(!non_unicode
394 || ((!Cs::char_class_unicode()
395 || std::is_same_v<decltype(Cs::char_class_match_cp(0)),
396 std::false_type>)&&...),
397 "cannot mix bytes and Unicode char classes");
409 (result.
insert(Cs::char_class_ascii()), ...);
415 if constexpr ((std::is_same_v<decltype(Cs::char_class_match_cp(cp)), std::false_type>
417 return std::false_type{};
419 return (Cs::char_class_match_cp(cp) || ...);
423 template <
typename R1,
typename R2>
430 template <
typename... Cs,
typename C>
435 template <
typename C,
typename... Cs>
441 template <
typename... Cs,
typename... Ds>
450 template <
typename C>
455 return C::char_class_unicode();
466 result.
insert(0x00, 0x7F);
467 result.
remove(C::char_class_ascii());
477 if constexpr (std::is_same_v<decltype(C::char_class_match_cp(cp)), std::false_type>)
480 return !C::char_class_match_cp(cp);
484 template <
typename C>
489 template <
typename C>
498 template <
typename Set,
typename Minus>
514 auto result = Set::char_class_ascii();
515 result.remove(Minus::char_class_ascii());
521 if constexpr (std::is_same_v<decltype(Set::char_class_match_cp(cp)), std::false_type>)
522 return std::false_type{};
523 else if constexpr (std::is_same_v<decltype(Minus::char_class_match_cp(cp)),
527 return cp > 0x7F && Set::char_class_match_cp(cp);
530 return cp > 0x7F && Set::char_class_match_cp(cp) && !Minus::char_class_match_cp(cp);
534 template <
typename Set,
typename Minus>
540 template <
typename Set,
typename Minus,
typename OtherMinus>
549 template <
typename... Cs>
552 static_assert(
sizeof...(Cs) > 1);
562 return "intersection";
568 for (
auto c = 0; c <= 0x7F; ++c)
569 if ((Cs::char_class_ascii().contains[c] && ...))
576 if constexpr ((std::is_same_v<decltype(Cs::char_class_match_cp(cp)), std::false_type>
578 return std::false_type{};
580 return (Cs::char_class_match_cp(cp) && ...);
584 template <
typename C1,
typename C2>
591 template <
typename... Cs,
typename C>
596 template <
typename C,
typename... Cs>
602 template <
typename... Cs,
typename... Ds>
609 #endif // LEXY_DSL_CHAR_CLASS_HPP_INCLUDED