@@ -34,6 +34,39 @@ namespace Fortran::parser {
3434constexpr auto startOmpLine = skipStuffBeforeStatement >> "!$OMP "_sptok;
3535constexpr auto endOmpLine = space >> endOfLine;
3636
37+ // Given a parser for a single element, and a parser for a list of elements
38+ // of the same type, create a parser that constructs the entire list by having
39+ // the single element be the head of the list, and the rest be the tail.
40+ template <typename ParserH, typename ParserT> struct ConsParser {
41+ static_assert(std::is_same_v<std::list<typename ParserH::resultType>,
42+ typename ParserT::resultType>);
43+
44+ using resultType = typename ParserT::resultType;
45+ constexpr ConsParser(ParserH h, ParserT t) : head_(h), tail_(t) {}
46+
47+ std::optional<resultType> Parse(ParseState &state) const {
48+ if (auto &&first{head_.Parse(state)}) {
49+ if (auto rest{tail_.Parse(state)}) {
50+ rest->push_front(std::move(*first));
51+ return std::move(*rest);
52+ }
53+ }
54+ return std::nullopt;
55+ }
56+
57+ private:
58+ const ParserH head_;
59+ const ParserT tail_;
60+ };
61+
62+ template <typename ParserH, typename ParserT,
63+ typename ValueH = typename ParserH::resultType,
64+ typename ValueT = typename ParserT::resultType,
65+ typename = std::enable_if_t<std::is_same_v<std::list<ValueH>, ValueT>>>
66+ constexpr auto cons(ParserH head, ParserT tail) {
67+ return ConsParser<ParserH, ParserT>(head, tail);
68+ }
69+
3770// Given a parser P for a wrapper class, invoke P, and if it succeeds return
3871// the wrapped object.
3972template <typename Parser> struct UnwrapParser {
@@ -1831,19 +1864,20 @@ TYPE_PARSER(
18311864 sourced("END"_tok >> Parser<OmpSectionsDirective>{}),
18321865 Parser<OmpClauseList>{})))
18331866
1834- // OMP SECTION-BLOCK
1835-
1836- TYPE_PARSER(construct<OpenMPSectionConstruct>(block))
1837-
1838- TYPE_PARSER(maybe(startOmpLine >> "SECTION"_tok / endOmpLine) >>
1839- construct<OmpSectionBlocks>(nonemptySeparated(
1840- construct<OpenMPConstruct>(sourced(Parser<OpenMPSectionConstruct>{})),
1841- startOmpLine >> "SECTION"_tok / endOmpLine)))
1867+ static constexpr auto sectionDir{
1868+ startOmpLine >> (predicated(OmpDirectiveNameParser{},
1869+ IsDirective(llvm::omp::Directive::OMPD_section)) >=
1870+ Parser<OmpDirectiveSpecification>{})};
18421871
18431872// OMP SECTIONS (OpenMP 5.0 - 2.8.1), PARALLEL SECTIONS (OpenMP 5.0 - 2.13.3)
1844- TYPE_PARSER(construct<OpenMPSectionsConstruct>(
1873+ TYPE_PARSER(sourced( construct<OpenMPSectionsConstruct>(
18451874 Parser<OmpBeginSectionsDirective>{} / endOmpLine,
1846- Parser<OmpSectionBlocks>{}, Parser<OmpEndSectionsDirective>{} / endOmpLine))
1875+ cons( //
1876+ construct<OpenMPConstruct>(sourced(
1877+ construct<OpenMPSectionConstruct>(maybe(sectionDir), block))),
1878+ many(construct<OpenMPConstruct>(
1879+ sourced(construct<OpenMPSectionConstruct>(sectionDir, block))))),
1880+ Parser<OmpEndSectionsDirective>{} / endOmpLine)))
18471881
18481882static bool IsExecutionPart(const OmpDirectiveName &name) {
18491883 return name.IsExecutionPart();
0 commit comments