[flang] Refinements; builds and passes tests again
authorpeter klausler <pklausler@nvidia.com>
Fri, 12 Jul 2019 16:30:19 +0000 (09:30 -0700)
committerpeter klausler <pklausler@nvidia.com>
Mon, 15 Jul 2019 20:05:23 +0000 (13:05 -0700)
Original-commit: flang-compiler/f18@a83410a4400a05b2b21e0207c605b5351bda6dbe
Reviewed-on: https://github.com/flang-compiler/f18/pull/569
Tree-same-pre-rewrite: false

flang/lib/parser/openmp-grammar.h

index 3fc6a58..c499978 100644 (file)
 // OpenMP Directives and Clauses
 namespace Fortran::parser {
 
+constexpr auto startOmpLine = skipStuffBeforeStatement >> "!$OMP "_sptok;
 constexpr auto endOmpLine = space >> endOfLine;
 
 // OpenMP Clauses
 // DEFAULT (PRIVATE | FIRSTPRIVATE | SHARED | NONE )
 TYPE_PARSER(construct<OmpDefaultClause>(
-    "PRIVATE"_id >> pure(OmpDefaultClause::Type::Private) ||
-    "FIRSTPRIVATE"_id >> pure(OmpDefaultClause::Type::Firstprivate) ||
-    "SHARED"_id >> pure(OmpDefaultClause::Type::Shared) ||
-    "NONE"_id >> pure(OmpDefaultClause::Type::None)))
+    "PRIVATE" >> pure(OmpDefaultClause::Type::Private) ||
+    "FIRSTPRIVATE" >> pure(OmpDefaultClause::Type::Firstprivate) ||
+    "SHARED" >> pure(OmpDefaultClause::Type::Shared) ||
+    "NONE" >> pure(OmpDefaultClause::Type::None)))
 
 // PROC_BIND(CLOSE | MASTER | SPREAD)
 TYPE_PARSER(construct<OmpProcBindClause>(
-    "CLOSE"_id >> pure(OmpProcBindClause::Type::Close) ||
-    "MASTER"_id >> pure(OmpProcBindClause::Type::Master) ||
-    "SPREAD"_id >> pure(OmpProcBindClause::Type::Spread)))
+    "CLOSE" >> pure(OmpProcBindClause::Type::Close) ||
+    "MASTER" >> pure(OmpProcBindClause::Type::Master) ||
+    "SPREAD" >> pure(OmpProcBindClause::Type::Spread)))
 
 // MAP ([ [map-type-modifier[,]] map-type : ] list)
 // map-type-modifier -> ALWAYS
 // map-type -> TO | FROM | TOFROM | ALLOC | RELEASE | DELETE
 TYPE_PARSER(construct<OmpMapType>(
-    maybe("ALWAYS"_id >> construct<OmpMapType::Always>() / maybe(","_tok)),
+    maybe("ALWAYS" >> construct<OmpMapType::Always>() / maybe(","_tok)),
     "TO"_id >> pure(OmpMapType::Type::To) / ":"_tok ||
-        "FROM"_id >> pure(OmpMapType::Type::From) / ":"_tok ||
-        "TOFROM"_id >> pure(OmpMapType::Type::Tofrom) / ":"_tok ||
-        "ALLOC"_id >> pure(OmpMapType::Type::Alloc) / ":"_tok ||
-        "RELEASE"_id >> pure(OmpMapType::Type::Release) / ":"_tok ||
-        "DELETE"_id >> pure(OmpMapType::Type::Delete) / ":"_tok))
+        "FROM" >> pure(OmpMapType::Type::From) / ":"_tok ||
+        "TOFROM" >> pure(OmpMapType::Type::Tofrom) / ":"_tok ||
+        "ALLOC" >> pure(OmpMapType::Type::Alloc) / ":"_tok ||
+        "RELEASE" >> pure(OmpMapType::Type::Release) / ":"_tok ||
+        "DELETE" >> pure(OmpMapType::Type::Delete) / ":"_tok))
 
 TYPE_PARSER(construct<OmpMapClause>(
     maybe(Parser<OmpMapType>{}), Parser<OmpObjectList>{}))
