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())),
113 if constexpr (lexy::is_unicode_encoding<encoding>)
115 static_assert(CharClass::char_class_unicode(),
116 "cannot use this character class with Unicode encoding");
120 && CharClass::char_class_match_cp(result.cp))
122 reader.reset(result.end);
126 finish(context, sink, reader.position());
128 auto recover_begin = reader.position();
129 if (recover_begin == result.end.position())
132 reader.reset(result.end);
133 _recover(context, recover_begin, reader.position());
138 static_assert(!CharClass::char_class_unicode(),
139 "cannot use this character class with non-Unicode char encoding");
141 "EOF should be checked before calling this");
143 auto recover_begin = reader.position();
144 auto cp =
static_cast<char32_t
>(reader.peek());
147 if (!CharClass::char_class_match_cp(cp))
149 finish(context, sink, recover_begin);
150 _recover(context, recover_begin, reader.position());
159 "EOF should be checked before calling this");
160 auto recover_begin = reader.position();
162 auto recover_end = reader.position();
164 finish(context, sink, recover_begin);
165 _recover(context, recover_begin, recover_end);
169 template <
typename Context,
typename Sink>
170 constexpr
void finish(Context& context, Sink& sink,
typename Reader::iterator
end)
180 template <
typename Token,
typename Error = lexy::missing_delimiter>
185 template <
typename Reader>
186 static constexpr
bool peek(Reader reader)
191 template <
typename Error>
196 template <
typename Reader>
197 static constexpr
bool peek(Reader reader)
203 template <
typename Close,
typename Char,
typename Limit,
typename... Escapes>
206 using _limit = std::conditional_t<std::is_void_v<Limit> || lexy::is_token_rule<Limit>,
209 template <
typename CloseParser,
typename Context,
typename Reader,
typename Sink>
213 auto del_begin = reader.position();
219 cur_chars.
parse_swar(reader, Close{}, Escapes{}...);
222 if (close.try_parse(context.control_block, reader))
224 close.cancel(context);
230 auto end = reader.position();
239 if ((Escapes::esc_try_parse(context, reader, sink, cur_chars) || ...))
244 cur_chars.
parse_one(context, reader, sink);
248 cur_chars.
finish(context, sink, reader.position());
252 template <
typename NextParser>
255 template <
typename Context,
typename Reader,
typename... Args>
258 static_assert(lexy::is_char_encoding<typename Reader::encoding>);
259 auto sink = context.value_callback().sink();
263 if (!
_loop(close, context, reader, sink))
267 if constexpr (std::is_same_v<
typename decltype(sink)::return_type,
void>)
270 return close.template finish<NextParser>(context, reader,
LEXY_FWD(args)...);
274 return close.template finish<NextParser>(context, reader,
LEXY_FWD(args)...,
284 template <
typename Open,
typename Close,
typename Limit =
void>
288 template <
typename LimitCharClass>
289 constexpr
auto limit(LimitCharClass)
const
291 static_assert(std::is_void_v<Limit> && lexy::is_char_class_rule<LimitCharClass>);
296 template <
typename Error,
typename LimitCharClass>
297 constexpr
auto limit(LimitCharClass)
const
299 static_assert(std::is_void_v<Limit> && lexy::is_char_class_rule<LimitCharClass>);
305 template <
typename Char,
typename... Escapes>
308 static_assert(lexy::is_char_class_rule<Char>);
309 static_assert((std::is_base_of_v<_escape_base, Escapes> && ...));
328 template <
typename Open,
typename Close>
337 template <
typename Delim>
360 return "invalid escape sequence";
367 template <
typename Escape,
typename... Branches>
371 template <
typename Encoding>
374 return Escape::template lit_first_char<Encoding>();
377 template <
typename Context,
typename Reader,
typename Sink,
typename Char>
378 static constexpr
bool esc_try_parse(Context& context, Reader& reader, Sink& sink,
381 auto begin = reader.position();
385 if (!
token.try_parse(context.control_block, reader))
392 token.template finish<lexy::pattern_parser<>>(context, reader);
395 auto try_parse_branch = [&](
auto branch) {
397 if (!parser.try_parse(context.control_block, reader))
399 parser.cancel(context);
406 parser.template finish<lexy::sink_parser>(context, reader, sink);
409 auto found = (try_parse_branch(Branches{}) || ...);
411 if constexpr ((lexy::is_unconditional_branch_rule<Branches> || ...))
413 LEXY_ASSERT(found,
"there is an unconditional branch");
423 cur_chars.
begin = reader.position();
428 template <
typename Branch>
429 constexpr
auto rule(Branch)
const
432 return _escape<Escape, Branches..., Branch>{};
436 template <
typename Branch>
444 template <const auto& Table,
typename Rule>
447 return this->
rule(lexyd::symbol<Table>(
rule));
449 template <const auto& Table>
452 return this->
rule(lexyd::symbol<Table>);
459 template <
typename EscapeToken>
462 static_assert(lexy::is_token_rule<EscapeToken>);
470 #endif // LEXY_DSL_DELIMITED_HPP_INCLUDED