Skip to content

Commit 42c9d82

Browse files
committed
Add an optional char parser to quoted_string_parser, so that it can be made
fully general. Fixes #196.
1 parent 958ac38 commit 42c9d82

File tree

6 files changed

+187
-33
lines changed

6 files changed

+187
-33
lines changed

doc/tutorial.qbk

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,14 @@ escaped quote character, since those always work.
836836

837837
[quoted_string_example_5]
838838

839+
Additionally, with each of the forms shown above, you can optionally provide a
840+
parser as a final argument, to will be used to parse each character inside the
841+
quotes. You have to provide an actual full parser here; you cannot provide a
842+
character or string literal. If you do not provide a character parser, _ch_
843+
is used.
844+
845+
[quoted_string_example_6]
846+
839847
[endsect]
840848

841849
[section Parsing In Detail]

include/boost/parser/detail/printing.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,10 +280,14 @@ namespace boost { namespace parser { namespace detail {
280280
std::ostream & os,
281281
int components = 0);
282282

283-
template<typename Context, typename Quotes, typename Escapes>
283+
template<
284+
typename Context,
285+
typename Quotes,
286+
typename Escapes,
287+
typename CharParser>
284288
void print_parser(
285289
Context const & context,
286-
quoted_string_parser<Quotes, Escapes> const & parser,
290+
quoted_string_parser<Quotes, Escapes, CharParser> const & parser,
287291
std::ostream & os,
288292
int components = 0);
289293

include/boost/parser/detail/printing_impl.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -695,10 +695,14 @@ namespace boost { namespace parser { namespace detail {
695695
os << "\"";
696696
}
697697

698-
template<typename Context, typename Quotes, typename Escapes>
698+
template<
699+
typename Context,
700+
typename Quotes,
701+
typename Escapes,
702+
typename CharParser>
699703
void print_parser(
700704
Context const & context,
701-
quoted_string_parser<Quotes, Escapes> const & parser,
705+
quoted_string_parser<Quotes, Escapes, CharParser> const & parser,
702706
std::ostream & os,
703707
int components)
704708
{

include/boost/parser/parser.hpp

Lines changed: 72 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7252,7 +7252,7 @@ namespace boost { namespace parser {
72527252
return parser_interface{string_parser(str)};
72537253
}
72547254

7255-
template<typename Quotes, typename Escapes>
7255+
template<typename Quotes, typename Escapes, typename CharParser>
72567256
struct quoted_string_parser
72577257
{
72587258
constexpr quoted_string_parser() : chs_(), ch_('"') {}
@@ -7265,7 +7265,11 @@ namespace boost { namespace parser {
72657265
typename Enable =
72667266
std::enable_if_t<detail::is_parsable_range_like_v<R>>>
72677267
#endif
7268-
constexpr quoted_string_parser(R && r) : chs_((R &&) r), ch_(0)
7268+
constexpr quoted_string_parser(
7269+
R && r,
7270+
parser_interface<CharParser> char_p =
7271+
parser_interface{CharParser()}) :
7272+
chs_((R &&)r), char_p_(char_p), ch_(0)
72697273
{
72707274
BOOST_PARSER_DEBUG_ASSERT(r.begin() != r.end());
72717275
}
@@ -7278,16 +7282,29 @@ namespace boost { namespace parser {
72787282
typename Enable =
72797283
std::enable_if_t<detail::is_parsable_range_like_v<R>>>
72807284
#endif
7281-
constexpr quoted_string_parser(R && r, Escapes escapes) :
7282-
chs_((R &&) r), escapes_(escapes), ch_(0)
7285+
constexpr quoted_string_parser(
7286+
R && r,
7287+
Escapes escapes,
7288+
parser_interface<CharParser> char_p =
7289+
parser_interface{CharParser()}) :
7290+
chs_((R &&)r), escapes_(escapes), char_p_(char_p), ch_(0)
72837291
{
72847292
BOOST_PARSER_DEBUG_ASSERT(r.begin() != r.end());
72857293
}
72867294

7287-
constexpr quoted_string_parser(char32_t cp) : chs_(), ch_(cp) {}
7295+
constexpr quoted_string_parser(
7296+
char32_t cp,
7297+
parser_interface<CharParser> char_p =
7298+
parser_interface{CharParser()}) :
7299+
chs_(), char_p_(char_p), ch_(cp)
7300+
{}
72887301

7289-
constexpr quoted_string_parser(char32_t cp, Escapes escapes) :
7290-
chs_(), escapes_(escapes), ch_(cp)
7302+
constexpr quoted_string_parser(
7303+
char32_t cp,
7304+
Escapes escapes,
7305+
parser_interface<CharParser> char_p =
7306+
parser_interface{CharParser()}) :
7307+
chs_(), escapes_(escapes), char_p_(char_p), ch_(cp)
72917308
{}
72927309

72937310
template<
@@ -7376,11 +7393,11 @@ namespace boost { namespace parser {
73767393
auto make_parser = [&]() {
73777394
if constexpr (detail::is_nope_v<Escapes>) {
73787395
return *((lit('\\') >> back_delim) |
7379-
(char_ - back_delim))[append] > ch;
7396+
(char_p_ - back_delim))[append] > ch;
73807397
} else {
73817398
return *((lit('\\') >> back_delim)[append] |
73827399
(lit('\\') >> parser_interface(escapes_))[append] |
7383-
(char_ - back_delim)[append]) > ch;
7400+
(char_p_ - back_delim)[append]) > ch;
73847401
}
73857402
};
73867403

@@ -7402,15 +7419,17 @@ namespace boost { namespace parser {
74027419
/** Returns a `parser_interface` containing a `quoted_string_parser`
74037420
that uses `x` as its quotation marks. */
74047421
#if BOOST_PARSER_USE_CONCEPTS
7405-
template<typename T>
7422+
template<typename T, typename Parser = char_parser<detail::nope>>
74067423
requires(!parsable_range_like<T>)
74077424
#else
74087425
template<
74097426
typename T,
7427+
typename Parser = char_parser<detail::nope>,
74107428
typename Enable =
74117429
std::enable_if_t<!detail::is_parsable_range_like_v<T>>>
74127430
#endif
7413-
constexpr auto operator()(T x) const noexcept
7431+
constexpr auto
7432+
operator()(T x, parser_interface<Parser> char_p = char_) const noexcept
74147433
{
74157434
if constexpr (!detail::is_nope_v<Quotes>) {
74167435
BOOST_PARSER_ASSERT(
@@ -7419,7 +7438,9 @@ namespace boost { namespace parser {
74197438
"quoted_string, like 'quoted_string('\"')('\\'')'. Quit "
74207439
"it!'"));
74217440
}
7422-
return parser_interface(quoted_string_parser(std::move(x)));
7441+
return parser_interface(
7442+
quoted_string_parser<detail::nope, detail::nope, Parser>(
7443+
std::move(x), char_p));
74237444
}
74247445

74257446
/** Returns a `parser_interface` containing a `quoted_string_parser`
@@ -7430,14 +7451,18 @@ namespace boost { namespace parser {
74307451
character begin matched is directly compared to the elements of
74317452
`r`. */
74327453
#if BOOST_PARSER_USE_CONCEPTS
7433-
template<parsable_range_like R>
7454+
template<
7455+
parsable_range_like R,
7456+
typename Parser = char_parser<detail::nope>>
74347457
#else
74357458
template<
74367459
typename R,
7460+
typename Parser = char_parser<detail::nope>,
74377461
typename Enable =
74387462
std::enable_if_t<detail::is_parsable_range_like_v<R>>>
74397463
#endif
7440-
constexpr auto operator()(R && r) const noexcept
7464+
constexpr auto operator()(
7465+
R && r, parser_interface<Parser> char_p = char_) const noexcept
74417466
{
74427467
BOOST_PARSER_ASSERT(((
74437468
!std::is_rvalue_reference_v<R &&> ||
@@ -7453,10 +7478,14 @@ namespace boost { namespace parser {
74537478
"'quoted_string(char-range)(char-range)'. Quit it!'"));
74547479
}
74557480
return parser_interface(
7456-
quoted_string_parser<decltype(BOOST_PARSER_SUBRANGE(
7457-
detail::make_view_begin(r), detail::make_view_end(r)))>(
7481+
quoted_string_parser<
7482+
decltype(BOOST_PARSER_SUBRANGE(
7483+
detail::make_view_begin(r), detail::make_view_end(r))),
7484+
detail::nope,
7485+
Parser>(
74587486
BOOST_PARSER_SUBRANGE(
7459-
detail::make_view_begin(r), detail::make_view_end(r))));
7487+
detail::make_view_begin(r), detail::make_view_end(r)),
7488+
char_p));
74607489
}
74617490

74627491
/** Returns a `parser_interface` containing a `quoted_string_parser`
@@ -7465,16 +7494,23 @@ namespace boost { namespace parser {
74657494
sequence, and what character(s) each escape sequence represents.
74667495
Note that `"\\"` and `"\ch"` are always valid escape sequences. */
74677496
#if BOOST_PARSER_USE_CONCEPTS
7468-
template<typename T, typename U>
7497+
template<
7498+
typename T,
7499+
typename U,
7500+
typename Parser = char_parser<detail::nope>>
74697501
requires(!parsable_range_like<T>)
74707502
#else
74717503
template<
74727504
typename T,
74737505
typename U,
7506+
typename Parser = char_parser<detail::nope>,
74747507
typename Enable =
74757508
std::enable_if_t<!detail::is_parsable_range_like_v<T>>>
74767509
#endif
7477-
auto operator()(T x, symbols<U> const & escapes) const noexcept
7510+
auto operator()(
7511+
T x,
7512+
symbols<U> const & escapes,
7513+
parser_interface<Parser> char_p = char_) const noexcept
74787514
{
74797515
if constexpr (!detail::is_nope_v<Quotes>) {
74807516
BOOST_PARSER_ASSERT(
@@ -7484,8 +7520,9 @@ namespace boost { namespace parser {
74847520
"it!'"));
74857521
}
74867522
auto symbols = symbol_parser(escapes.parser_);
7487-
auto parser = quoted_string_parser<detail::nope, decltype(symbols)>(
7488-
char32_t(x), symbols);
7523+
auto parser =
7524+
quoted_string_parser<detail::nope, decltype(symbols), Parser>(
7525+
char32_t(x), symbols, char_p);
74897526
return parser_interface(parser);
74907527
}
74917528

@@ -7500,15 +7537,22 @@ namespace boost { namespace parser {
75007537
escape sequence represents. Note that `"\\"` and `"\ch"` are
75017538
always valid escape sequences. */
75027539
#if BOOST_PARSER_USE_CONCEPTS
7503-
template<parsable_range_like R, typename T>
7540+
template<
7541+
parsable_range_like R,
7542+
typename T,
7543+
typename Parser = char_parser<detail::nope>>
75047544
#else
75057545
template<
75067546
typename R,
75077547
typename T,
7548+
typename Parser = char_parser<detail::nope>,
75087549
typename Enable =
75097550
std::enable_if_t<detail::is_parsable_range_like_v<R>>>
75107551
#endif
7511-
auto operator()(R && r, symbols<T> const & escapes) const noexcept
7552+
auto operator()(
7553+
R && r,
7554+
symbols<T> const & escapes,
7555+
parser_interface<Parser> char_p = char_) const noexcept
75127556
{
75137557
BOOST_PARSER_ASSERT(((
75147558
!std::is_rvalue_reference_v<R &&> ||
@@ -7526,14 +7570,16 @@ namespace boost { namespace parser {
75267570
auto symbols = symbol_parser(escapes.parser_);
75277571
auto quotes = BOOST_PARSER_SUBRANGE(
75287572
detail::make_view_begin(r), detail::make_view_end(r));
7529-
auto parser =
7530-
quoted_string_parser<decltype(quotes), decltype(symbols)>(
7531-
quotes, symbols);
7573+
auto parser = quoted_string_parser<
7574+
decltype(quotes),
7575+
decltype(symbols),
7576+
Parser>(quotes, symbols, char_p);
75327577
return parser_interface(parser);
75337578
}
75347579

75357580
Quotes chs_;
75367581
Escapes escapes_;
7582+
parser_interface<CharParser> char_p_;
75377583
char32_t ch_;
75387584
};
75397585

include/boost/parser/parser_fwd.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,10 @@ namespace boost { namespace parser {
380380

381381
/** Matches a string delimited by quotation marks; produces a
382382
`std::string` attribute. */
383-
template<typename Quotes = detail::nope, typename Escapes = detail::nope>
383+
template<
384+
typename Quotes = detail::nope,
385+
typename Escapes = detail::nope,
386+
typename CharParser = char_parser<detail::nope>>
384387
struct quoted_string_parser;
385388

386389
/** Matches an end-of-line (`NewlinesOnly == true`), whitespace

0 commit comments

Comments
 (0)