4 #ifndef LEXY_DSL_DELIMITED_HPP_INCLUDED
5 #define LEXY_DSL_DELIMITED_HPP_INCLUDED
22 return "missing delimiter";
29 template <
typename CharClass,
typename Reader>
32 typename Reader::iterator
begin;
36 template <
typename Context>
37 constexpr
void _recover(Context& context,
typename Reader::iterator recover_begin,
38 typename Reader::iterator recover_end)
40 CharClass::template char_class_report_error<Reader>(context, recover_begin);
52 template <
typename Close,
typename... Escs>
53 constexpr
void parse_swar(Reader& reader, Close, Escs...)
55 using encoding =
typename Reader::encoding;
60 if constexpr (lexy::_detail::is_swar_reader<Reader>
61 && (lexy::is_literal_rule<Close> && ... && Escs::esc_is_literal)
63 decltype(CharClass::template char_class_match_swar<encoding>({})),
71 auto cur = reader.peek_swar();
80 if constexpr (
sizeof...(Escs) > 0)
89 if (!CharClass::template char_class_match_swar<encoding>(cur))
99 template <
typename Context,
typename Sink>
100 constexpr
void parse_one(Context& context, Reader& reader, Sink& sink)
102 using encoding =
typename Reader::encoding;
106 if (matcher::template match<encoding>(reader.peek()))
110 else if constexpr (!std::is_same_v<decltype(CharClass::char_class_match_cp(char32_t())),
114 if constexpr (std::is_same_v<encoding, lexy::default_encoding>
115 || std::is_same_v<encoding, lexy::byte_encoding>)
117 static_assert(!CharClass::char_class_unicode(),
118 "cannot use this character class with default/byte_encoding");
120 "EOF should be checked before calling this");
122 auto recover_begin = reader.position();
123 auto cp =
static_cast<char32_t
>(reader.peek());
126 if (!CharClass::char_class_match_cp(cp))
128 finish(context, sink, recover_begin);
129 _recover(context, recover_begin, reader.position());
135 static_assert(CharClass::char_class_unicode(),
136 "cannot use this character class with Unicode encoding");
140 && CharClass::char_class_match_cp(result.cp))
142 reader.set_position(result.end);
146 finish(context, sink, reader.position());
147 _recover(context, reader.position(), result.end);
148 reader.set_position(result.end);
157 "EOF should be checked before calling this");
158 auto recover_begin = reader.position();
160 auto recover_end = reader.position();
162 finish(context, sink, recover_begin);
163 _recover(context, recover_begin, recover_end);
167 template <
typename Context,
typename Sink>
168 constexpr
void finish(Context& context, Sink& sink,
typename Reader::iterator
end)
178 template <
typename Token,
typename Error = lexy::missing_delimiter>
183 template <
typename Reader>
184 static constexpr
bool peek(Reader reader)
189 template <
typename Error>
194 template <
typename Reader>
195 static constexpr
bool peek(Reader reader)
201 template <
typename Close,
typename Char,
typename Limit,
typename... Escapes>
204 using _limit = std::conditional_t<std::is_void_v<Limit> || lexy::is_token_rule<Limit>,
207 template <
typename CloseParser,
typename Context,
typename Reader,
typename Sink>
211 auto del_begin = reader.position();
217 cur_chars.
parse_swar(reader, Close{}, Escapes{}...);
220 if (close.try_parse(context.control_block, reader))
222 close.cancel(context);
228 auto end = reader.position();
237 if ((Escapes::esc_try_parse(context, reader, sink, cur_chars) || ...))
242 cur_chars.
parse_one(context, reader, sink);
246 cur_chars.
finish(context, sink, reader.position());
250 template <
typename NextParser>
253 template <
typename Context,
typename Reader,
typename... Args>
256 auto sink = context.value_callback().sink();
260 if (!
_loop(close, context, reader, sink))
264 if constexpr (std::is_same_v<
typename decltype(sink)::return_type,
void>)
267 return close.template finish<NextParser>(context, reader,
LEXY_FWD(args)...);
271 return close.template finish<NextParser>(context, reader,
LEXY_FWD(args)...,
281 template <
typename Open,
typename Close,
typename Limit =
void>
285 template <
typename LimitCharClass>
286 constexpr
auto limit(LimitCharClass)
const
288 static_assert(std::is_void_v<Limit> && lexy::is_char_class_rule<LimitCharClass>);
293 template <
typename Error,
typename LimitCharClass>
294 constexpr
auto limit(LimitCharClass)
const
296 static_assert(std::is_void_v<Limit> && lexy::is_char_class_rule<LimitCharClass>);
302 template <
typename Char,
typename... Escapes>
305 static_assert(lexy::is_char_class_rule<Char>);
306 static_assert((std::is_base_of_v<_escape_base, Escapes> && ...));
325 template <
typename Open,
typename Close>
328 static_assert(lexy::is_branch_rule<Open> && lexy::is_branch_rule<Close>);
333 template <
typename Delim>
336 static_assert(lexy::is_branch_rule<Delim>);
356 return "invalid escape sequence";
363 template <
typename Escape,
typename... Branches>
367 template <
typename Encoding>
370 return Escape::template lit_first_char<Encoding>();
373 template <
typename Context,
typename Reader,
typename Sink,
typename Char>
374 static constexpr
bool esc_try_parse(Context& context, Reader& reader, Sink& sink,
377 auto begin = reader.position();
381 if (!
token.try_parse(context.control_block, reader))
388 token.template finish<lexy::pattern_parser<>>(context, reader);
391 auto try_parse_branch = [&](
auto branch) {
393 if (!parser.try_parse(context.control_block, reader))
395 parser.cancel(context);
402 parser.template finish<lexy::sink_parser>(context, reader, sink);
405 auto found = (try_parse_branch(Branches{}) || ...);
407 if constexpr ((lexy::is_unconditional_branch_rule<Branches> || ...))
409 LEXY_ASSERT(found,
"there is an unconditional branch");
419 cur_chars.
begin = reader.position();
424 template <
typename Branch>
425 constexpr
auto rule(Branch)
const
427 static_assert(lexy::is_branch_rule<Branch>);
428 return _escape<Escape, Branches..., Branch>{};
432 template <
typename Branch>
435 static_assert(lexy::is_branch_rule<Branch>);
440 template <const auto& Table,
typename Rule>
443 return this->
rule(lexyd::symbol<Table>(
rule));
445 template <const auto& Table>
448 return this->
rule(lexyd::symbol<Table>);
455 template <
typename EscapeToken>
458 static_assert(lexy::is_token_rule<EscapeToken>);
466 #endif // LEXY_DSL_DELIMITED_HPP_INCLUDED