@@ -75,37 +76,36 @@ TYPE_PARSER(construct<OmpMapClause>(
 // kind -> STATIC | DYNAMIC | GUIDED | AUTO | RUNTIME
 // chunk_size -> ScalarIntExpr
 TYPE_PARSER(construct<OmpScheduleModifierType>(
-    "MONOTONIC"_id >> pure(OmpScheduleModifierType::ModType::Monotonic) ||
-    "NONMONOTONIC"_id >> pure(OmpScheduleModifierType::ModType::Nonmonotonic) ||
-    "SIMD"_id >> pure(OmpScheduleModifierType::ModType::Simd)))
+    "MONOTONIC" >> pure(OmpScheduleModifierType::ModType::Monotonic) ||
+    "NONMONOTONIC" >> pure(OmpScheduleModifierType::ModType::Nonmonotonic) ||
+    "SIMD" >> pure(OmpScheduleModifierType::ModType::Simd)))
 
 TYPE_PARSER(construct<OmpScheduleModifier>(Parser<OmpScheduleModifierType>{},
-    maybe(","_tok >> Parser<OmpScheduleModifierType>{}) / ":"_tok))
+    maybe("," >> Parser<OmpScheduleModifierType>{}) / ":"))
 
 TYPE_PARSER(construct<OmpScheduleClause>(maybe(Parser<OmpScheduleModifier>{}),
-    "STATIC"_id >> pure(OmpScheduleClause::ScheduleType::Static) ||
-        "DYNAMIC"_id >> pure(OmpScheduleClause::ScheduleType::Dynamic) ||
-        "GUIDED"_id >> pure(OmpScheduleClause::ScheduleType::Guided) ||
-        "AUTO"_id >> pure(OmpScheduleClause::ScheduleType::Auto) ||
-        "RUNTIME"_id >> pure(OmpScheduleClause::ScheduleType::Runtime),
-    maybe(","_tok >> scalarIntExpr)))
+    "STATIC" >> pure(OmpScheduleClause::ScheduleType::Static) ||
+        "DYNAMIC" >> pure(OmpScheduleClause::ScheduleType::Dynamic) ||
+        "GUIDED" >> pure(OmpScheduleClause::ScheduleType::Guided) ||
+        "AUTO" >> pure(OmpScheduleClause::ScheduleType::Auto) ||
+        "RUNTIME" >> pure(OmpScheduleClause::ScheduleType::Runtime),
+    maybe("," >> scalarIntExpr)))
 
 // IF(directive-name-modifier: scalar-logical-expr)
 TYPE_PARSER(construct<OmpIfClause>(
-    maybe(
-        ("PARALLEL"_id >> pure(OmpIfClause::DirectiveNameModifier::Parallel) ||
-            "TARGET ENTER DATA"_id >>
-                pure(OmpIfClause::DirectiveNameModifier::TargetEnterData) ||
-            "TARGET EXIT DATA"_id >>
-                pure(OmpIfClause::DirectiveNameModifier::TargetExitData) ||
-            "TARGET DATA"_id >>
-                pure(OmpIfClause::DirectiveNameModifier::TargetData) ||
-            "TARGET UPDATE"_id >>
-                pure(OmpIfClause::DirectiveNameModifier::TargetUpdate) ||
-            "TARGET"_id >> pure(OmpIfClause::DirectiveNameModifier::Target) ||
-            "TASKLOOP"_id >> pure(OmpIfClause::DirectiveNameModifier::Taskloop) ||
-            "TASK"_id >> pure(OmpIfClause::DirectiveNameModifier::Task)) /
-        ":"_tok),
+    maybe(("PARALLEL" >> pure(OmpIfClause::DirectiveNameModifier::Parallel) ||
+              "TARGET ENTER DATA" >>
+                  pure(OmpIfClause::DirectiveNameModifier::TargetEnterData) ||
+              "TARGET EXIT DATA" >>
+                  pure(OmpIfClause::DirectiveNameModifier::TargetExitData) ||
+              "TARGET DATA" >>
+                  pure(OmpIfClause::DirectiveNameModifier::TargetData) ||
+              "TARGET UPDATE" >>
+                  pure(OmpIfClause::DirectiveNameModifier::TargetUpdate) ||
+              "TARGET" >> pure(OmpIfClause::DirectiveNameModifier::Target) ||
+              "TASK"_id >> pure(OmpIfClause::DirectiveNameModifier::Taskloop) ||
+              "TASKLOOP" >> pure(OmpIfClause::DirectiveNameModifier::Task)) /
+        ":"),
     scalarLogicalExpr))
 
 TYPE_PARSER(
@@ -113,7 +113,7 @@ TYPE_PARSER(
     construct<OmpReductionOperator>(Parser<ProcedureDesignator>{}))
 
 TYPE_PARSER(construct<OmpReductionClause>(
-    Parser<OmpReductionOperator>{} / ":"_tok, nonemptyList(designator)))
+    Parser<OmpReductionOperator>{} / ":", nonemptyList(designator)))
 
 // DEPEND(SOURCE | SINK : vec | (IN | OUT | INOUT) : list
 TYPE_PARSER(construct<OmpDependSinkVecLength>(
@@ -122,33 +122,33 @@ TYPE_PARSER(construct<OmpDependSinkVecLength>(
 TYPE_PARSER(
     construct<OmpDependSinkVec>(name, maybe(Parser<OmpDependSinkVecLength>{})))
 
-TYPE_PARSER(construct<OmpDependenceType>(
-    "INOUT"_id >> pure(OmpDependenceType::Type::Inout) ||
-    "IN"_id >> pure(OmpDependenceType::Type::In) ||
-    "OUT"_id >> pure(OmpDependenceType::Type::Out)))
+TYPE_PARSER(
+    construct<OmpDependenceType>("IN"_id >> pure(OmpDependenceType::Type::In) ||
+        "INOUT" >> pure(OmpDependenceType::Type::Inout) ||
+        "OUT" >> pure(OmpDependenceType::Type::Out)))
 
 TYPE_CONTEXT_PARSER("Omp Depend clause"_en_US,
     construct<OmpDependClause>(construct<OmpDependClause::Sink>(
-        "SINK"_id_tok >> ":"_tok >> nonemptyList(Parser<OmpDependSinkVec>{}))) ||
+        "SINK :" >> nonemptyList(Parser<OmpDependSinkVec>{}))) ||
         construct<OmpDependClause>(
-            construct<OmpDependClause::Source>("SOURCE"_id)) ||
+            construct<OmpDependClause::Source>("SOURCE"_tok)) ||
         construct<OmpDependClause>(construct<OmpDependClause::InOut>(
-            Parser<OmpDependenceType>{}, ":"_tok >> nonemptyList(designator))))
+            Parser<OmpDependenceType>{}, ":" >> nonemptyList(designator))))
 
 // linear-modifier
 TYPE_PARSER(
-    construct<OmpLinearModifier>("REF"_id >> pure(OmpLinearModifier::Type::Ref) ||
-        "VAL"_id >> pure(OmpLinearModifier::Type::Val) ||
-        "UVAL"_id >> pure(OmpLinearModifier::Type::Uval)))
+    construct<OmpLinearModifier>("REF" >> pure(OmpLinearModifier::Type::Ref) ||
+        "VAL" >> pure(OmpLinearModifier::Type::Val) ||
+        "UVAL" >> pure(OmpLinearModifier::Type::Uval)))
 
 // LINEAR(list: linear-step)
 TYPE_CONTEXT_PARSER("Omp LINEAR clause"_en_US,
     construct<OmpLinearClause>(
         construct<OmpLinearClause>(construct<OmpLinearClause::WithModifier>(
             Parser<OmpLinearModifier>{}, parenthesized(nonemptyList(name)),
-            maybe(":"_tok >> scalarIntConstantExpr))) ||
+            maybe(":" >> scalarIntConstantExpr))) ||
         construct<OmpLinearClause>(construct<OmpLinearClause::WithoutModifier>(
-            nonemptyList(name), maybe(":"_tok >> scalarIntConstantExpr)))))
+            nonemptyList(name), maybe(":" >> scalarIntConstantExpr)))))
 
 // ALIGNED(list: alignment)
 TYPE_PARSER(construct<OmpAlignedClause>(
@@ -166,18 +166,16 @@ TYPE_PARSER("ALIGNED" >>
                     parenthesized(Parser<OmpObjectList>{}))) ||
     "COPYPRIVATE" >> construct<OmpClause>(construct<OmpClause::Copyprivate>(
                          (parenthesized(Parser<OmpObjectList>{})))) ||
-    "DEFAULTMAP" >>
-        construct<OmpClause>(construct<OmpClause::Defaultmap>(
-            parenthesized("TOFROM"_tok >> ":"_tok >> "SCALAR"_tok))) ||
-    "DEFAULT" >>
+    "DEFAULT"_id >>
         construct<OmpClause>(parenthesized(Parser<OmpDefaultClause>{})) ||
+    "DEFAULTMAP" >> construct<OmpClause>(construct<OmpClause::Defaultmap>(
+                        "( TOFROM : SCALAR )"_tok)) ||
     "DEPEND" >>
         construct<OmpClause>(parenthesized(Parser<OmpDependClause>{})) ||
     "DEVICE" >> construct<OmpClause>(construct<OmpClause::Device>(
                     parenthesized(scalarIntExpr))) ||
-    "DIST_SCHEDULE" >>
-        construct<OmpClause>(construct<OmpClause::DistSchedule>(
-            parenthesized("STATIC"_tok >> ","_tok >> scalarIntExpr))) ||
+    "DIST_SCHEDULE" >> construct<OmpClause>(construct<OmpClause::DistSchedule>(
+                           parenthesized("STATIC ," >> scalarIntExpr))) ||
     "FINAL" >> construct<OmpClause>(
                    construct<OmpClause::Final>(parenthesized(scalarIntExpr))) ||
     "FIRSTPRIVATE" >> construct<OmpClause>(construct<OmpClause::Firstprivate>(
@@ -224,9 +222,9 @@ TYPE_PARSER("ALIGNED" >>
         construct<OmpClause>(parenthesized(Parser<OmpScheduleClause>{})) ||
     "SHARED" >> construct<OmpClause>(construct<OmpClause::Shared>(
                     parenthesized(Parser<OmpObjectList>{}))) ||
+    "SIMD"_id >> construct<OmpClause>(construct<OmpClause::Simd>()) ||
     "SIMDLEN" >> construct<OmpClause>(construct<OmpClause::Simdlen>(
                      parenthesized(scalarIntConstantExpr))) ||
-    "SIMD" >> construct<OmpClause>(construct<OmpClause::Simd>()) ||
     "THREADS" >> construct<OmpClause>(construct<OmpClause::Threads>()) ||
     "THREAD_LIMIT" >> construct<OmpClause>(construct<OmpClause::ThreadLimit>(
                           parenthesized(scalarIntExpr))) ||
@@ -256,15 +254,15 @@ TYPE_PARSER("DISTRIBUTE PARALLEL DO SIMD" >>
                              construct<OmpLoopDirective::DistributeSimd>()) ||
     "DISTRIBUTE" >> construct<OmpLoopDirective>(
                         construct<OmpLoopDirective::Distribute>()) ||
+    "DO SIMD" >>
+        construct<OmpLoopDirective>(construct<OmpLoopDirective::DoSimd>()) ||
+    "DO" >> construct<OmpLoopDirective>(construct<OmpLoopDirective::Do>()) ||
     "PARALLEL DO SIMD" >> construct<OmpLoopDirective>(
                               construct<OmpLoopDirective::ParallelDoSimd>()) ||
     "PARALLEL DO" >> construct<OmpLoopDirective>(
                          construct<OmpLoopDirective::ParallelDo>()) ||
     "SIMD" >>
         construct<OmpLoopDirective>(construct<OmpLoopDirective::Simd>()) ||
-    "DO SIMD" >>
-        construct<OmpLoopDirective>(construct<OmpLoopDirective::DoSimd>()) ||
-    "DO" >> construct<OmpLoopDirective>(construct<OmpLoopDirective::Do>()) ||
     "TARGET PARALLEL DO SIMD" >>
         construct<OmpLoopDirective>(
             construct<OmpLoopDirective::TargetParallelDoSimd>()) ||
@@ -350,21 +348,21 @@ TYPE_PARSER("MASTER" >>
                           construct<OmpBlockDirective::TargetTeams>()) ||
     "TARGET" >>
         construct<OmpBlockDirective>(construct<OmpBlockDirective::Target>()) ||
+    "TASK"_id >>
+        construct<OmpBlockDirective>(construct<OmpBlockDirective::Task>()) ||
     "TASKGROUP" >> construct<OmpBlockDirective>(
                        construct<OmpBlockDirective::Taskgroup>()) ||
-    "TASK" >>
-        construct<OmpBlockDirective>(construct<OmpBlockDirective::Task>()) ||
     "TEAMS" >>
         construct<OmpBlockDirective>(construct<OmpBlockDirective::Teams>()))
 
-TYPE_PARSER(construct<OmpReductionInitializerClause>("INITIALIZER"_tok >>
-    parenthesized("OMP_PRIV"_tok >> "="_tok >> indirect(expr))))
+TYPE_PARSER(construct<OmpReductionInitializerClause>(
+    "INITIALIZER" >> parenthesized("OMP_PRIV =" >> indirect(expr))))
 
 // Declare Reduction Construct
 TYPE_PARSER(construct<OpenMPDeclareReductionConstruct>(
-    "("_tok >> Parser<OmpReductionOperator>{} / ":"_tok,
-    nonemptyList(Parser<DeclarationTypeSpec>{}) / ":"_tok,
-    Parser<OmpReductionCombiner>{} / ")"_tok,
+    "(" >> Parser<OmpReductionOperator>{} / ":",
+    nonemptyList(Parser<DeclarationTypeSpec>{}) / ":",
+    Parser<OmpReductionCombiner>{} / ")",
     maybe(Parser<OmpReductionInitializerClause>{})))
 
 // declare-target-map-type
@@ -392,48 +390,40 @@ TYPE_PARSER(construct<OmpReductionCombiner>(Parser<AssignmentStmt>{}) ||
                 parenthesized(optionalList(actualArgSpec))))))
 
 // OMP END ATOMIC
