@@ -23,6 +23,55 @@ namespace Fortran::parser {
2323constexpr auto startOmpLine = skipStuffBeforeStatement >> " !$OMP " _sptok;
2424constexpr auto endOmpLine = space >> endOfLine;
2525
26+ template <typename Separator>
27+ struct MapModifiers {
28+ constexpr MapModifiers (Separator sep,
29+ std::optional<MessageFixedText> msg = std::nullopt )
30+ : sep_(sep), msg_(msg) {}
31+ constexpr MapModifiers (const MapModifiers &) = default;
32+ constexpr MapModifiers (MapModifiers &&) = default;
33+
34+ using resultType =
35+ std::tuple<std::optional<std::list<OmpMapClause::TypeModifier>>,
36+ std::optional<OmpMapClause::Type>>;
37+
38+ std::optional<resultType> Parse (ParseState &state) const {
39+ auto pmod{Parser<OmpMapClause::TypeModifier>{}};
40+ auto ptype{Parser<OmpMapClause::Type>{}};
41+ auto startLoc{state.GetLocation ()};
42+
43+ auto &&[mods, type] = [&]() -> resultType {
44+ // The 'maybe' will return optional<optional<list>>, and the outer
45+ // optional will never be nullopt.
46+ if (auto mods{
47+ *maybe (attempt (nonemptySeparated (pmod, sep_))).Parse (state)}) {
48+ // mods = optional<list>, and the list is nonempty.
49+ return attempt (sep_).Parse (state)
50+ ? resultType (mods, *maybe (attempt (ptype)).Parse (state))
51+ : resultType (mods, std::nullopt );
52+ }
53+ return {std::nullopt , *maybe (attempt (ptype)).Parse (state)};
54+ }();
55+ auto endLoc{state.GetLocation ()};
56+
57+ // The above always "succeeds", i.e. even if the input is junk, it will
58+ // return a tuple with two nullopts. If any of the components is not a
59+ // nullopt, expect a ":".
60+ if ((mods.has_value () || type.has_value ()) &&
61+ !attempt (" :" _tok).Parse (state)) {
62+ return std::nullopt ;
63+ }
64+ if (msg_) {
65+ state.Say (CharBlock{startLoc, endLoc}, *msg_);
66+ }
67+ return resultType (mods, type);
68+ }
69+
70+ private:
71+ const Separator sep_;
72+ std::optional<MessageFixedText> msg_;
73+ };
74+
2675// OpenMP Clauses
2776// 2.15.3.1 DEFAULT (PRIVATE | FIRSTPRIVATE | SHARED | NONE)
2877TYPE_PARSER (construct<OmpDefaultClause>(
@@ -38,20 +87,41 @@ TYPE_PARSER(construct<OmpProcBindClause>(
3887 "PRIMARY" >> pure(OmpProcBindClause::Type::Primary) ||
3988 "SPREAD" >> pure(OmpProcBindClause::Type::Spread)))
4089
41- // 2.15.5.1 MAP ([ [ALWAYS[,]] map-type : ] variable-name-list)
42- // map-type -> TO | FROM | TOFROM | ALLOC | RELEASE | DELETE
43- TYPE_PARSER(construct<OmpMapType>(
44- maybe (" ALWAYS" >> construct<OmpMapType::Always>() / maybe(" ," _tok)),
45- (" TO" _id >> pure (OmpMapType::Type::To) ||
46- "FROM" >> pure(OmpMapType::Type::From) ||
47- "TOFROM" >> pure(OmpMapType::Type::Tofrom) ||
48- "ALLOC" >> pure(OmpMapType::Type::Alloc) ||
49- "RELEASE" >> pure(OmpMapType::Type::Release) ||
50- "DELETE" >> pure(OmpMapType::Type::Delete)) /
51- ":"))
52-
53- TYPE_PARSER(construct<OmpMapClause>(
54- maybe (Parser<OmpMapType>{}), Parser<OmpObjectList>{}))
90+ // 2.15.5.1 map ->
91+ // MAP ([ [map-type-modifiers [,] ] map-type : ] variable-name-list)
92+ // map-type-modifiers -> map-type-modifier [,] [...]
93+ // map-type-modifier -> ALWAYS | CLOSE | OMPX_HOLD | PRESENT
94+ // map-type -> ALLOC | DELETE | FROM | RELEASE | TO | TOFROM
95+ TYPE_PARSER(construct<OmpMapClause::TypeModifier>(
96+ " ALWAYS" >> pure (OmpMapClause::TypeModifier::Always) ||
97+ "CLOSE" >> pure(OmpMapClause::TypeModifier::Close) ||
98+ "OMPX_HOLD" >> pure(OmpMapClause::TypeModifier::OmpxHold) ||
99+ "PRESENT" >> pure(OmpMapClause::TypeModifier::Present)))
100+
101+ TYPE_PARSER(construct<OmpMapClause::Type>(
102+ " ALLOC" >> pure (OmpMapClause::Type::Alloc) ||
103+ "DELETE" >> pure(OmpMapClause::Type::Delete) ||
104+ "FROM" >> pure(OmpMapClause::Type::From) ||
105+ "RELEASE" >> pure(OmpMapClause::Type::Release) ||
106+ "TO"_id >> pure(OmpMapClause::Type::To) ||
107+ "TOFROM" >> pure(OmpMapClause::Type::Tofrom)))
108+
109+ static inline OmpMapClause
110+ makeMapClause(std::tuple<std::optional<std::list<OmpMapClause::TypeModifier>>,
111+ std::optional<OmpMapClause::Type>> &&mod,
112+ OmpObjectList &&obj) {
113+ return OmpMapClause{std::move (std::get<0 >(mod)), std::move (std::get<1 >(mod)),
114+ std::move (obj)};
115+ }
116+
117+ TYPE_PARSER (construct<OmpMapClause>(applyFunction(
118+ makeMapClause,
119+ (MapModifiers(" ," _tok) ||
120+ MapModifiers(
121+ maybe (" ," _tok),
122+ "the specification of modifiers without comma separators for the "
123+ "'MAP' clause has been deprecated"_port_en_US)),
124+ Parser<OmpObjectList>{})))
55125
56126// [OpenMP 5.0]
57127// 2.19.7.2 defaultmap(implicit-behavior[:variable-category])
0 commit comments