Skip to content

Commit b42b052

Browse files
committed
Add the delimiter(p)[] directive, whic allows you to introduce a delimiter
into the parse of a permutation parser. Fixes #162.
1 parent 42c9d82 commit b42b052

File tree

4 files changed

+50
-23
lines changed

4 files changed

+50
-23
lines changed

include/boost/parser/detail/printing.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,10 @@ namespace boost { namespace parser { namespace detail {
7373
std::ostream & os,
7474
int components = 0);
7575

76-
template<typename Context, typename ParserTuple>
76+
template<typename Context, typename ParserTuple, typename DelimiterParser>
7777
void print_parser(
7878
Context const & context,
79-
perm_parser<ParserTuple> const & parser,
79+
perm_parser<ParserTuple, DelimiterParser> const & parser,
8080
std::ostream & os,
8181
int components = 0);
8282

include/boost/parser/detail/printing_impl.hpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,9 @@ namespace boost { namespace parser { namespace detail {
6363
struct n_aray_parser<or_parser<ParserTuple>> : std::true_type
6464
{};
6565

66-
template<typename ParserTuple>
67-
struct n_aray_parser<perm_parser<ParserTuple>> : std::true_type
66+
template<typename ParserTuple, typename DelimiterParser>
67+
struct n_aray_parser<perm_parser<ParserTuple, DelimiterParser>>
68+
: std::true_type
6869
{};
6970

7071
template<
@@ -206,15 +207,23 @@ namespace boost { namespace parser { namespace detail {
206207
context, parser, os, components, " | ...", " | ");
207208
}
208209

209-
template<typename Context, typename ParserTuple>
210+
template<typename Context, typename ParserTuple, typename DelimiterParser>
210211
void print_parser(
211212
Context const & context,
212-
perm_parser<ParserTuple> const & parser,
213+
perm_parser<ParserTuple, DelimiterParser> const & parser,
213214
std::ostream & os,
214215
int components)
215216
{
217+
if constexpr (!is_nope_v<DelimiterParser>) {
218+
os << "delimiter(";
219+
detail::print_parser(
220+
context, parser.delimiter_parser_, os, components);
221+
os << ")[";
222+
}
216223
detail::print_or_like_parser(
217224
context, parser, os, components, " || ...", " || ");
225+
if constexpr (!is_nope_v<DelimiterParser>)
226+
os << "]";
218227
}
219228

220229
template<

include/boost/parser/parser.hpp

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,8 +1015,8 @@ namespace boost { namespace parser {
10151015
template<typename T>
10161016
struct is_perm_p : std::false_type
10171017
{};
1018-
template<typename T>
1019-
struct is_perm_p<perm_parser<T>> : std::true_type
1018+
template<typename T, typename DelimiterParser>
1019+
struct is_perm_p<perm_parser<T, DelimiterParser>> : std::true_type
10201020
{};
10211021

10221022
template<typename T>
@@ -3413,10 +3413,14 @@ namespace boost { namespace parser {
34133413
ParserTuple parsers_;
34143414
};
34153415

3416-
template<typename ParserTuple>
3416+
template<typename ParserTuple, typename DelimiterParser>
34173417
struct perm_parser
34183418
{
34193419
constexpr perm_parser(ParserTuple parsers) : parsers_(parsers) {}
3420+
constexpr perm_parser(
3421+
ParserTuple parsers, DelimiterParser delimiter_parser) :
3422+
parsers_(parsers), delimiter_parser_(delimiter_parser)
3423+
{}
34203424

34213425
#ifndef BOOST_PARSER_DOXYGEN
34223426

@@ -3643,7 +3647,19 @@ namespace boost { namespace parser {
36433647
};
36443648
// Use one of the previously-unused parsers to parse one
36453649
// alternative.
3650+
bool first_iteration = true;
36463651
auto parsed_one = [&](auto) {
3652+
if constexpr (!detail::is_nope_v<DelimiterParser>) {
3653+
if (!first_iteration) {
3654+
detail::skip(first, last, skip, flags);
3655+
bool local_success = true;
3656+
delimiter_parser_.call(
3657+
first, last, context, skip, flags, local_success);
3658+
if (!local_success)
3659+
return false;
3660+
}
3661+
first_iteration = false;
3662+
}
36473663
return (
36483664
parse_into(
36493665
Is,
@@ -3667,6 +3683,7 @@ namespace boost { namespace parser {
36673683
#endif
36683684

36693685
ParserTuple parsers_;
3686+
DelimiterParser delimiter_parser_;
36703687
};
36713688

36723689
namespace detail {
@@ -5605,7 +5622,7 @@ namespace boost { namespace parser {
56055622
return rhs.parser_.prepend(*this);
56065623
} else {
56075624
return parser::parser_interface{
5608-
perm_parser<tuple<parser_type, ParserType2>>{
5625+
perm_parser<tuple<parser_type, ParserType2>, detail::nope>{
56095626
tuple<parser_type, ParserType2>{parser_, rhs.parser_}}};
56105627
}
56115628
}
@@ -6120,37 +6137,38 @@ namespace boost { namespace parser {
61206137
}
61216138
}
61226139

6123-
template<typename ParserTuple>
6140+
template<typename ParserTuple, typename DelimiterParser>
61246141
template<typename Parser>
6125-
constexpr auto perm_parser<ParserTuple>::prepend(
6142+
constexpr auto perm_parser<ParserTuple, DelimiterParser>::prepend(
61266143
parser_interface<Parser> parser) const noexcept
61276144
{
61286145
// If you're seeing this as a compile- or run-time failure, you've
61296146
// tried to put an eps parser in a permutation-parser, such as "eps ||
61306147
// int_".
61316148
BOOST_PARSER_ASSERT(!detail::is_eps_p<Parser>{});
6132-
return parser_interface{perm_parser<decltype(detail::hl::prepend(
6133-
parsers_, parser.parser_))>{
6134-
detail::hl::prepend(parsers_, parser.parser_)}};
6149+
return parser_interface{perm_parser<
6150+
decltype(detail::hl::prepend(parsers_, parser.parser_)),
6151+
detail::nope>{detail::hl::prepend(parsers_, parser.parser_)}};
61356152
}
61366153

6137-
template<typename ParserTuple>
6154+
template<typename ParserTuple, typename DelimiterParser>
61386155
template<typename Parser>
6139-
constexpr auto perm_parser<ParserTuple>::append(
6156+
constexpr auto perm_parser<ParserTuple, DelimiterParser>::append(
61406157
parser_interface<Parser> parser) const noexcept
61416158
{
61426159
// If you're seeing this as a compile- or run-time failure, you've
61436160
// tried to put an eps parser in a permutation-parser, such as "int_
61446161
// || eps".
61456162
BOOST_PARSER_ASSERT(!detail::is_eps_p<Parser>{});
61466163
if constexpr (detail::is_perm_p<Parser>{}) {
6147-
return parser_interface{perm_parser<decltype(detail::hl::concat(
6148-
parsers_, parser.parser_.parsers_))>{
6164+
return parser_interface{perm_parser<
6165+
decltype(detail::hl::concat(parsers_, parser.parser_.parsers_)),
6166+
detail::nope>{
61496167
detail::hl::concat(parsers_, parser.parser_.parsers_)}};
61506168
} else {
6151-
return parser_interface{perm_parser<decltype(detail::hl::append(
6152-
parsers_, parser.parser_))>{
6153-
detail::hl::append(parsers_, parser.parser_)}};
6169+
return parser_interface{perm_parser<
6170+
decltype(detail::hl::append(parsers_, parser.parser_)),
6171+
detail::nope>{detail::hl::append(parsers_, parser.parser_)}};
61546172
}
61556173
}
61566174

include/boost/parser/parser_fwd.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ namespace boost { namespace parser {
207207
`ParserTuple`, not the order of the parsers' matches. It is an error
208208
to specialize `perm_parser` with a `ParserTuple` template parameter
209209
that includes an `eps_parser`. */
210-
template<typename ParserTuple>
210+
template<typename ParserTuple, typename DelimiterParser>
211211
struct perm_parser;
212212

213213
/** Applies each parser in `ParserTuple`, in order. The parse succeeds

0 commit comments

Comments
 (0)