Skip to content

Commit 1b984e3

Browse files
Andreas Buhrtzlaine
authored andcommitted
Allow move-only attributes
This tests the usage of move-only attributes. parser.hpp and printing.hpp are slightly modified to make it work.
1 parent 316b492 commit 1b984e3

3 files changed

Lines changed: 185 additions & 4 deletions

File tree

include/boost/parser/detail/printing.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,7 @@ namespace boost { namespace parser { namespace detail {
593593
}
594594

595595
template<typename Context, typename T>
596-
auto resolve(Context const & context, T const & x);
596+
decltype(auto) resolve(Context const & context, T const & x);
597597

598598
template<typename Context>
599599
auto resolve(Context const &, nope n);

include/boost/parser/parser.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,7 +1020,7 @@ namespace boost { namespace parser {
10201020
bool Callable = is_detected_v<callable, T const &, Context const &>>
10211021
struct resolve_impl
10221022
{
1023-
static auto call(Context const &, T const & x) { return x; }
1023+
static auto& call(Context const &, T const & x) { return x; }
10241024
};
10251025

10261026
template<typename Context, typename T>
@@ -1033,7 +1033,7 @@ namespace boost { namespace parser {
10331033
};
10341034

10351035
template<typename Context, typename T>
1036-
auto resolve(Context const & context, T const & x)
1036+
decltype(auto) resolve(Context const & context, T const & x)
10371037
{
10381038
return resolve_impl<Context, T>::call(context, x);
10391039
}
@@ -4331,7 +4331,7 @@ namespace boost { namespace parser {
43314331
// A 1-tuple is converted to a scalar.
43324332
if constexpr (detail::hl::size(retval) == llong<1>{}) {
43334333
using namespace literals;
4334-
return parser::get(retval, 0_c);
4334+
return parser::get(std::move(retval), 0_c);
43354335
} else {
43364336
return retval;
43374337
}

test/github_issues.cpp

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,186 @@ void github_pr_297()
597597
}
598598
}
599599

600+
namespace github_issue_312_ {
601+
/*
602+
* Recursive descent parser for expressions.
603+
* Supports addition (+), multiplication (*) and
604+
* parethesized expressions, nothing else.
605+
*
606+
* Creates a tree of "evaluatable" objects which
607+
* own their downstream objects in a unique_ptr
608+
*/
609+
610+
// base class for all tree nodes
611+
struct evaluatable
612+
{
613+
virtual double evaluate() = 0;
614+
virtual ~evaluatable() = default;
615+
};
616+
617+
namespace bp = boost::parser;
618+
619+
// top level parser
620+
constexpr bp::rule<struct expression_tag, std::unique_ptr<evaluatable>> expression_parser = "expression_parser";
621+
622+
/*
623+
* LITERAL EXPRESSION
624+
*/
625+
struct literal_evaluatable : evaluatable
626+
{
627+
explicit literal_evaluatable(double v) : value_(v) {}
628+
double evaluate() override
629+
{
630+
return value_;
631+
}
632+
double value_;
633+
};
634+
constexpr bp::rule<struct literal_tag, std::unique_ptr<evaluatable>> literal_parser = "literal_parser";
635+
constexpr auto literal_parser_action = [](auto& ctx) {
636+
std::unique_ptr<evaluatable>& val = _val(ctx);
637+
double& parsed_value = _attr(ctx);
638+
val = std::make_unique<literal_evaluatable>(parsed_value);
639+
};
640+
constexpr auto literal_parser_def =
641+
bp::double_[literal_parser_action];
642+
643+
/*
644+
* PARENTHESIZED EXPRESSION
645+
*/
646+
struct parenthesized_evaluatable : evaluatable
647+
{
648+
explicit parenthesized_evaluatable(std::unique_ptr<evaluatable>&& e) : evaluatable_(std::move(e)) {}
649+
double evaluate() override
650+
{
651+
return evaluatable_->evaluate();
652+
}
653+
std::unique_ptr<evaluatable> evaluatable_;
654+
};
655+
constexpr bp::rule<struct parenthesized_tag, std::unique_ptr<evaluatable>> parenthesized_parser = "parenthesized_parser";
656+
constexpr auto parenthesized_action = [](auto& ctx) {
657+
std::unique_ptr<evaluatable>& val = _val(ctx);
658+
std::unique_ptr<evaluatable>& attr = _attr(ctx);
659+
val = std::make_unique<parenthesized_evaluatable>(std::move(attr));
660+
};
661+
constexpr auto parenthesized_parser_def =
662+
(
663+
bp::lit('(') > expression_parser > bp::lit(')')
664+
)[parenthesized_action];
665+
666+
/*
667+
* ATOM EXPRESSION
668+
*/
669+
struct atom_evaluatable : evaluatable
670+
{
671+
explicit atom_evaluatable(std::unique_ptr<evaluatable>&& e) : evaluatable_(std::move(e)) {}
672+
double evaluate() override
673+
{
674+
return evaluatable_->evaluate();
675+
}
676+
std::unique_ptr<evaluatable> evaluatable_;
677+
};
678+
constexpr bp::rule<struct atom_tag, std::unique_ptr<evaluatable>> atom_parser = "atom_parser";
679+
constexpr auto atom_action = [](auto& ctx) {
680+
std::unique_ptr<evaluatable>& val = _val(ctx);
681+
std::unique_ptr<evaluatable>& attr = _attr(ctx);
682+
val = std::make_unique<atom_evaluatable>(std::move(attr));
683+
};
684+
constexpr auto atom_parser_def =
685+
(
686+
parenthesized_parser
687+
|
688+
literal_parser
689+
)[atom_action];
690+
691+
/*
692+
* MULTIPLICATION EXPRESSION
693+
*/
694+
struct multiplication_evaluatable : evaluatable
695+
{
696+
multiplication_evaluatable(std::vector<std::unique_ptr<evaluatable>>&& e)
697+
: evaluatables_(std::move(e))
698+
{}
699+
double evaluate() override
700+
{
701+
double result = 1;
702+
for (const auto& e : evaluatables_) {
703+
result *= e->evaluate();
704+
}
705+
return result;
706+
}
707+
std::vector<std::unique_ptr<evaluatable>> evaluatables_;
708+
};
709+
constexpr bp::rule<struct mult_tag, std::unique_ptr<evaluatable>> mult_parser = "mult_parser";
710+
constexpr auto mult_parser_action = [](auto& ctx) {
711+
std::unique_ptr<evaluatable>& val = _val(ctx);
712+
std::vector<std::unique_ptr<evaluatable>>& operands = _attr(ctx);
713+
val = std::make_unique<multiplication_evaluatable>(std::move(operands));
714+
};
715+
constexpr auto mult_parser_def =
716+
(atom_parser % bp::lit('*'))[mult_parser_action];
717+
718+
/*
719+
* ADDITION EXPRESSION
720+
*/
721+
struct addition_evaluatable : evaluatable
722+
{
723+
addition_evaluatable(std::vector<std::unique_ptr<evaluatable>>&& e)
724+
: evaluatables_(std::move(e))
725+
{}
726+
double evaluate() override
727+
{
728+
double result = 0;
729+
for (const auto& e : evaluatables_) {
730+
result += e->evaluate();
731+
}
732+
return result;
733+
}
734+
std::vector<std::unique_ptr<evaluatable>> evaluatables_;
735+
};
736+
constexpr bp::rule<struct add_tag, std::unique_ptr<evaluatable>> add_parser = "add_parser";
737+
constexpr auto add_parser_action = [](auto& ctx) {
738+
std::unique_ptr<evaluatable>& val = _val(ctx);
739+
std::vector<std::unique_ptr<evaluatable>>& operands = _attr(ctx);
740+
val = std::make_unique<addition_evaluatable>(std::move(operands));
741+
};
742+
constexpr auto add_parser_def =
743+
(mult_parser % bp::lit('+'))[add_parser_action];
744+
745+
constexpr auto expression_parser_action = [](auto& ctx) {
746+
std::unique_ptr<evaluatable>& val = _val(ctx);
747+
std::unique_ptr<evaluatable>& attr = _attr(ctx);
748+
val = std::move(attr);
749+
};
750+
751+
/*
752+
* EXPRESSION
753+
*/
754+
constexpr auto expression_parser_def =
755+
add_parser[expression_parser_action];
756+
757+
BOOST_PARSER_DEFINE_RULES(
758+
literal_parser,
759+
mult_parser,
760+
add_parser,
761+
expression_parser,
762+
parenthesized_parser,
763+
atom_parser);
764+
}
765+
766+
void github_issue_312()
767+
{
768+
namespace bp = boost::parser;
769+
using namespace github_issue_312_;
770+
771+
auto result = bp::parse("(2 + 3) + 3.1415 * 2", expression_parser, bp::blank);
772+
BOOST_TEST(result);
773+
BOOST_TEST(result.value()->evaluate() == (2 + 3) + 3.1415 * 2);
774+
775+
result = bp::parse("((2*0.1) + 33.) * (2 + 3) + 3.1415 * 2", expression_parser, bp::blank);
776+
BOOST_TEST(result);
777+
BOOST_TEST(result.value()->evaluate() == ((2*0.1) + 33.) * (2 + 3) + 3.1415 * 2);
778+
}
779+
600780

601781
int main()
602782
{
@@ -615,5 +795,6 @@ int main()
615795
github_pr_290();
616796
github_issue_294();
617797
github_pr_297();
798+
github_issue_312();
618799
return boost::report_errors();
619800
}

0 commit comments

Comments
 (0)