Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion flang/docs/ParserCombinators.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ collect the values that they return.
* `applyLambda([](&&x){}, p1, p2, ...)` is the same thing, but for lambdas
and other function objects.
* `applyMem(mf, p1, p2, ...)` is the same thing, but invokes a member
function of the result of the first parser for updates in place.
function of the result of the first parser.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the new version no longer work for updates in place?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It returns the value returned by the member call, so for member functions returning void (as it was before) it wouldn't work. For member functions returning reference to *this or something equivalent it should be fine.

Is modifying in-place is still needed? If so I'd need to separate the code from this PR into its own parser.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll need to look at usage sites (of which there are not many) to be sure this comment is obsolete. I wouldn't have added that comment unless I had been thinking about mutation in situ at the time.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't find any uses of this in the upstream sources. I thought that maybe it's used in some downstream project.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Go for it, then. Downstream usage can adapt if needed.


### Token Parsers
Last, we have these basic parsers on which the actual grammar of the Fortran
Expand Down
54 changes: 23 additions & 31 deletions flang/lib/Parser/basic-parsers.h
Original file line number Diff line number Diff line change
Expand Up @@ -580,11 +580,11 @@ template <typename PA> inline constexpr auto defaulted(PA p) {
// applyLambda(f, ...) is the same concept extended to std::function<> functors.
// It is not constexpr.
//
// Member function application is supported by applyMem(f, a). If the
// parser a succeeds and returns some value ax, the result is that returned
// by ax.f(). Additional parser arguments can be specified to supply their
// results to the member function call, so applyMem(f, a, b) succeeds if
// both a and b do so and returns the result of calling ax.f(std::move(bx)).
// Member function application is supported by applyMem(&C::f, a). If the
// parser a succeeds and returns some value ax of type C, the result is that
// returned by ax.f(). Additional parser arguments can be specified to supply
// their results to the member function call, so applyMem(&C::f, a, b) succeeds
// if both a and b do so and returns the result of calling ax.f(std::move(bx)).

// Runs a sequence of parsers until one fails or all have succeeded.
// Collects their results in a std::tuple<std::optional<>...>.
Expand Down Expand Up @@ -654,39 +654,31 @@ inline /* not constexpr */ auto applyLambda(
}

// Member function application
template <typename OBJPARSER, typename... PARSER> class AMFPHelper {
using resultType = typename OBJPARSER::resultType;

public:
using type = void (resultType::*)(typename PARSER::resultType &&...);
};
template <typename OBJPARSER, typename... PARSER>
using ApplicableMemberFunctionPointer =
typename AMFPHelper<OBJPARSER, PARSER...>::type;

template <typename OBJPARSER, typename... PARSER, std::size_t... J>
inline auto ApplyHelperMember(
ApplicableMemberFunctionPointer<OBJPARSER, PARSER...> mfp,
ApplyArgs<OBJPARSER, PARSER...> &&args, std::index_sequence<J...>) ->
typename OBJPARSER::resultType {
((*std::get<0>(args)).*mfp)(std::move(*std::get<J + 1>(args))...);
return std::get<0>(std::move(args));
template <typename MEMFUNC, typename OBJPARSER, typename... PARSER,
std::size_t... J>
inline auto ApplyHelperMember(MEMFUNC mfp,
ApplyArgs<OBJPARSER, PARSER...> &&args, std::index_sequence<J...>) {
return ((*std::get<0>(args)).*mfp)(std::move(*std::get<J + 1>(args))...);
}

template <typename OBJPARSER, typename... PARSER> class ApplyMemberFunction {
using funcType = ApplicableMemberFunctionPointer<OBJPARSER, PARSER...>;
template <typename MEMFUNC, typename OBJPARSER, typename... PARSER>
class ApplyMemberFunction {
static_assert(std::is_member_function_pointer_v<MEMFUNC>);
using funcType = MEMFUNC;

public:
using resultType = typename OBJPARSER::resultType;
using resultType =
std::invoke_result_t<MEMFUNC, typename OBJPARSER::resultType, PARSER...>;

constexpr ApplyMemberFunction(const ApplyMemberFunction &) = default;
constexpr ApplyMemberFunction(funcType f, OBJPARSER o, PARSER... p)
constexpr ApplyMemberFunction(MEMFUNC f, OBJPARSER o, PARSER... p)
: function_{f}, parsers_{o, p...} {}
std::optional<resultType> Parse(ParseState &state) const {
ApplyArgs<OBJPARSER, PARSER...> results;
using Sequence1 = std::index_sequence_for<OBJPARSER, PARSER...>;
using Sequence2 = std::index_sequence_for<PARSER...>;
if (ApplyHelperArgs(parsers_, results, state, Sequence1{})) {
return ApplyHelperMember<OBJPARSER, PARSER...>(
return ApplyHelperMember<MEMFUNC, OBJPARSER, PARSER...>(
function_, std::move(results), Sequence2{});
} else {
return std::nullopt;
Expand All @@ -698,11 +690,11 @@ template <typename OBJPARSER, typename... PARSER> class ApplyMemberFunction {
const std::tuple<OBJPARSER, PARSER...> parsers_;
};

template <typename OBJPARSER, typename... PARSER>
template <typename MEMFUNC, typename OBJPARSER, typename... PARSER>
inline constexpr auto applyMem(
ApplicableMemberFunctionPointer<OBJPARSER, PARSER...> mfp,
const OBJPARSER &objParser, PARSER... parser) {
return ApplyMemberFunction<OBJPARSER, PARSER...>{mfp, objParser, parser...};
MEMFUNC memfn, const OBJPARSER &objParser, PARSER... parser) {
return ApplyMemberFunction<MEMFUNC, OBJPARSER, PARSER...>{
memfn, objParser, parser...};
}

// As is done with function application via applyFunction() above, class
Expand Down
Loading