-TYPE_PARSER(construct<OmpEndAtomic>("!$OMP "_sptok >> "END ATOMIC"_tok))
+TYPE_PARSER(construct<OmpEndAtomic>(startOmpLine >> "END ATOMIC"_tok))
 
 // OMP [SEQ_CST] ATOMIC READ [SEQ_CST]
 TYPE_PARSER(construct<OmpAtomicRead>(
-    maybe(
-        "SEQ_CST"_tok >> construct<OmpAtomicRead::SeqCst1>() / maybe(","_tok)),
+    maybe("SEQ_CST" >> construct<OmpAtomicRead::SeqCst1>() / maybe(","_tok)),
     "READ" >> maybe(","_tok) >>
-        maybe("SEQ_CST"_tok >> construct<OmpAtomicRead::SeqCst2>()) /
-            endOmpLine,
+        maybe("SEQ_CST" >> construct<OmpAtomicRead::SeqCst2>()) / endOmpLine,
     statement(assignmentStmt), maybe(Parser<OmpEndAtomic>{} / endOmpLine)))
 
 // OMP ATOMIC [SEQ_CST] CAPTURE [SEQ_CST]
 TYPE_PARSER(construct<OmpAtomicCapture>(
-    maybe("SEQ_CST"_tok >>
-        construct<OmpAtomicCapture::SeqCst1>() / maybe(","_tok)),
+    maybe("SEQ_CST" >> construct<OmpAtomicCapture::SeqCst1>() / maybe(","_tok)),
     "CAPTURE" >> maybe(","_tok) >>
-        maybe("SEQ_CST"_tok >> construct<OmpAtomicCapture::SeqCst2>()) /
-            endOmpLine,
+        maybe("SEQ_CST" >> construct<OmpAtomicCapture::SeqCst2>()) / endOmpLine,
     statement(assignmentStmt), statement(assignmentStmt),
     Parser<OmpEndAtomic>{} / endOmpLine))
 
 // OMP ATOMIC [SEQ_CST] UPDATE [SEQ_CST]
 TYPE_PARSER(construct<OmpAtomicUpdate>(
-    maybe("SEQ_CST"_tok >>
-        construct<OmpAtomicUpdate::SeqCst1>() / maybe(","_tok)),
+    maybe("SEQ_CST" >> construct<OmpAtomicUpdate::SeqCst1>() / maybe(","_tok)),
     "UPDATE" >> maybe(","_tok) >>
-        maybe("SEQ_CST"_tok >> construct<OmpAtomicUpdate::SeqCst2>()) /
-            endOmpLine,
+        maybe("SEQ_CST" >> construct<OmpAtomicUpdate::SeqCst2>()) / endOmpLine,
     statement(assignmentStmt), maybe(Parser<OmpEndAtomic>{} / endOmpLine)))
 
 // OMP ATOMIC [SEQ_CST]
 TYPE_PARSER(construct<OmpAtomic>(
-    maybe("SEQ_CST"_tok >> construct<OmpAtomic::SeqCst>()) / endOmpLine,
+    maybe("SEQ_CST" >> construct<OmpAtomic::SeqCst>()) / endOmpLine,
     statement(assignmentStmt), maybe(Parser<OmpEndAtomic>{} / endOmpLine)))
 
 // ATOMIC [SEQ_CST] WRITE [SEQ_CST]
 TYPE_PARSER(construct<OmpAtomicWrite>(
-    maybe(
-        "SEQ_CST"_tok >> construct<OmpAtomicWrite::SeqCst1>() / maybe(","_tok)),
+    maybe("SEQ_CST" >> construct<OmpAtomicWrite::SeqCst1>() / maybe(","_tok)),
     "WRITE" >> maybe(","_tok) >>
-        maybe("SEQ_CST"_tok >> construct<OmpAtomicWrite::SeqCst2>()) /
-            endOmpLine,
+        maybe("SEQ_CST" >> construct<OmpAtomicWrite::SeqCst2>()) / endOmpLine,
     statement(assignmentStmt), maybe(Parser<OmpEndAtomic>{} / endOmpLine)))
 
 // Atomic Construct
