2
0
mirror of https://github.com/boostorg/parser.git synced 2026-01-19 16:32:13 +00:00

7 Commits

Author SHA1 Message Date
Andreas Buhr
c54307b95c update CI from macos-13 to macos-15
MacOS 13 is retired in github actions, see
https://github.com/actions/runner-images/issues/13046
2025-12-11 19:32:36 -06:00
Andreas Buhr
5b3f122aa7 use fold expressions in or_parser and seq_parser 2025-12-05 23:48:02 -06:00
Andreas Buhr
6db68bc7f7 add test for constexpr switch_parser
The test led to the following error before:
github_issues.cpp(522): error C3615: constexpr function
'boost::parser::switch_' cannot result in a constant expression
2025-11-25 12:02:18 -06:00
Andreas Buhr
00fe33d2f3 add "constexpr" to switch_parser constructor
so switch(predicate)(valA, parserA)(valB, parserB)
can result in a constexpr object.
2025-11-25 12:02:18 -06:00
Andreas Buhr
bb183cf5ee Improve error visualization.
If the parsed string contains tab characters on the failing line,
the underlining in the error message pointed to the wrong position.

This patch adds as many tab characters to the underlining as
there are in the parsed line. So the underlining points to the
correct position.
2025-11-23 12:14:55 -06:00
Zach Laine
885595f7bd Parse the attribute of quoted_string into a temporary, and assign at the end,
if successful.  This makes the code well-formed when the attribute type is an
optional.

Addresses PR #290.
2025-11-15 16:39:34 -06:00
Zach Laine
6826f957a1 Add missing 'else' between two if constexpr cases. 2025-11-15 15:57:05 -06:00
4 changed files with 81 additions and 12 deletions

View File

@@ -1,4 +1,4 @@
name: macos-13 - Clang 14
name: macos-15 - Clang
on:
push:
@@ -14,9 +14,9 @@ jobs:
build:
strategy:
matrix:
cxx_std: [17]
cxx_std: [17, 20]
runs-on: macos-13
runs-on: macos-15
steps:
- uses: actions/checkout@v4

View File

@@ -90,6 +90,9 @@ namespace boost { namespace parser {
os << ":\n";
std::string underlining(std::distance(position.line_start, it), ' ');
std::transform(position.line_start, it,
underlining.begin(),
[](auto c) { return c == '\t' ? '\t' : ' ';});
detail::trace_input(os, position.line_start, it, false, 1u << 31);
if (it == last) {
os << '\n' << underlining << "^\n";

View File

@@ -3529,7 +3529,9 @@ namespace boost { namespace parser {
else
use_parser.first_ = prev_first;
};
detail::hl::for_each(parsers_, try_parser); // TODO: -> fold-expr
std::apply([&try_parser](auto&&... args) {
((try_parser(args)), ...);
}, parsers_);
if (!done)
success = false;
@@ -4562,7 +4564,7 @@ namespace boost { namespace parser {
using just_out = detail::remove_cv_ref_t<decltype(out)>;
if constexpr (detail::is_nope_v<attr_t>) {
// nothing to do
} if constexpr (
} else if constexpr (
(!out_container ||
!std::is_same_v<just_x, just_out>) &&
std::is_assignable_v<just_out &, just_x &&> &&
@@ -4578,7 +4580,9 @@ namespace boost { namespace parser {
auto const parsers_and_indices =
detail::hl::zip(parsers_, indices, merged, backtracking{});
detail::hl::for_each(parsers_and_indices, use_parser);
std::apply([&use_parser](auto&&... args) {
((use_parser(args)), ...);
}, parsers_and_indices);
}
template<bool AllowBacktracking, typename Parser>
@@ -7635,9 +7639,10 @@ namespace boost { namespace parser {
auto const prev_first = first;
auto append = [&retval,
std::string temp;
auto append = [&temp,
gen_attrs = detail::gen_attrs(flags)](auto & ctx) {
detail::move_back(retval, _attr(ctx), gen_attrs);
detail::move_back(temp, _attr(ctx), gen_attrs);
};
auto quote_ch = [&]() {
@@ -7695,7 +7700,10 @@ namespace boost { namespace parser {
detail::disable_skip(flags),
success);
if (!success) {
if (success) {
if (detail::gen_attrs(flags))
detail::assign(retval, std::move(temp));
} else {
retval = Attribute();
first = prev_first;
}
@@ -8521,9 +8529,9 @@ namespace boost { namespace parser {
template<typename SwitchValue, typename OrParser>
struct switch_parser
{
switch_parser() {}
switch_parser(SwitchValue switch_value) : switch_value_(switch_value) {}
switch_parser(SwitchValue switch_value, OrParser or_parser) :
constexpr switch_parser() {}
constexpr switch_parser(SwitchValue switch_value) : switch_value_(switch_value) {}
constexpr switch_parser(SwitchValue switch_value, OrParser or_parser) :
switch_value_(switch_value), or_parser_(or_parser)
{}

View File

@@ -501,6 +501,62 @@ void github_issue_285()
BOOST_TEST(result.value().get() != nullptr);
}
void github_pr_290()
{
namespace bp = boost::parser;
auto const pTest = bp::lit("TEST:") > -bp::quoted_string;
auto result = bp::parse("TEST: \"foo\"", pTest, bp::blank);
BOOST_TEST(result);
BOOST_TEST(*result == "foo");
}
namespace github_pr_297_ {
namespace bp = boost::parser;
constexpr auto bar_required_f = [](auto& ctx) -> bool {
const bool& argument = bp::_p<0>(ctx);
return argument;
};
constexpr bp::rule<struct foobar_parser_tag> foobar_parser = "foobar_parser";
constexpr auto foobar_parser_def =
bp::lit("foo")
>> bp::switch_(bar_required_f)
(true, bp::lit("bar"))
(false, -bp::lit("bar"));
BOOST_PARSER_DEFINE_RULES(foobar_parser);
}
void github_pr_297()
{
namespace bp = boost::parser;
using namespace github_pr_297_;
{
const bool bar_required = true;
const bool result =
bp::parse("foo bar", foobar_parser.with(bar_required), bp::blank);
BOOST_TEST(result);
}
{
const bool bar_required = true;
const bool result =
bp::parse("foo", foobar_parser.with(bar_required), bp::blank);
BOOST_TEST(!result);
}
{
const bool bar_required = false;
const bool result =
bp::parse("foo bar", foobar_parser.with(bar_required), bp::blank);
BOOST_TEST(result);
}
{
const bool bar_required = false;
const bool result =
bp::parse("foo", foobar_parser.with(bar_required), bp::blank);
BOOST_TEST(result);
}
}
int main()
{
@@ -516,5 +572,7 @@ int main()
github_issue_268();
github_issue_279();
github_issue_285();
github_pr_290();
github_pr_297();
return boost::report_errors();
}