@@ -445,22 +435,22 @@ TYPE_PARSER("ATOMIC" >>
         construct<OpenMPAtomicConstruct>(Parser<OmpAtomic>{})))
 
 // OMP CRITICAL
-TYPE_PARSER("!$OMP "_sptok >> "END"_tok >> "CRITICAL"_tok >>
+TYPE_PARSER(startOmpLine >> "END CRITICAL"_tok >>
     construct<OmpEndCritical>(maybe(parenthesized(name))))
 
-TYPE_PARSER("CRITICAL" >>
-    construct<OpenMPCriticalConstruct>(maybe(parenthesized(name)),
-        maybe("HINT"_tok >> construct<OpenMPCriticalConstruct::Hint>(
-                                parenthesized(constantExpr))) /
-            endOmpLine,
-        block, Parser<OmpEndCritical>{} / endOmpLine))
+TYPE_PARSER(
+    "CRITICAL" >> construct<OpenMPCriticalConstruct>(maybe(parenthesized(name)),
+                      maybe("HINT" >> construct<OpenMPCriticalConstruct::Hint>(
+                                          parenthesized(constantExpr))) /
+                          endOmpLine,
+                      block, Parser<OmpEndCritical>{} / endOmpLine))
 
 // Declare Simd construct
 TYPE_PARSER(construct<OpenMPDeclareSimdConstruct>(
     maybe(parenthesized(name)), Parser<OmpClauseList>{}))
 
 // Declarative construct & Threadprivate directive
-TYPE_PARSER(!"!$OMP END"_tok >> "!$OMP "_tok >>
+TYPE_PARSER(startOmpLine >>
     ("DECLARE REDUCTION" >>
             construct<OpenMPDeclarativeConstruct>(
                 construct<OpenMPDeclarativeConstruct>(
@@ -497,15 +487,15 @@ TYPE_PARSER("TASKWAIT" >> construct<OpenMPTaskwaitConstruct>() / endOmpLine)
 TYPE_PARSER("TASKYIELD" >> construct<OpenMPTaskyieldConstruct>() / endOmpLine)
 
 // OMP SINGLE
-TYPE_PARSER(skipStuffBeforeStatement >> "!$OMP "_sptok >> "END"_tok >>
-    construct<OmpEndSingle>("SINGLE"_tok >> Parser<OmpClauseList>{}))
+TYPE_PARSER(startOmpLine >> "END"_tok >>
+    construct<OmpEndSingle>("SINGLE" >> Parser<OmpClauseList>{}))
 
 TYPE_PARSER("SINGLE" >>
     construct<OpenMPSingleConstruct>(Parser<OmpClauseList>{} / endOmpLine,
         block, Parser<OmpEndSingle>{} / endOmpLine))
 
-TYPE_PARSER(skipStuffBeforeStatement >> "!$OMP "_sptok >> "END"_tok >>
-    construct<OmpEndWorkshare>("WORKSHARE"_tok))
+TYPE_PARSER(
+    startOmpLine >> "END"_tok >> construct<OmpEndWorkshare>("WORKSHARE"_tok))
 
 // OMP WORKSHARE
 TYPE_PARSER("WORKSHARE" >>
@@ -520,10 +510,9 @@ TYPE_PARSER(construct<OmpEndDoSimd>(maybe(construct<OmpNowait>("NOWAIT"_tok))))
 TYPE_PARSER(construct<OmpEndDo>(maybe(construct<OmpNowait>("NOWAIT"_tok))))
 
 // OMP END SECTIONS [NOWAIT]
-TYPE_PARSER(skipStuffBeforeStatement >> "!$OMP "_sptok >> "END"_tok >>
-    "SECTIONS"_tok >>
+TYPE_PARSER(startOmpLine >> "END SECTIONS"_tok >>
     construct<OmpEndSections>(
-        maybe("NOWAIT"_tok >> construct<OmpNowait>()) / endOmpLine))
+        maybe("NOWAIT" >> construct<OmpNowait>()) / endOmpLine))
 
 // OMP SECTIONS
 TYPE_PARSER("SECTIONS" >>
@@ -531,10 +520,9 @@ TYPE_PARSER("SECTIONS" >>
         Parser<OmpClauseList>{} / endOmpLine, block, Parser<OmpEndSections>{}))
 
 // OMP END PARALLEL SECTIONS [NOWAIT]
-TYPE_PARSER(skipStuffBeforeStatement >> "!$OMP "_sptok >> "END"_tok >>
-    "PARALLEL SECTIONS"_tok >>
+TYPE_PARSER(startOmpLine >> "END PARALLEL SECTIONS"_tok >>
     construct<OmpEndParallelSections>(
-        maybe("NOWAIT"_tok >> construct<OmpNowait>()) / endOmpLine))
+        maybe("NOWAIT" >> construct<OmpNowait>()) / endOmpLine))
 
 // OMP PARALLEL SECTIONS
 TYPE_PARSER("PARALLEL SECTIONS" >> construct<OpenMPParallelSectionsConstruct>(
@@ -542,7 +530,7 @@ TYPE_PARSER("PARALLEL SECTIONS" >> construct<OpenMPParallelSectionsConstruct>(
                                        block, Parser<OmpEndParallelSections>{}))
 
 TYPE_CONTEXT_PARSER("OpenMP construct"_en_US,
-    skipStuffBeforeStatement >> "!$OMP "_sptok >> !"END"_tok >>
+    startOmpLine >>
         (construct<OpenMPConstruct>(
              indirect(Parser<OpenMPStandaloneConstruct>{})) ||
             construct<OpenMPConstruct>(
@@ -573,15 +561,15 @@ TYPE_CONTEXT_PARSER("OpenMP construct"_en_US,
                 indirect(Parser<OpenMPCancellationPointConstruct>{})) ||
             construct<OpenMPConstruct>(
                 indirect(Parser<OpenMPFlushConstruct>{})) ||
-            "SECTION"_tok >> endOmpLine >>
+            "SECTION" >> endOmpLine >>
                 construct<OpenMPConstruct>(construct<OmpSection>())))
 
 // END OMP Block directives
-TYPE_PARSER(skipStuffBeforeStatement >> "!$OMP "_sptok >> "END"_tok >>
+TYPE_PARSER(startOmpLine >> "END"_tok >>
     construct<OmpEndBlockDirective>(indirect(Parser<OmpBlockDirective>{})))
 
 // END OMP Loop directives
-TYPE_PARSER(skipStuffBeforeStatement >> "!$OMP "_sptok >> "END"_tok >>
+TYPE_PARSER(startOmpLine >> "END"_tok >>
     (construct<OpenMPEndLoopDirective>(
          "DO SIMD" >> indirect(Parser<OmpEndDoSimd>{}) / endOmpLine) ||
         construct<OpenMPEndLoopDirective>(