[flang] Merge pull request flang-compiler/f18#137 from flang-compiler/omppar
authorhsuauthai <37883210+hsuauthai@users.noreply.github.com>
Fri, 20 Jul 2018 22:49:19 +0000 (15:49 -0700)
committerGitHub <noreply@github.com>
Fri, 20 Jul 2018 22:49:19 +0000 (15:49 -0700)
Omppar

Original-commit: flang-compiler/f18@d341464e7ffde700b94a11a2c3a82be71ddebf84
Reviewed-on: https://github.com/flang-compiler/f18/pull/137

Due to a conflicting rebase during the linearizing of flang-compiler/f18, this commit squashes a number of other commits:

flang-compiler/f18@cfbc8bd16b1c63da4f8cb5f501766f52e7f862d5 Add OpenMP Block directives and some declarative directive(TBD:declare reduction and declare target)
flang-compiler/f18@d198352f840ad51aa6ab944043e8879239ff5d15 Removed extra code from resolveing conflict of the merge.
flang-compiler/f18@85911a0e80b81913f9372456b7fdd0875777915c fix some grammar and unparsing.
flang-compiler/f18@43bcfb7cd3efb80ad15b5b853af6527981ef8182 OpenMP declartive directive can be after function declaration line. OpenMP Loop construct will be treated as if statement instead of block because currently parser cannot construct the loop if loop end with Label [Continue] Use DefinedOperator and ProcedureDesignator instead of create a new Parser and postpone the validity of operator in semantic.
flang-compiler/f18@5d83b50ad344c889afffa26552827433489b63da Merge branch 'master' into omppar
flang-compiler/f18@8c666436a5d29785a6480d4741d374fd0a5b3227 remove "HEAD" code and resolve conflict.

flang/lib/parser/grammar.h
flang/lib/parser/openmp-grammar.h
flang/lib/parser/parse-tree-visitor.h
flang/lib/parser/parse-tree.h
flang/lib/parser/stmt-parser.h
flang/lib/parser/type-parsers.h
flang/lib/parser/unparse.cc
flang/lib/semantics/dump-parse-tree.h

index 36f682b..dbfd22f 100644 (file)
@@ -49,7 +49,7 @@ namespace Fortran::parser {
 // R507 declaration-construct ->
 //        specification-construct | data-stmt | format-stmt |
 //        entry-stmt | stmt-function-stmt
-constexpr auto execPartLookAhead{first(actionStmt >> ok, "ASSOCIATE ("_tok,
+constexpr auto execPartLookAhead{first(actionStmt >> ok, openmpEndLoopDirective >> ok, openmpConstruct >> ok, "ASSOCIATE ("_tok,
     "BLOCK"_tok, "SELECT"_tok, "CHANGE TEAM"_sptok, "CRITICAL"_tok, "DO"_tok,
     "IF ("_tok, "WHERE ("_tok, "FORALL ("_tok)};
 constexpr auto declErrorRecovery{
@@ -96,7 +96,7 @@ TYPE_CONTEXT_PARSER("specification construct"_en_US,
         construct<SpecificationConstruct>(
             statement(indirect(typeDeclarationStmt))),
         construct<SpecificationConstruct>(indirect(Parser<StructureDef>{})),
-        construct<SpecificationConstruct>(indirect(openmpConstruct)),
+        construct<SpecificationConstruct>(indirect(openmpDeclarativeConstruct)),
         construct<SpecificationConstruct>(indirect(compilerDirective))))
 
 // R513 other-specification-stmt ->
@@ -263,7 +263,7 @@ TYPE_PARSER(construct<ProgramUnit>(indirect(functionSubprogram)) ||
 //         [use-stmt]... [import-stmt]... [implicit-part]
 //         [declaration-construct]...
 TYPE_CONTEXT_PARSER("specification part"_en_US,
-    construct<SpecificationPart>(
+    construct<SpecificationPart>(many(openmpDeclarativeConstruct),
         many(unambiguousStatement(indirect(Parser<UseStmt>{}))),
         many(unambiguousStatement(indirect(Parser<ImportStmt>{}))),
         implicitPart, many(declarationConstruct)))
@@ -274,7 +274,7 @@ TYPE_CONTEXT_PARSER("specification part"_en_US,
 // specialized error recovery in the event of a spurious executable
 // statement.
 constexpr auto limitedSpecificationPart{inContext("specification part"_en_US,
-    construct<SpecificationPart>(
+    construct<SpecificationPart>(many(openmpDeclarativeConstruct),
         many(unambiguousStatement(indirect(Parser<UseStmt>{}))),
         many(unambiguousStatement(indirect(Parser<ImportStmt>{}))),
         implicitPart, many(limitedDeclarationConstruct)))};
@@ -391,6 +391,7 @@ constexpr auto executableConstruct{
         construct<ExecutableConstruct>(indirect(Parser<SelectTypeConstruct>{})),
         construct<ExecutableConstruct>(indirect(whereConstruct)),
         construct<ExecutableConstruct>(indirect(forallConstruct)),
+        construct<ExecutableConstruct>(indirect(openmpEndLoopDirective)),
         construct<ExecutableConstruct>(indirect(openmpConstruct)),
         construct<ExecutableConstruct>(indirect(compilerDirective)))};
 
index 5ca0e2c..d668f59 100644 (file)
 // OpenMP Directives and Clauses
 namespace Fortran::parser {
 
-constexpr auto beginOmpDirective{skipStuffBeforeStatement >> "!$OMP "_sptok};
+constexpr auto endOmpLine = space >> endOfLine;
 
 // OpenMP Clauses
-
 // DEFAULT (PRIVATE | FIRSTPRIVATE | SHARED | NONE )
 TYPE_PARSER(construct<OmpDefaultClause>(
     "PRIVATE" >> pure(OmpDefaultClause::Type::Private) ||
@@ -59,15 +58,17 @@ TYPE_PARSER(construct<OmpProcBindClause>(
 // 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" >> construct<OmpMapType::Always>() / maybe(","_tok)),
+    "TO" >> pure(OmpMapType::Type::To) / ":"_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(maybe("ALWAYS" >> maybe(","_tok)) >>
-        ("TO" >> pure(OmpMapClause::Type::To) / ":"_tok ||
-            "FROM" >> pure(OmpMapClause::Type::From) / ":"_tok ||
-            "TOFROM" >> pure(OmpMapClause::Type::Tofrom) / ":"_tok ||
-            "ALLOC" >> pure(OmpMapClause::Type::Alloc) / ":"_tok ||
-            "RELEASE" >> pure(OmpMapClause::Type::Release) / ":"_tok ||
-            "DELETE" >> pure(OmpMapClause::Type::Delete) / ":"_tok)),
-    nonemptyList(name)))
+    maybe(Parser<OmpMapType>{}), Parser<OmpObjectList>{}))
 
 // SCHEDULE ([modifier [, modifier]:]kind[, chunk_size])
 // Modifier ->  MONITONIC | NONMONOTONIC | SIMD
@@ -87,45 +88,29 @@ TYPE_PARSER(construct<OmpScheduleClause>(maybe(Parser<OmpScheduleModifier>{}),
         "GUIDED" >> pure(OmpScheduleClause::ScheduleType::Guided) ||
         "AUTO" >> pure(OmpScheduleClause::ScheduleType::Auto) ||
         "RUNTIME" >> pure(OmpScheduleClause::ScheduleType::Runtime),
-    maybe(","_tok) >> scalarIntExpr))
+    maybe(","_tok >> scalarIntExpr)))
 
 // IF(directive-name-modifier: scalar-logical-expr)
 TYPE_PARSER(construct<OmpIfClause>(
     maybe(
-        "PARALLEL"_tok >> pure(OmpIfClause::DirectiveNameModifier::Parallel) ||
-        "TARGET ENTER DATA"_tok >>
-            pure(OmpIfClause::DirectiveNameModifier::TargetEnterData) ||
-        "TARGET EXIT DATA"_tok >>
-            pure(OmpIfClause::DirectiveNameModifier::TargetExitData) ||
-        "TARGET DATA"_tok >>
-            pure(OmpIfClause::DirectiveNameModifier::TargetData) ||
-        "TARGET UPDATE"_tok >>
-            pure(OmpIfClause::DirectiveNameModifier::TargetUpdate) ||
-        "TARGET"_tok >> pure(OmpIfClause::DirectiveNameModifier::Target) ||
-        "TASKLOOP"_tok >> pure(OmpIfClause::DirectiveNameModifier::Taskloop) ||
-        "TASK"_tok >> pure(OmpIfClause::DirectiveNameModifier::Task)) /
-        maybe(":"_tok),
+        ("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) ||
+            "TASKLOOP" >> pure(OmpIfClause::DirectiveNameModifier::Taskloop) ||
+            "TASK" >> pure(OmpIfClause::DirectiveNameModifier::Task)) /
+        ":"_tok),
     scalarLogicalExpr))
 
-// REDUCTION(reduction-identifier: list)
-constexpr auto reductionBinaryOperator{
-    "+" >> pure(OmpReductionOperator::BinaryOperator::Add) ||
-    "-" >> pure(OmpReductionOperator::BinaryOperator::Subtract) ||
-    "*" >> pure(OmpReductionOperator::BinaryOperator::Multiply) ||
-    ".AND." >> pure(OmpReductionOperator::BinaryOperator::AND) ||
-    ".OR." >> pure(OmpReductionOperator::BinaryOperator::OR) ||
-    ".EQV." >> pure(OmpReductionOperator::BinaryOperator::EQV) ||
-    ".NEQV." >> pure(OmpReductionOperator::BinaryOperator::NEQV)};
-
-constexpr auto reductionProcedureOperator{
-    "MIN" >> pure(OmpReductionOperator::ProcedureOperator::MIN) ||
-    "MAX" >> pure(OmpReductionOperator::ProcedureOperator::MAX) ||
-    "IAND" >> pure(OmpReductionOperator::ProcedureOperator::IAND) ||
-    "IOR" >> pure(OmpReductionOperator::ProcedureOperator::IOR) ||
-    "IEOR" >> pure(OmpReductionOperator::ProcedureOperator::IEOR)};
-
-TYPE_PARSER(construct<OmpReductionOperator>(reductionBinaryOperator) ||
-    construct<OmpReductionOperator>(reductionProcedureOperator))
+TYPE_PARSER(
+    construct<OmpReductionOperator>(indirect(Parser<DefinedOperator>{})) ||
+    construct<OmpReductionOperator>(Parser<ProcedureDesignator>{}))
 
 TYPE_PARSER(construct<OmpReductionClause>(
     Parser<OmpReductionOperator>{} / ":"_tok, nonemptyList(designator)))
@@ -138,9 +123,9 @@ TYPE_PARSER(
     construct<OmpDependSinkVec>(name, maybe(Parser<OmpDependSinkVecLength>{})))
 
 TYPE_PARSER(construct<OmpDependenceType>(
-    "IN"_tok >> pure(OmpDependenceType::Type::In) ||
-    "OUT"_tok >> pure(OmpDependenceType::Type::Out) ||
-    "INOUT"_tok >> pure(OmpDependenceType::Type::Inout)))
+    "INOUT" >> pure(OmpDependenceType::Type::Inout) ||
+    "IN" >> pure(OmpDependenceType::Type::In) ||
+    "OUT" >> pure(OmpDependenceType::Type::Out)))
 
 TYPE_CONTEXT_PARSER("Omp Depend clause"_en_US,
     construct<OmpDependClause>(construct<OmpDependClause::Sink>(
@@ -150,12 +135,13 @@ TYPE_CONTEXT_PARSER("Omp Depend clause"_en_US,
         construct<OmpDependClause>(construct<OmpDependClause::InOut>(
             Parser<OmpDependenceType>{}, ":"_tok >> nonemptyList(designator))))
 
-// LINEAR(list: linear-step)
-TYPE_PARSER(construct<OmpLinearModifier>(
-    "REF"_tok >> pure(OmpLinearModifier::Type::Ref) ||
-    "VAL"_tok >> pure(OmpLinearModifier::Type::Val) ||
-    "UVAL"_tok >> pure(OmpLinearModifier::Type::Uval)))
+// linear-modifier
+TYPE_PARSER(
+    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>(
@@ -168,187 +154,437 @@ TYPE_CONTEXT_PARSER("Omp LINEAR clause"_en_US,
 TYPE_PARSER(construct<OmpAlignedClause>(
     nonemptyList(name), maybe(":"_tok) >> scalarIntConstantExpr))
 
-TYPE_PARSER(construct<OmpNameList>(pure(OmpNameList::Kind::Object), name) ||
-    construct<OmpNameList>("/" >> pure(OmpNameList::Kind::Common), name / "/"))
-
-TYPE_PARSER(
-    construct<OmpClause>(construct<OmpClause::Defaultmap>("DEFAULTMAP"_tok >>
-        parenthesized("TOFROM"_tok >> ":"_tok >> "SCALAR"_tok))) ||
-    construct<OmpClause>(construct<OmpClause::Inbranch>("INBRANCH"_tok)) ||
-    construct<OmpClause>(construct<OmpClause::Mergeable>("MERGEABLE"_tok)) ||
-    construct<OmpClause>(construct<OmpClause::Nogroup>("NOGROUP"_tok)) ||
-    construct<OmpClause>(
-        construct<OmpClause::Notinbranch>("NOTINBRANCH"_tok)) ||
-    construct<OmpClause>(construct<OmpClause::Nowait>("NOWAIT"_tok)) ||
-    construct<OmpClause>(construct<OmpClause::Untied>("UNTIED"_tok)) ||
-    construct<OmpClause>(construct<OmpClause::Collapse>(
-        "COLLAPSE"_tok >> parenthesized(scalarIntConstantExpr))) ||
-    construct<OmpClause>(construct<OmpClause::Copyin>(
-        "COPYIN"_tok >> parenthesized(nonemptyList(Parser<OmpNameList>{})))) ||
-    construct<OmpClause>(construct<OmpClause::Copyprivate>("COPYPRIVATE"_tok >>
-        parenthesized(nonemptyList(Parser<OmpNameList>{})))) ||
-    construct<OmpClause>(construct<OmpClause::Device>(
-        "DEVICE"_tok >> parenthesized(scalarIntExpr))) ||
-    construct<OmpClause>(
-        construct<OmpClause::DistSchedule>("DIST_SCHEDULE"_tok >>
+TYPE_PARSER(construct<OmpObject>(pure(OmpObject::Kind::Object), designator) ||
+    construct<OmpObject>(
+        "/" >> pure(OmpObject::Kind::Common), designator / "/"))
+
+TYPE_PARSER("DEFAULTMAP" >>
+        construct<OmpClause>(construct<OmpClause::Defaultmap>(
+            parenthesized("TOFROM"_tok >> ":"_tok >> "SCALAR"_tok))) ||
+    "INBRANCH" >> construct<OmpClause>(construct<OmpClause::Inbranch>()) ||
+    "MERGEABLE" >> construct<OmpClause>(construct<OmpClause::Mergeable>()) ||
+    "NOGROUP" >> construct<OmpClause>(construct<OmpClause::Nogroup>()) ||
+    "NOTINBRANCH" >>
+        construct<OmpClause>(construct<OmpClause::Notinbranch>()) ||
+    "NOWAIT" >> construct<OmpClause>(construct<OmpNowait>()) ||
+    "UNTIED" >> construct<OmpClause>(construct<OmpClause::Untied>()) ||
+    "COLLAPSE" >> construct<OmpClause>(construct<OmpClause::Collapse>(
+                      parenthesized(scalarIntConstantExpr))) ||
+    "COPYIN" >> construct<OmpClause>(construct<OmpClause::Copyin>(
+                    parenthesized(Parser<OmpObjectList>{}))) ||
+    "COPYPRIVATE" >> construct<OmpClause>(construct<OmpClause::Copyprivate>(
+                         (parenthesized(Parser<OmpObjectList>{})))) ||
+    "DEVICE" >> construct<OmpClause>(construct<OmpClause::Device>(
+                    parenthesized(scalarIntExpr))) ||
+    "DIST_SCHEDULE" >>
+        construct<OmpClause>(construct<OmpClause::DistSchedule>(
             parenthesized("STATIC"_tok >> ","_tok >> scalarIntExpr))) ||
-    construct<OmpClause>(construct<OmpClause::Final>(
-        "FINAL"_tok >> parenthesized(scalarIntExpr))) ||
-    construct<OmpClause>(
-        construct<OmpClause::Firstprivate>("FIRSTPRIVATE"_tok >>
-            parenthesized(nonemptyList(Parser<OmpNameList>{})))) ||
-    construct<OmpClause>(construct<OmpClause::From>(
-        "FROM"_tok >> parenthesized(nonemptyList(designator)))) ||
-    construct<OmpClause>(construct<OmpClause::Grainsize>(
-        "GRAINSIZE"_tok >> parenthesized(scalarIntExpr))) ||
-    construct<OmpClause>(construct<OmpClause::Lastprivate>("LASTPRIVATE"_tok >>
-        parenthesized(nonemptyList(Parser<OmpNameList>{})))) ||
-    construct<OmpClause>(construct<OmpClause::Link>(
-        "LINK"_tok >> parenthesized(nonemptyList(name)))) ||
-    construct<OmpClause>(construct<OmpClause::NumTasks>(
-        "NUM_TASKS"_tok >> parenthesized(scalarIntExpr))) ||
-    construct<OmpClause>(construct<OmpClause::NumTeams>(
-        "NUM_TEAMS"_tok >> parenthesized(scalarIntExpr))) ||
-    construct<OmpClause>(construct<OmpClause::NumThreads>(
-        "NUM_THREADS"_tok >> parenthesized(scalarIntExpr))) ||
-    construct<OmpClause>(construct<OmpClause::Ordered>(
-        "ORDERED"_tok >> maybe(parenthesized(scalarIntConstantExpr)))) ||
-    construct<OmpClause>(construct<OmpClause::Priority>(
-        "PRIORITY"_tok >> parenthesized(scalarIntExpr))) ||
-    construct<OmpClause>(construct<OmpClause::Private>(
-        "PRIVATE"_tok >> parenthesized(nonemptyList(Parser<OmpNameList>{})))) ||
-    construct<OmpClause>(construct<OmpClause::Safelen>(
-        "SAFELEN"_tok >> parenthesized(scalarIntConstantExpr))) ||
-    construct<OmpClause>(construct<OmpClause::Shared>(
-        "SHARED"_tok >> parenthesized(nonemptyList(Parser<OmpNameList>{})))) ||
-    construct<OmpClause>(construct<OmpClause::Simdlen>(
-        "SIMDLEN"_tok >> parenthesized(scalarIntConstantExpr))) ||
-    construct<OmpClause>(construct<OmpClause::ThreadLimit>(
-        "THREAD_LIMIT"_tok >> parenthesized(scalarIntExpr))) ||
-    construct<OmpClause>(construct<OmpClause::To>(
-        "TO"_tok >> parenthesized(nonemptyList(designator)))) ||
-    construct<OmpClause>(construct<OmpClause::Uniform>(
-        "UNIFORM"_tok >> parenthesized(nonemptyList(name)))) ||
-    construct<OmpClause>(construct<OmpClause::UseDevicePtr>(
-        "USE_DEVICE_PTR"_tok >> parenthesized(nonemptyList(name)))) ||
-    construct<OmpClause>(
-        "ALIGNED"_tok >> parenthesized(Parser<OmpAlignedClause>{})) ||
-    construct<OmpClause>(
-        "DEFAULT"_tok >> parenthesized(Parser<OmpDefaultClause>{})) ||
-    construct<OmpClause>(
-        "DEPEND"_tok >> parenthesized(Parser<OmpDependClause>{})) ||
-    construct<OmpClause>("IF"_tok >> parenthesized(Parser<OmpIfClause>{})) ||
-    construct<OmpClause>(
-        "LINEAR"_tok >> parenthesized(Parser<OmpLinearClause>{})) ||
-    construct<OmpClause>("MAP"_tok >> parenthesized(Parser<OmpMapClause>{})) ||
-    construct<OmpClause>(
-        "PROC_BIND"_tok >> parenthesized(Parser<OmpProcBindClause>{})) ||
-    construct<OmpClause>(
-        "REDUCTION"_tok >> parenthesized(Parser<OmpReductionClause>{})) ||
-    construct<OmpClause>(
-        "SCHEDULE"_tok >> parenthesized(Parser<OmpScheduleClause>{})))
-
-TYPE_PARSER(skipStuffBeforeStatement >> "!$OMP END"_sptok >>
-    (construct<OmpEndDirective>(Parser<OmpLoopDirective>{})))
-
-// Omp directives enclosing do loop
+    "FINAL" >> construct<OmpClause>(
+                   construct<OmpClause::Final>(parenthesized(scalarIntExpr))) ||
+    "FIRSTPRIVATE" >> construct<OmpClause>(construct<OmpClause::Firstprivate>(
+                          parenthesized(Parser<OmpObjectList>{}))) ||
+    "FROM" >> construct<OmpClause>(construct<OmpClause::From>(
+                  parenthesized(nonemptyList(designator)))) ||
+    "GRAINSIZE" >> construct<OmpClause>(construct<OmpClause::Grainsize>(
+                       parenthesized(scalarIntExpr))) ||
+    "LASTPRIVATE" >> construct<OmpClause>(construct<OmpClause::Lastprivate>(
+                         parenthesized(Parser<OmpObjectList>{}))) ||
+    "NUM_TASKS" >> construct<OmpClause>(construct<OmpClause::NumTasks>(
+                       parenthesized(scalarIntExpr))) ||
+    "NUM_TEAMS" >> construct<OmpClause>(construct<OmpClause::NumTeams>(
+                       parenthesized(scalarIntExpr))) ||
+    "NUM_THREADS" >> construct<OmpClause>(construct<OmpClause::NumThreads>(
+                         parenthesized(scalarIntExpr))) ||
+    "ORDERED" >> construct<OmpClause>(construct<OmpClause::Ordered>(
+                     maybe(parenthesized(scalarIntConstantExpr)))) ||
+    "PRIORITY" >> construct<OmpClause>(construct<OmpClause::Priority>(
+                      parenthesized(scalarIntExpr))) ||
+    "PRIVATE" >> construct<OmpClause>(construct<OmpClause::Private>(
+                     parenthesized(Parser<OmpObjectList>{}))) ||
+    "SAFELEN" >> construct<OmpClause>(construct<OmpClause::Safelen>(
+                     parenthesized(scalarIntConstantExpr))) ||
+    "SHARED" >> construct<OmpClause>(construct<OmpClause::Shared>(
+                    parenthesized(Parser<OmpObjectList>{}))) ||
+    "SIMDLEN" >> construct<OmpClause>(construct<OmpClause::Simdlen>(
+                     parenthesized(scalarIntConstantExpr))) ||
+    "THREAD_LIMIT" >> construct<OmpClause>(construct<OmpClause::ThreadLimit>(
+                          parenthesized(scalarIntExpr))) ||
+    "TO" >> construct<OmpClause>(construct<OmpClause::To>(
+                parenthesized(nonemptyList(designator)))) ||
+    "UNIFORM" >> construct<OmpClause>(construct<OmpClause::Uniform>(
+                     parenthesized(nonemptyList(name)))) ||
+    "USE_DEVICE_PTR" >> construct<OmpClause>(construct<OmpClause::UseDevicePtr>(
+                            parenthesized(nonemptyList(name)))) ||
+    "ALIGNED" >>
+        construct<OmpClause>(parenthesized(Parser<OmpAlignedClause>{})) ||
+    "DEFAULT" >>
+        construct<OmpClause>(parenthesized(Parser<OmpDefaultClause>{})) ||
+    "DEPEND" >>
+        construct<OmpClause>(parenthesized(Parser<OmpDependClause>{})) ||
+    "IF" >> construct<OmpClause>(parenthesized(Parser<OmpIfClause>{})) ||
+    "LINEAR" >>
+        construct<OmpClause>(parenthesized(Parser<OmpLinearClause>{})) ||
+    "MAP" >> construct<OmpClause>(parenthesized(Parser<OmpMapClause>{})) ||
+    "PROC_BIND" >>
+        construct<OmpClause>(parenthesized(Parser<OmpProcBindClause>{})) ||
+    "REDUCTION" >>
+        construct<OmpClause>(parenthesized(Parser<OmpReductionClause>{})) ||
+    "SCHEDULE" >>
+        construct<OmpClause>(parenthesized(Parser<OmpScheduleClause>{})))
+
+// [Clause, [Clause], ...]
 TYPE_PARSER(
-    construct<OmpLoopDirective>(
-        construct<OmpLoopDirective::DistributeParallelDoSimd>(
-            "DISTRIBUTE PARALLEL DO SIMD"_tok >> many(Parser<OmpClause>{}))) ||
-    construct<OmpLoopDirective>(
-        construct<OmpLoopDirective::DistributeParallelDo>(
-            "DISTRIBUTE PARALLEL DO"_tok >> many(Parser<OmpClause>{}))) ||
-    construct<OmpLoopDirective>(construct<OmpLoopDirective::DistributeSimd>(
-        "DISTRIBUTE SIMD"_tok >> many(Parser<OmpClause>{}))) ||
-    construct<OmpLoopDirective>(construct<OmpLoopDirective::Distribute>(
-        "DISTRIBUTE"_tok >> many(Parser<OmpClause>{}))) ||
-    construct<OmpLoopDirective>(construct<OmpLoopDirective::DoSimd>(
-        "DO SIMD"_tok >> many(Parser<OmpClause>{}))) ||
-    construct<OmpLoopDirective>(construct<OmpLoopDirective::Do>(
-        "DO"_tok >> many(Parser<OmpClause>{}))) ||
-    construct<OmpLoopDirective>(construct<OmpLoopDirective::ParallelDoSimd>(
-        "PARALLEL DO SIMD"_tok >> many(Parser<OmpClause>{}))) ||
-    construct<OmpLoopDirective>(construct<OmpLoopDirective::ParallelDo>(
-        "PARALLEL DO"_tok >> many(Parser<OmpClause>{}))) ||
-    construct<OmpLoopDirective>(construct<OmpLoopDirective::Simd>(
-        "SIMD"_tok >> many(Parser<OmpClause>{}))) ||
-    construct<OmpLoopDirective>(
-        construct<OmpLoopDirective::TargetParallelDoSimd>(
-            "TARGET PARALLEL DO SIMD"_tok >> many(Parser<OmpClause>{}))) ||
-    construct<OmpLoopDirective>(construct<OmpLoopDirective::TargetParallelDo>(
-        "TARGET PARALLEL DO"_tok >> many(Parser<OmpClause>{}))) ||
-    construct<OmpLoopDirective>(construct<OmpLoopDirective::TargetSimd>(
-        "TARGET SIMD"_tok >> many(Parser<OmpClause>{}))) ||
-    construct<OmpLoopDirective>(
-        construct<OmpLoopDirective::TargetTeamsDistributeParallelDoSimd>(
-            "TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD"_tok >>
-            many(Parser<OmpClause>{}))) ||
-    construct<OmpLoopDirective>(
-        construct<OmpLoopDirective::TargetTeamsDistributeParallelDo>(
-            "TARGET TEAMS DISTRIBUTE PARALLEL DO"_tok >>
-            many(Parser<OmpClause>{}))) ||
-    construct<OmpLoopDirective>(
-        construct<OmpLoopDirective::TargetTeamsDistributeSimd>(
-            "TARGET TEAMS DISTRIBUTE SIMD"_tok >> many(Parser<OmpClause>{}))) ||
-    construct<OmpLoopDirective>(
-        construct<OmpLoopDirective::TargetTeamsDistribute>(
-            "TARGET TEAMS DISTRIBUTE"_tok >> many(Parser<OmpClause>{}))) ||
-    construct<OmpLoopDirective>(construct<OmpLoopDirective::TaskloopSimd>(
-        "TASKLOOP SIMD" >> many(Parser<OmpClause>{}))) ||
-    construct<OmpLoopDirective>(construct<OmpLoopDirective::Taskloop>(
-        "TASKLOOP" >> many(Parser<OmpClause>{}))) ||
-    construct<OmpLoopDirective>(
-        construct<OmpLoopDirective::TeamsDistributeParallelDoSimd>(
-            "TEAMS DISTRIBUTE PARALLEL DO SIMD"_tok >>
-            many(Parser<OmpClause>{}))) ||
-    construct<OmpLoopDirective>(
-        construct<OmpLoopDirective::TeamsDistributeParallelDo>(
-            "TEAMS DISTRIBUTE PARALLEL DO"_tok >> many(Parser<OmpClause>{}))) ||
-    construct<OmpLoopDirective>(
-        construct<OmpLoopDirective::TeamsDistributeSimd>(
-            "TEAMS DISTRIBUTE SIMD"_tok >> many(Parser<OmpClause>{}))) ||
-    construct<OmpLoopDirective>(construct<OmpLoopDirective::TeamsDistribute>(
-        "TEAMS DISTRIBUTE"_tok >> many(Parser<OmpClause>{}))))
-
-TYPE_PARSER(construct<OmpStandaloneDirective>(
-                construct<OmpStandaloneDirective::Barrier>(
-                    "BARRIER"_tok >> many(Parser<OmpClause>{}))) ||
-    construct<OmpStandaloneDirective>(
-        construct<OmpStandaloneDirective::CancellationPoint>(
-            "CANCELLATION POINT"_tok >> many(Parser<OmpClause>{}))) ||
-    construct<OmpStandaloneDirective>(construct<OmpStandaloneDirective::Cancel>(
-        "CANCEL"_tok >> many(Parser<OmpClause>{}))) ||
-    construct<OmpStandaloneDirective>(construct<OmpStandaloneDirective::Flush>(
-        "FLUSH"_tok >> many(Parser<OmpClause>{}))) ||
-    construct<OmpStandaloneDirective>(
-        construct<OmpStandaloneDirective::TargetEnterData>(
-            "TARGET ENTER DATA"_tok >> many(Parser<OmpClause>{}))) ||
-    construct<OmpStandaloneDirective>(
-        construct<OmpStandaloneDirective::TargetExitData>(
-            "TARGET EXIT DATA"_tok >> many(Parser<OmpClause>{}))) ||
-    construct<OmpStandaloneDirective>(
-        construct<OmpStandaloneDirective::TargetUpdate>(
-            "TARGET UPDATE"_tok >> many(Parser<OmpClause>{}))) ||
-    construct<OmpStandaloneDirective>(
-        construct<OmpStandaloneDirective::Taskwait>(
-            "TASKWAIT"_tok >> many(Parser<OmpClause>{}))) ||
-    construct<OmpStandaloneDirective>(
-        construct<OmpStandaloneDirective::Taskyield>(
-            "TASKYIELD"_tok >> many(Parser<OmpClause>{}))))
+    construct<OmpClauseList>(many(maybe(","_tok) >> Parser<OmpClause>{})))
+
+// (variable | /common-block | array-sections)
+TYPE_PARSER(construct<OmpObjectList>(nonemptyList(Parser<OmpObject>{})))
 
+// Omp directives enclosing do loop
+TYPE_PARSER("DISTRIBUTE PARALLEL DO SIMD" >>
+        construct<OmpLoopDirective>(
+            construct<OmpLoopDirective::DistributeParallelDoSimd>()) ||
+    "DISTRIBUTE PARALLEL DO" >>
+        construct<OmpLoopDirective>(
+            construct<OmpLoopDirective::DistributeParallelDo>()) ||
+    "DISTRIBUTE SIMD" >> construct<OmpLoopDirective>(
+                             construct<OmpLoopDirective::DistributeSimd>()) ||
+    "DISTRIBUTE" >> construct<OmpLoopDirective>(
+                        construct<OmpLoopDirective::Distribute>()) ||
+    "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>()) ||
+    "TARGET PARALLEL DO" >>
+        construct<OmpLoopDirective>(
+            construct<OmpLoopDirective::TargetParallelDo>()) ||
+    "TARGET SIMD" >> construct<OmpLoopDirective>(
+                         construct<OmpLoopDirective::TargetSimd>()) ||
+    "TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD" >>
+        construct<OmpLoopDirective>(construct<
+            OmpLoopDirective::TargetTeamsDistributeParallelDoSimd>()) ||
+    "TARGET TEAMS DISTRIBUTE PARALLEL DO" >>
+        construct<OmpLoopDirective>(
+            construct<OmpLoopDirective::TargetTeamsDistributeParallelDo>()) ||
+    "TARGET TEAMS DISTRIBUTE SIMD" >>
+        construct<OmpLoopDirective>(
+            construct<OmpLoopDirective::TargetTeamsDistributeSimd>()) ||
+    "TARGET TEAMS DISTRIBUTE" >>
+        construct<OmpLoopDirective>(
+            construct<OmpLoopDirective::TargetTeamsDistribute>()) ||
+    "TASKLOOP SIMD" >> construct<OmpLoopDirective>(
+                           construct<OmpLoopDirective::TaskloopSimd>()) ||
+    "TASKLOOP" >>
+        construct<OmpLoopDirective>(construct<OmpLoopDirective::Taskloop>()) ||
+    "TEAMS DISTRIBUTE PARALLEL DO SIMD" >>
+        construct<OmpLoopDirective>(
+            construct<OmpLoopDirective::TeamsDistributeParallelDoSimd>()) ||
+    "TEAMS DISTRIBUTE PARALLEL DO" >>
+        construct<OmpLoopDirective>(
+            construct<OmpLoopDirective::TeamsDistributeParallelDo>()) ||
+    "TEAMS DISTRIBUTE SIMD" >>
+        construct<OmpLoopDirective>(
+            construct<OmpLoopDirective::TeamsDistributeSimd>()) ||
+    "TEAMS DISTRIBUTE" >> construct<OmpLoopDirective>(
+                              construct<OmpLoopDirective::TeamsDistribute>()))
+
+// Cancellation Point construct
+TYPE_PARSER("CANCELLATION POINT" >>
+    construct<OpenMPCancellationPointConstruct>(
+        "PARALLEL" >> pure(OmpCancelType::Type::Parallel) ||
+        "SECTIONS" >> pure(OmpCancelType::Type::Sections) ||
+        "DO" >> pure(OmpCancelType::Type::Do) ||
+        "TASKGROUP" >> pure(OmpCancelType::Type::Taskgroup)))
+
+// Cancel construct
 TYPE_PARSER(
-    construct<OpenMPLoopConstruct>(statement(Parser<OmpLoopDirective>{}),
-        Parser<DoConstruct>{}, maybe(Parser<OmpEndDirective>{})))
+    "CANCEL" >> construct<OpenMPCancelConstruct>(
+                    ("PARALLEL" >> pure(OmpCancelType::Type::Parallel) ||
+                        "SECTIONS" >> pure(OmpCancelType::Type::Sections) ||
+                        "DO" >> pure(OmpCancelType::Type::Do) ||
+                        "TASKGROUP" >> pure(OmpCancelType::Type::Taskgroup)),
+                    maybe("IF" >> parenthesized(scalarLogicalExpr))))
+
+// Flush construct
+TYPE_PARSER("FLUSH" >> construct<OpenMPFlushConstruct>(
+                           maybe(parenthesized(Parser<OmpObjectList>{}))))
+
+// Standalone directives
+TYPE_PARSER("TARGET ENTER DATA" >>
+        construct<OmpStandaloneDirective>(
+            construct<OmpStandaloneDirective::TargetEnterData>()) ||
+    "TARGET EXIT DATA" >>
+        construct<OmpStandaloneDirective>(
+            construct<OmpStandaloneDirective::TargetExitData>()) ||
+    "TARGET UPDATE" >> construct<OmpStandaloneDirective>(
+                           construct<OmpStandaloneDirective::TargetUpdate>()))
+
+// Directives enclosing structured-block
+TYPE_PARSER("MASTER" >>
+        construct<OmpBlockDirective>(construct<OmpBlockDirective::Master>()) ||
+    "ORDERED" >>
+        construct<OmpBlockDirective>(construct<OmpBlockDirective::Ordered>()) ||
+    "PARALLEL WORKSHARE" >>
+        construct<OmpBlockDirective>(
+            construct<OmpBlockDirective::ParallelWorkshare>()) ||
+    "PARALLEL" >> construct<OmpBlockDirective>(
+                      construct<OmpBlockDirective::Parallel>()) ||
+    "TARGET DATA" >> construct<OmpBlockDirective>(
+                         construct<OmpBlockDirective::TargetData>()) ||
+    "TARGET PARALLEL" >> construct<OmpBlockDirective>(
+                             construct<OmpBlockDirective::TargetParallel>()) ||
+    "TARGET TEAMS" >> construct<OmpBlockDirective>(
+                          construct<OmpBlockDirective::TargetTeams>()) ||
+    "TARGET" >>
+        construct<OmpBlockDirective>(construct<OmpBlockDirective::Target>()) ||
+    "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))))
+
+// Declare Reduction Construct
+TYPE_PARSER(construct<OpenMPDeclareReductionConstruct>(
+    "("_tok >> Parser<OmpReductionOperator>{} / ":"_tok,
+    nonemptyList(Parser<DeclarationTypeSpec>{}) / ":"_tok,
+    Parser<OmpReductionCombiner>{} / ")"_tok,
+    maybe(Parser<OmpReductionInitializerClause>{})))
+
+// declare-target-map-type
+TYPE_PARSER(construct<OmpDeclareTargetMapType>(
+    "LINK" >> pure(OmpDeclareTargetMapType::Type::Link) ||
+    "TO" >> pure(OmpDeclareTargetMapType::Type::To)))
+
+// Declarative directives
+TYPE_PARSER(construct<OpenMPDeclareTargetConstruct>(
+    construct<OpenMPDeclareTargetConstruct>(
+        construct<OpenMPDeclareTargetConstruct::WithClause>(
+            Parser<OmpDeclareTargetMapType>{},
+            parenthesized(Parser<OmpObjectList>{}))) ||
+    lookAhead(endOfLine) >>
+        construct<OpenMPDeclareTargetConstruct>(
+            construct<OpenMPDeclareTargetConstruct::Implicit>()) ||
+    construct<OpenMPDeclareTargetConstruct>(
+        parenthesized(construct<OpenMPDeclareTargetConstruct::WithExtendedList>(
+            Parser<OmpObjectList>{})))))
+
+TYPE_PARSER(construct<OmpReductionCombiner>(Parser<AssignmentStmt>{}) ||
+    construct<OmpReductionCombiner>(
+        construct<OmpReductionCombiner::FunctionCombiner>(
+            construct<Call>(Parser<ProcedureDesignator>{},
+                parenthesized(optionalList(actualArgSpec))))))
+
+// OMP END ATOMIC
+TYPE_PARSER(construct<OmpEndAtomic>("!$OMP "_sptok >> "END ATOMIC"_tok))
+
+// OMP [SEQ_CST] ATOMIC READ [SEQ_CST]
+TYPE_PARSER(construct<OmpAtomicRead>(
+    maybe(
+        "SEQ_CST"_tok >> construct<OmpAtomicRead::SeqCst1>() / maybe(","_tok)),
+    "READ" >> maybe(","_tok) >>
+        maybe("SEQ_CST"_tok >> 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)),
+    "CAPTURE" >> maybe(","_tok) >>
+        maybe("SEQ_CST"_tok >> 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)),
+    "UPDATE" >> maybe(","_tok) >>
+        maybe("SEQ_CST"_tok >> 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,
+    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)),
+    "WRITE" >> maybe(","_tok) >>
+        maybe("SEQ_CST"_tok >> construct<OmpAtomicWrite::SeqCst2>()) /
+            endOmpLine,
+    statement(assignmentStmt), maybe(Parser<OmpEndAtomic>{} / endOmpLine)))
+
+// Atomic Construct
+TYPE_PARSER("ATOMIC" >>
+    (construct<OpenMPAtomicConstruct>(Parser<OmpAtomicRead>{}) ||
+        construct<OpenMPAtomicConstruct>(Parser<OmpAtomicCapture>{}) ||
+        construct<OpenMPAtomicConstruct>(Parser<OmpAtomicWrite>{}) ||
+        construct<OpenMPAtomicConstruct>(Parser<OmpAtomicUpdate>{}) ||
+        construct<OpenMPAtomicConstruct>(Parser<OmpAtomic>{})))
+
+// OMP CRITICAL
+TYPE_PARSER("!$OMP "_sptok >> "END"_tok >> "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))
+
+// Declare Simd construct
+TYPE_PARSER(construct<OpenMPDeclareSimdConstruct>(
+    maybe(parenthesized(name)), Parser<OmpClauseList>{}))
+
+// Declarative construct & Threadprivate directive
+TYPE_PARSER(lookAhead(!"!$OMP END"_tok) >> "!$OMP "_tok >>
+    ("DECLARE REDUCTION" >>
+            construct<OpenMPDeclarativeConstruct>(
+                construct<OpenMPDeclarativeConstruct>(
+                    Parser<OpenMPDeclareReductionConstruct>{})) /
+                endOmpLine ||
+        "DECLARE SIMD" >> construct<OpenMPDeclarativeConstruct>(
+                              Parser<OpenMPDeclareSimdConstruct>{}) /
+                endOmpLine ||
+        "DECLARE TARGET" >> construct<OpenMPDeclarativeConstruct>(
+                                construct<OpenMPDeclarativeConstruct>(
+                                    Parser<OpenMPDeclareTargetConstruct>{})) /
+                endOmpLine ||
+        "THREADPRIVATE" >>
+            construct<OpenMPDeclarativeConstruct>(
+                construct<OpenMPDeclarativeConstruct::Threadprivate>(
+                    parenthesized(Parser<OmpObjectList>{})) /
+                endOmpLine)))
+
+// Block Construct
+TYPE_PARSER(construct<OpenMPBlockConstruct>(Parser<OmpBlockDirective>{},
+    Parser<OmpClauseList>{} / endOmpLine, block,
+    Parser<OmpEndBlockDirective>{} / endOmpLine))
 
 TYPE_PARSER(construct<OpenMPStandaloneConstruct>(
-    statement(Parser<OmpStandaloneDirective>{})))
+    Parser<OmpStandaloneDirective>{}, Parser<OmpClauseList>{} / endOmpLine))
+
+// OMP BARRIER
+TYPE_PARSER("BARRIER" >> construct<OpenMPBarrierConstruct>() / endOmpLine)
+
+// OMP TASKWAIT
+TYPE_PARSER("TASKWAIT" >> construct<OpenMPTaskwaitConstruct>() / endOmpLine)
+
+// OMP TASKYIELD
+TYPE_PARSER("TASKYIELD" >> construct<OpenMPTaskyieldConstruct>() / endOmpLine)
+
+// OMP SINGLE
+TYPE_PARSER(skipStuffBeforeStatement >> "!$OMP "_sptok >> "END"_tok >>
+    construct<OmpEndSingle>("SINGLE"_tok >> 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))
+
+// OMP WORKSHARE
+TYPE_PARSER("WORKSHARE" >>
+    construct<OpenMPWorkshareConstruct>(endOmpLine >> block,
+        Parser<OmpEndWorkshare>{} >>
+            maybe(construct<OmpNowait>("NOWAIT"_tok)) / endOmpLine))
+
+// OMP END DO SIMD [NOWAIT]
+TYPE_PARSER(construct<OmpEndDoSimd>(maybe(construct<OmpNowait>("NOWAIT"_tok))))
+
+// OMP END DO [NOWAIT]
+TYPE_PARSER(construct<OmpEndDo>(maybe(construct<OmpNowait>("NOWAIT"_tok))))
+
+// OMP END SECTIONS [NOWAIT]
+TYPE_PARSER(skipStuffBeforeStatement >> "!$OMP "_sptok >> "END"_tok >>
+    "SECTIONS"_tok >>
+    construct<OmpEndSections>(
+        maybe("NOWAIT"_tok >> construct<OmpNowait>()) / endOmpLine))
+
+// OMP SECTIONS
+TYPE_PARSER("SECTIONS" >>
+    construct<OpenMPSectionsConstruct>(
+        Parser<OmpClauseList>{} / endOmpLine, block, Parser<OmpEndSections>{}))
+
+// OMP END PARALLEL SECTIONS [NOWAIT]
+TYPE_PARSER(skipStuffBeforeStatement >> "!$OMP "_sptok >> "END"_tok >>
+    "PARALLEL SECTIONS"_tok >>
+    construct<OmpEndParallelSections>(
+        maybe("NOWAIT"_tok >> construct<OmpNowait>()) / endOmpLine))
+
+// OMP PARALLEL SECTIONS
+TYPE_PARSER("PARALLEL SECTIONS" >> construct<OpenMPParallelSectionsConstruct>(
+                                       Parser<OmpClauseList>{} / endOmpLine,
+                                       block, Parser<OmpEndParallelSections>{}))
 
 TYPE_CONTEXT_PARSER("OpenMP construct"_en_US,
-    beginOmpDirective >> (construct<OpenMPConstruct>(
-                              indirect(Parser<OpenMPStandaloneConstruct>{})) ||
-                             construct<OpenMPConstruct>(
-                                 indirect(Parser<OpenMPLoopConstruct>{}))))
+    skipStuffBeforeStatement >> "!$OMP "_sptok >> lookAhead(!"END"_tok) >>
+        (construct<OpenMPConstruct>(
+             indirect(Parser<OpenMPStandaloneConstruct>{})) ||
+            construct<OpenMPConstruct>(
+                indirect(Parser<OpenMPBarrierConstruct>{})) ||
+            construct<OpenMPConstruct>(
+                indirect(Parser<OpenMPTaskwaitConstruct>{})) ||
+            construct<OpenMPConstruct>(
+                indirect(Parser<OpenMPTaskyieldConstruct>{})) ||
+            construct<OpenMPConstruct>(
+                indirect(Parser<OpenMPSingleConstruct>{})) ||
+            construct<OpenMPConstruct>(
+                indirect(Parser<OpenMPSectionsConstruct>{})) ||
+            construct<OpenMPConstruct>(
+                indirect(Parser<OpenMPParallelSectionsConstruct>{})) ||
+            construct<OpenMPConstruct>(
+                indirect(Parser<OpenMPWorkshareConstruct>{})) ||
+            construct<OpenMPConstruct>(
+                indirect(Parser<OpenMPLoopConstruct>{})) ||
+            construct<OpenMPConstruct>(
+                indirect(Parser<OpenMPBlockConstruct>{})) ||
+            construct<OpenMPConstruct>(
+                indirect(Parser<OpenMPAtomicConstruct>{})) ||
+            construct<OpenMPConstruct>(
+                indirect(Parser<OpenMPCriticalConstruct>{})) ||
+            construct<OpenMPConstruct>(
+                indirect(Parser<OpenMPCancelConstruct>{})) ||
+            construct<OpenMPConstruct>(
+                indirect(Parser<OpenMPCancellationPointConstruct>{})) ||
+            construct<OpenMPConstruct>(
+                indirect(Parser<OpenMPFlushConstruct>{})) ||
+            "SECTION"_tok >> endOmpLine >>
+                construct<OpenMPConstruct>(construct<OmpSection>())))
+
+// END OMP Block directives
+TYPE_PARSER(skipStuffBeforeStatement >> "!$OMP "_sptok >> "END"_tok >>
+    construct<OmpEndBlockDirective>(indirect(Parser<OmpBlockDirective>{})))
+
+// END OMP Loop directives
+TYPE_PARSER(skipStuffBeforeStatement >> "!$OMP "_sptok >> "END"_tok >>
+    (construct<OpenMPEndLoopDirective>(
+         "DO SIMD" >> indirect(Parser<OmpEndDoSimd>{}) / endOmpLine) ||
+        construct<OpenMPEndLoopDirective>(
+            "DO" >> indirect(Parser<OmpEndDo>{}) / endOmpLine) ||
+        construct<OpenMPEndLoopDirective>(
+            indirect(Parser<OmpLoopDirective>{}) / endOmpLine)))
+
+TYPE_PARSER(construct<OpenMPLoopConstruct>(
+    Parser<OmpLoopDirective>{}, Parser<OmpClauseList>{} / endOmpLine))
 
 }  // namespace Fortran::parser
 #endif  // FORTRAN_PARSER_OPENMP_GRAMMAR_H_
index c481379..cb3e7c5 100644 (file)
@@ -672,7 +672,6 @@ void Walk(format::IntrinsicTypeDataEditDesc &x, M &mutator) {
     mutator.Post(x);
   }
 }
-
 template<typename V>
 void Walk(const OmpLinearClause::WithModifier &x, V &visitor) {
   if (visitor.Pre(x)) {
@@ -706,6 +705,35 @@ void Walk(OmpLinearClause::WithoutModifier &x, M &mutator) {
     mutator.Post(x);
   }
 }
+template<typename V>
+void Walk(const OpenMPDeclareTargetConstruct::WithClause &x, V &visitor) {
+  if (visitor.Pre(x)) {
+    Walk(x.maptype, visitor);
+    Walk(x.names, visitor);
+    visitor.Post(x);
+  }
+}
+template<typename M> void Walk(OpenMPDeclareTargetConstruct::WithClause &x, M &mutator) {
+  if (mutator.Pre(x)) {
+    Walk(x.maptype, mutator);
+    Walk(x.names, mutator);
+    mutator.Post(x);
+  }
+}
+template<typename V>
+void Walk(const OpenMPDeclareTargetConstruct::WithExtendedList &x, V &visitor) {
+  if (visitor.Pre(x)) {
+    Walk(x.names, visitor);
+    visitor.Post(x);
+  }
+}
+template<typename M>
+void Walk(OpenMPDeclareTargetConstruct::WithExtendedList &x, M &mutator) {
+  if (mutator.Pre(x)) {
+    Walk(x.names, mutator);
+    mutator.Post(x);
+  }
+}
 
 }  // namespace Fortran::parser
 #endif  // FORTRAN_PARSER_PARSE_TREE_VISITOR_H_
index d1eb62e..4596d12 100644 (file)
@@ -249,10 +249,9 @@ struct AssignStmt;
 struct AssignedGotoStmt;
 struct PauseStmt;
 struct OpenMPConstruct;
-struct OmpClause;
-struct OmpStandaloneDirective;
-struct OmpLoopDirective;
-struct OmpEndDirective;
+struct OpenMPDeclarativeConstruct;
+struct OmpBlockDirective;
+struct OpenMPEndLoopDirective;
 
 // Cooked character stream locations
 using Location = const char *;
@@ -260,7 +259,7 @@ using Location = const char *;
 // Implicit definitions of the Standard
 
 // R403 scalar-xyz -> xyz
-// These class template wrappers correspond to the Standard's modifiers
+// These template class wrappers correspond to the Standard's modifiers
 // scalar-xyz, constant-xzy, int-xzy, default-char-xyz, & logical-xyz.
 // TODO: Implement as wrappers instead, or maybe remove.
 template<typename A> struct Scalar {
@@ -365,7 +364,8 @@ struct SpecificationConstruct {
       Statement<common::Indirection<ProcedureDeclarationStmt>>,
       Statement<OtherSpecificationStmt>,
       Statement<common::Indirection<TypeDeclarationStmt>>,
-      common::Indirection<StructureDef>, common::Indirection<OpenMPConstruct>,
+      common::Indirection<StructureDef>,
+      common::Indirection<OpenMPDeclarativeConstruct>,
       common::Indirection<CompilerDirective>>
       u;
 };
@@ -403,7 +403,8 @@ struct DeclarationConstruct {
 // from the implicit part to the declaration constructs
 struct SpecificationPart {
   TUPLE_CLASS_BOILERPLATE(SpecificationPart);
-  std::tuple<std::list<Statement<common::Indirection<UseStmt>>>,
+  std::tuple<std::list<OpenMPDeclarativeConstruct>,
+      std::list<Statement<common::Indirection<UseStmt>>>,
       std::list<Statement<common::Indirection<ImportStmt>>>, ImplicitPart,
       std::list<DeclarationConstruct>>
       t;
@@ -487,7 +488,8 @@ struct ExecutableConstruct {
       common::Indirection<SelectTypeConstruct>,
       common::Indirection<WhereConstruct>, common::Indirection<ForallConstruct>,
       common::Indirection<CompilerDirective>,
-      common::Indirection<OpenMPConstruct>>
+      common::Indirection<OpenMPConstruct>,
+      common::Indirection<OpenMPEndLoopDirective>>
       u;
 };
 
@@ -829,7 +831,7 @@ struct LiteralConstant {
 };
 
 // R604 constant ->  literal-constant | named-constant
-// Renamed to dodge a clash with Constant<> class template.
+// Renamed to dodge a clash with Constant<> template class.
 struct ConstantValue {
   UNION_CLASS_BOILERPLATE(ConstantValue);
   std::variant<LiteralConstant, NamedConstant> u;
@@ -3236,18 +3238,27 @@ struct OmpDefaultClause {
   WRAPPER_CLASS_BOILERPLATE(OmpDefaultClause, Type);
 };
 
-// List -> variable-name | / common-block /
-struct OmpNameList {
-  TUPLE_CLASS_BOILERPLATE(OmpNameList);
+// variable-name | / common-block / | array-sections
+struct OmpObject {
+  TUPLE_CLASS_BOILERPLATE(OmpObject);
   ENUM_CLASS(Kind, Object, Common)
-  std::tuple<Kind, Name> t;
+  std::tuple<Kind, Designator> t;
+};
+
+WRAPPER_CLASS(OmpObjectList, std::list<OmpObject>);
+
+// map-type ->(TO | FROM | TOFROM | ALLOC | RELEASE | DELETE)
+struct OmpMapType {
+  TUPLE_CLASS_BOILERPLATE(OmpMapType);
+  EMPTY_CLASS(Always);
+  ENUM_CLASS(Type, To, From, Tofrom, Alloc, Release, Delete)
+  std::tuple<std::optional<Always>, Type> t;
 };
 
-// MAP((TO | FROM | TOFROM | ALLOC | RELEASE | DELETE) : list)
+// MAP ( map-type : list)
 struct OmpMapClause {
   TUPLE_CLASS_BOILERPLATE(OmpMapClause);
-  ENUM_CLASS(Type, To, From, Tofrom, Alloc, Release, Delete)
-  std::tuple<std::optional<Type>, std::list<Name>> t;
+  std::tuple<std::optional<OmpMapType>, OmpObjectList> t;
 };
 
 // schedule-modifier-type -> MONOTONIC | NONMONOTONIC | SIMD
@@ -3293,7 +3304,7 @@ struct OmpLinearModifier {
   WRAPPER_CLASS_BOILERPLATE(OmpLinearModifier, Type);
 };
 
-// LINEAR((modifier(list) | (list)) [: linear-step])
+// LINEAR((linear-modifier(list) | (list)) [: linear-step])
 struct OmpLinearClause {
   UNION_CLASS_BOILERPLATE(OmpLinearClause);
   struct WithModifier {
@@ -3316,13 +3327,11 @@ struct OmpLinearClause {
   std::variant<WithModifier, WithoutModifier> u;
 };
 
-// reduction-identifier -> "+", "-", "*", .AND., .OR., .EQV., .NEQV.,
-// MIN, MAX, IAND, IOR, IEOR
+// reduction-identifier -> Add, Subtract, Multiply, .and., .or., .eqv., .neqv.,
+// min, max, iand, ior, ieor
 struct OmpReductionOperator {
   UNION_CLASS_BOILERPLATE(OmpReductionOperator);
-  ENUM_CLASS(ProcedureOperator, MIN, MAX, IAND, IOR, IEOR)
-  ENUM_CLASS(BinaryOperator, Add, Subtract, Multiply, AND, OR, EQV, NEQV)
-  std::variant<ProcedureOperator, BinaryOperator> u;
+  std::variant<common::Indirection<DefinedOperator>, ProcedureDesignator> u;
 };
 
 // REDUCTION(reduction-identifier: list)
@@ -3331,16 +3340,13 @@ struct OmpReductionClause {
   std::tuple<OmpReductionOperator, std::list<Designator>> t;
 };
 
-// DEPEND(SOURCE | SINK: vec | DEPEND((IN | OUT | INOUT) : list)
-//  vec -> iterator_variable [ +/- d1], x2 [ +/- d2], ...
-//  d1 -> non-negative-constant
-//  list -> names | array-sections
-
+//  depend-vec-length -> +/- non-negative-constant
 struct OmpDependSinkVecLength {
   TUPLE_CLASS_BOILERPLATE(OmpDependSinkVecLength);
   std::tuple<common::Indirection<DefinedOperator>, ScalarIntConstantExpr> t;
 };
 
+//  depend-vec -> iterator_variable [+/- depend-vec-length]
 struct OmpDependSinkVec {
   TUPLE_CLASS_BOILERPLATE(OmpDependSinkVec);
   std::tuple<Name, std::optional<OmpDependSinkVecLength>> t;
@@ -3351,6 +3357,7 @@ struct OmpDependenceType {
   WRAPPER_CLASS_BOILERPLATE(OmpDependenceType, Type);
 };
 
+// DEPEND(SOURCE | SINK: vec | DEPEND((IN | OUT | INOUT) : list)
 struct OmpDependClause {
   UNION_CLASS_BOILERPLATE(OmpDependClause);
   EMPTY_CLASS(Source);
@@ -3362,6 +3369,9 @@ struct OmpDependClause {
   std::variant<Source, Sink, InOut> u;
 };
 
+// NOWAIT
+EMPTY_CLASS(OmpNowait);
+
 // OpenMP Clauses
 struct OmpClause {
   UNION_CLASS_BOILERPLATE(OmpClause);
@@ -3370,35 +3380,33 @@ struct OmpClause {
   EMPTY_CLASS(Mergeable);
   EMPTY_CLASS(Nogroup);
   EMPTY_CLASS(Notinbranch);
-  EMPTY_CLASS(Nowait);
   EMPTY_CLASS(Untied);
   WRAPPER_CLASS(Collapse, ScalarIntConstantExpr);
-  WRAPPER_CLASS(Copyin, std::list<OmpNameList>);
-  WRAPPER_CLASS(Copyprivate, std::list<OmpNameList>);
+  WRAPPER_CLASS(Copyin, OmpObjectList);
+  WRAPPER_CLASS(Copyprivate, OmpObjectList);
   WRAPPER_CLASS(Device, ScalarIntExpr);
   WRAPPER_CLASS(DistSchedule, ScalarIntExpr);
   WRAPPER_CLASS(Final, ScalarIntExpr);
-  WRAPPER_CLASS(Firstprivate, std::list<OmpNameList>);
+  WRAPPER_CLASS(Firstprivate, OmpObjectList);
   WRAPPER_CLASS(From, std::list<Designator>);
   WRAPPER_CLASS(Grainsize, ScalarIntExpr);
-  WRAPPER_CLASS(Lastprivate, std::list<OmpNameList>);
-  WRAPPER_CLASS(Link, std::list<Name>);
+  WRAPPER_CLASS(Lastprivate, OmpObjectList);
   WRAPPER_CLASS(NumTasks, ScalarIntExpr);
   WRAPPER_CLASS(NumTeams, ScalarIntExpr);
   WRAPPER_CLASS(NumThreads, ScalarIntExpr);
   WRAPPER_CLASS(Ordered, std::optional<ScalarIntConstantExpr>);
   WRAPPER_CLASS(Priority, ScalarIntExpr);
-  WRAPPER_CLASS(Private, std::list<OmpNameList>);
+  WRAPPER_CLASS(Private, OmpObjectList);
   WRAPPER_CLASS(Safelen, ScalarIntConstantExpr);
-  WRAPPER_CLASS(Shared, std::list<OmpNameList>);
+  WRAPPER_CLASS(Shared, OmpObjectList);
   WRAPPER_CLASS(Simdlen, ScalarIntConstantExpr);
   WRAPPER_CLASS(ThreadLimit, ScalarIntExpr);
   WRAPPER_CLASS(To, std::list<Designator>);
   WRAPPER_CLASS(Uniform, std::list<Name>);
   WRAPPER_CLASS(UseDevicePtr, std::list<Name>);
-  std::variant<Defaultmap, Inbranch, Mergeable, Nogroup, Notinbranch, Nowait,
+  std::variant<Defaultmap, Inbranch, Mergeable, Nogroup, Notinbranch, OmpNowait,
       Untied, Collapse, Copyin, Copyprivate, Device, DistSchedule, Final,
-      Firstprivate, From, Grainsize, Lastprivate, Link, NumTasks, NumTeams,
+      Firstprivate, From, Grainsize, Lastprivate, NumTasks, NumTeams,
       NumThreads, Ordered, Priority, Private, Safelen, Shared, Simdlen,
       ThreadLimit, To, Uniform, UseDevicePtr, OmpAlignedClause,
       OmpDefaultClause, OmpDependClause, OmpIfClause, OmpLinearClause,
@@ -3406,32 +3414,202 @@ struct OmpClause {
       u;
 };
 
+WRAPPER_CLASS(OmpClauseList, std::list<OmpClause>);
+
+// SECTIONS, PARALLEL SECTIONS
+WRAPPER_CLASS(OmpEndSections, std::optional<OmpNowait>);
+WRAPPER_CLASS(OmpEndParallelSections, std::optional<OmpNowait>);
+EMPTY_CLASS(OmpSection);
+
+struct OpenMPSectionsConstruct {
+  TUPLE_CLASS_BOILERPLATE(OpenMPSectionsConstruct);
+  std::tuple<OmpClauseList, Block, OmpEndSections> t;
+};
+
+struct OpenMPParallelSectionsConstruct {
+  TUPLE_CLASS_BOILERPLATE(OpenMPParallelSectionsConstruct);
+  std::tuple<OmpClauseList, Block, OmpEndParallelSections> t;
+};
+
+// WORKSHARE
+EMPTY_CLASS(OmpEndWorkshare);
+struct OpenMPWorkshareConstruct {
+  TUPLE_CLASS_BOILERPLATE(OpenMPWorkshareConstruct);
+  std::tuple<Block, std::optional<OmpNowait>> t;
+};
+
+// SINGLE
+WRAPPER_CLASS(OmpEndSingle, OmpClauseList);
+struct OpenMPSingleConstruct {
+  TUPLE_CLASS_BOILERPLATE(OpenMPSingleConstruct);
+  std::tuple<OmpClauseList, Block, OmpEndSingle> t;
+};
+
+// OpenMP directive enclosing block
+struct OmpBlockDirective {
+  UNION_CLASS_BOILERPLATE(OmpBlockDirective);
+  EMPTY_CLASS(Master);
+  EMPTY_CLASS(Ordered);
+  EMPTY_CLASS(ParallelWorkshare);
+  EMPTY_CLASS(Parallel);
+  EMPTY_CLASS(TargetData);
+  EMPTY_CLASS(TargetParallel);
+  EMPTY_CLASS(TargetTeams);
+  EMPTY_CLASS(Target);
+  EMPTY_CLASS(Taskgroup);
+  EMPTY_CLASS(Task);
+  EMPTY_CLASS(Teams);
+  std::variant<Master, Ordered, ParallelWorkshare, Parallel, TargetData,
+      TargetParallel, TargetTeams, Target, Taskgroup, Task, Teams>
+      u;
+};
+
+struct OmpDeclareTargetMapType {
+  ENUM_CLASS(Type, Link, To)
+  WRAPPER_CLASS_BOILERPLATE(OmpDeclareTargetMapType, Type);
+};
+
+struct OpenMPDeclareTargetConstruct {
+  UNION_CLASS_BOILERPLATE(OpenMPDeclareTargetConstruct);
+  struct WithClause {
+    BOILERPLATE(WithClause);
+    WithClause(OmpDeclareTargetMapType &&m, OmpObjectList &&n)
+      : maptype(std::move(m)), names(std::move(n)) {}
+    OmpDeclareTargetMapType maptype;
+    OmpObjectList names;
+  };
+  struct WithExtendedList {
+    BOILERPLATE(WithExtendedList);
+    WithExtendedList(OmpObjectList &&n) : names(std::move(n)) {}
+    OmpObjectList names;
+  };
+  EMPTY_CLASS(Implicit);
+  std::variant<WithClause, WithExtendedList, Implicit> u;
+};
+
+struct OmpReductionCombiner {
+  UNION_CLASS_BOILERPLATE(OmpReductionCombiner);
+  WRAPPER_CLASS(FunctionCombiner, Call);
+  std::variant<AssignmentStmt, FunctionCombiner> u;
+};
+
+WRAPPER_CLASS(OmpReductionInitializerClause, common::Indirection<Expr>);
+
+struct OpenMPDeclareReductionConstruct {
+  TUPLE_CLASS_BOILERPLATE(OpenMPDeclareReductionConstruct);
+  std::tuple<OmpReductionOperator, std::list<DeclarationTypeSpec>,
+      OmpReductionCombiner, std::optional<OmpReductionInitializerClause>>
+      t;
+};
+
+struct OpenMPDeclareSimdConstruct {
+  TUPLE_CLASS_BOILERPLATE(OpenMPDeclareSimdConstruct);
+  std::tuple<std::optional<Name>, OmpClauseList> t;
+};
+
+struct OpenMPDeclarativeConstruct {
+  UNION_CLASS_BOILERPLATE(OpenMPDeclarativeConstruct);
+  WRAPPER_CLASS(Threadprivate, OmpObjectList);
+  std::variant<OpenMPDeclareReductionConstruct, OpenMPDeclareSimdConstruct,
+      OpenMPDeclareTargetConstruct, Threadprivate>
+      u;
+};
+
+// CRITICAL [Name] <block> END CRITICAL [Name]
+WRAPPER_CLASS(OmpEndCritical, std::optional<Name>);
+struct OpenMPCriticalConstruct {
+  TUPLE_CLASS_BOILERPLATE(OpenMPCriticalConstruct);
+  WRAPPER_CLASS(Hint, ConstantExpr);
+  std::tuple<std::optional<Name>, std::optional<Hint>, Block, OmpEndCritical> t;
+};
+
+// END ATOMIC
+EMPTY_CLASS(OmpEndAtomic);
+
+// ATOMIC READ
+struct OmpAtomicRead {
+  TUPLE_CLASS_BOILERPLATE(OmpAtomicRead);
+  EMPTY_CLASS(SeqCst1);
+  EMPTY_CLASS(SeqCst2);
+  std::tuple<std::optional<SeqCst1>, std::optional<SeqCst2>,
+      Statement<AssignmentStmt>, std::optional<OmpEndAtomic>>
+      t;
+};
+
+// ATOMIC WRITE
+struct OmpAtomicWrite {
+  TUPLE_CLASS_BOILERPLATE(OmpAtomicWrite);
+  EMPTY_CLASS(SeqCst1);
+  EMPTY_CLASS(SeqCst2);
+  std::tuple<std::optional<SeqCst1>, std::optional<SeqCst2>,
+      Statement<AssignmentStmt>, std::optional<OmpEndAtomic>>
+      t;
+};
+
+// ATOMIC UPDATE
+struct OmpAtomicUpdate {
+  TUPLE_CLASS_BOILERPLATE(OmpAtomicUpdate);
+  EMPTY_CLASS(SeqCst1);
+  EMPTY_CLASS(SeqCst2);
+  std::tuple<std::optional<SeqCst1>, std::optional<SeqCst2>,
+      Statement<AssignmentStmt>, std::optional<OmpEndAtomic>>
+      t;
+};
+
+// ATOMIC CAPTURE
+struct OmpAtomicCapture {
+  TUPLE_CLASS_BOILERPLATE(OmpAtomicCapture);
+  EMPTY_CLASS(SeqCst1);
+  EMPTY_CLASS(SeqCst2);
+  WRAPPER_CLASS(Stmt1, Statement<AssignmentStmt>);
+  WRAPPER_CLASS(Stmt2, Statement<AssignmentStmt>);
+  std::tuple<std::optional<SeqCst1>, std::optional<SeqCst2>, Stmt1, Stmt2,
+      OmpEndAtomic>
+      t;
+};
+
+// ATOMIC
+struct OmpAtomic {
+  TUPLE_CLASS_BOILERPLATE(OmpAtomic);
+  EMPTY_CLASS(SeqCst);
+  std::tuple<std::optional<SeqCst>, Statement<AssignmentStmt>,
+      std::optional<OmpEndAtomic>>
+      t;
+};
+
+struct OpenMPAtomicConstruct {
+  UNION_CLASS_BOILERPLATE(OpenMPAtomicConstruct);
+  std::variant<OmpAtomicRead, OmpAtomicWrite, OmpAtomicCapture, OmpAtomicUpdate,
+      OmpAtomic>
+      u;
+};
+
 struct OmpLoopDirective {
   UNION_CLASS_BOILERPLATE(OmpLoopDirective);
-  WRAPPER_CLASS(DistributeParallelDoSimd, std::list<OmpClause>);
-  WRAPPER_CLASS(DistributeParallelDo, std::list<OmpClause>);
-  WRAPPER_CLASS(DistributeSimd, std::list<OmpClause>);
-  WRAPPER_CLASS(Distribute, std::list<OmpClause>);
-  WRAPPER_CLASS(DoSimd, std::list<OmpClause>);
-  WRAPPER_CLASS(Do, std::list<OmpClause>);
-  WRAPPER_CLASS(ParallelDoSimd, std::list<OmpClause>);
-  WRAPPER_CLASS(ParallelDo, std::list<OmpClause>);
-  WRAPPER_CLASS(Simd, std::list<OmpClause>);
-  WRAPPER_CLASS(TargetParallelDoSimd, std::list<OmpClause>);
-  WRAPPER_CLASS(TargetParallelDo, std::list<OmpClause>);
-  WRAPPER_CLASS(TargetTeamsDistributeParallelDoSimd, std::list<OmpClause>);
-  WRAPPER_CLASS(TargetTeamsDistributeParallelDo, std::list<OmpClause>);
-  WRAPPER_CLASS(TargetTeamsDistributeSimd, std::list<OmpClause>);
-  WRAPPER_CLASS(TargetTeamsDistribute, std::list<OmpClause>);
-  WRAPPER_CLASS(TargetSimd, std::list<OmpClause>);
-  WRAPPER_CLASS(TaskloopSimd, std::list<OmpClause>);
-  WRAPPER_CLASS(Taskloop, std::list<OmpClause>);
-  WRAPPER_CLASS(TeamsDistributeParallelDoSimd, std::list<OmpClause>);
-  WRAPPER_CLASS(TeamsDistributeParallelDo, std::list<OmpClause>);
-  WRAPPER_CLASS(TeamsDistributeSimd, std::list<OmpClause>);
-  WRAPPER_CLASS(TeamsDistribute, std::list<OmpClause>);
+  EMPTY_CLASS(DistributeParallelDoSimd);
+  EMPTY_CLASS(DistributeParallelDo);
+  EMPTY_CLASS(DistributeSimd);
+  EMPTY_CLASS(Distribute);
+  EMPTY_CLASS(ParallelDoSimd);
+  EMPTY_CLASS(ParallelDo);
+  EMPTY_CLASS(Do);
+  EMPTY_CLASS(DoSimd);
+  EMPTY_CLASS(Simd);
+  EMPTY_CLASS(TargetParallelDoSimd);
+  EMPTY_CLASS(TargetParallelDo);
+  EMPTY_CLASS(TargetTeamsDistributeParallelDoSimd);
+  EMPTY_CLASS(TargetTeamsDistributeParallelDo);
+  EMPTY_CLASS(TargetTeamsDistributeSimd);
+  EMPTY_CLASS(TargetTeamsDistribute);
+  EMPTY_CLASS(TargetSimd);
+  EMPTY_CLASS(TaskloopSimd);
+  EMPTY_CLASS(Taskloop);
+  EMPTY_CLASS(TeamsDistributeParallelDoSimd);
+  EMPTY_CLASS(TeamsDistributeParallelDo);
+  EMPTY_CLASS(TeamsDistributeSimd);
+  EMPTY_CLASS(TeamsDistribute);
   std::variant<DistributeParallelDoSimd, DistributeParallelDo, DistributeSimd,
-      Distribute, DoSimd, Do, ParallelDoSimd, ParallelDo, Simd,
+      Distribute, ParallelDoSimd, ParallelDo, Do, DoSimd, Simd,
       TargetParallelDoSimd, TargetParallelDo,
       TargetTeamsDistributeParallelDoSimd, TargetTeamsDistributeParallelDo,
       TargetTeamsDistributeSimd, TargetTeamsDistribute, TargetSimd,
@@ -3440,40 +3618,81 @@ struct OmpLoopDirective {
       u;
 };
 
+// Cancel/Cancellation type
+struct OmpCancelType {
+  ENUM_CLASS(Type, Parallel, Sections, Do, Taskgroup)
+  WRAPPER_CLASS_BOILERPLATE(OmpCancelType, Type);
+};
+
+// CANCELLATION POINT
+WRAPPER_CLASS(OpenMPCancellationPointConstruct, OmpCancelType);
+
+// CANCEL
+struct OpenMPCancelConstruct {
+  TUPLE_CLASS_BOILERPLATE(OpenMPCancelConstruct);
+  WRAPPER_CLASS(If, ScalarLogicalExpr);
+  std::tuple<OmpCancelType, std::optional<If>> t;
+};
+
+// FLUSH
+WRAPPER_CLASS(OpenMPFlushConstruct, std::optional<OmpObjectList>);
+
+// Standalone constructs
 struct OmpStandaloneDirective {
   UNION_CLASS_BOILERPLATE(OmpStandaloneDirective);
-  WRAPPER_CLASS(Barrier, std::list<OmpClause>);
-  WRAPPER_CLASS(CancellationPoint, std::list<OmpClause>);
-  WRAPPER_CLASS(Cancel, std::list<OmpClause>);
-  WRAPPER_CLASS(Flush, std::list<OmpClause>);
-  WRAPPER_CLASS(TargetEnterData, std::list<OmpClause>);
-  WRAPPER_CLASS(TargetExitData, std::list<OmpClause>);
-  WRAPPER_CLASS(TargetUpdate, std::list<OmpClause>);
-  WRAPPER_CLASS(Taskwait, std::list<OmpClause>);
-  WRAPPER_CLASS(Taskyield, std::list<OmpClause>);
-  std::variant<Barrier, CancellationPoint, Cancel, Flush, TargetEnterData,
-      TargetExitData, TargetUpdate, Taskwait, Taskyield>
+  EMPTY_CLASS(TargetEnterData);
+  EMPTY_CLASS(TargetExitData);
+  EMPTY_CLASS(TargetUpdate);
+  std::variant<TargetEnterData, TargetExitData, TargetUpdate> u;
+};
+
+EMPTY_CLASS(OpenMPTaskyieldConstruct);
+EMPTY_CLASS(OpenMPTaskwaitConstruct);
+EMPTY_CLASS(OpenMPBarrierConstruct);
+WRAPPER_CLASS(OmpEndBlockDirective, common::Indirection<OmpBlockDirective>);
+
+// DO / DO SIMD
+WRAPPER_CLASS(OmpEndDoSimd, std::optional<OmpNowait>);
+WRAPPER_CLASS(OmpEndDo, std::optional<OmpNowait>);
+struct OpenMPEndLoopDirective {
+  UNION_CLASS_BOILERPLATE(OpenMPEndLoopDirective);
+  std::variant<common::Indirection<OmpEndDoSimd>, common::Indirection<OmpEndDo>,
+      common::Indirection<OmpLoopDirective>>
       u;
 };
 
-struct OmpEndDirective {
-  UNION_CLASS_BOILERPLATE(OmpEndDirective);
-  std::variant<OmpLoopDirective> u;
+struct OpenMPBlockConstruct {
+  TUPLE_CLASS_BOILERPLATE(OpenMPBlockConstruct);
+  std::tuple<OmpBlockDirective, OmpClauseList, Block, OmpEndBlockDirective> t;
 };
 
 struct OpenMPLoopConstruct {
   TUPLE_CLASS_BOILERPLATE(OpenMPLoopConstruct);
-  std::tuple<Statement<OmpLoopDirective>, DoConstruct,
-      std::optional<OmpEndDirective>>
-      t;
+  std::tuple<OmpLoopDirective, OmpClauseList> t;
 };
 
-WRAPPER_CLASS(OpenMPStandaloneConstruct, Statement<OmpStandaloneDirective>);
+struct OpenMPStandaloneConstruct {
+  TUPLE_CLASS_BOILERPLATE(OpenMPStandaloneConstruct);
+  std::tuple<OmpStandaloneDirective, OmpClauseList> t;
+};
 
 struct OpenMPConstruct {
   UNION_CLASS_BOILERPLATE(OpenMPConstruct);
   std::variant<common::Indirection<OpenMPStandaloneConstruct>,
-      common::Indirection<OpenMPLoopConstruct>>
+      common::Indirection<OpenMPBarrierConstruct>,
+      common::Indirection<OpenMPTaskwaitConstruct>,
+      common::Indirection<OpenMPTaskyieldConstruct>,
+      common::Indirection<OpenMPSingleConstruct>,
+      common::Indirection<OpenMPSectionsConstruct>,
+      common::Indirection<OpenMPParallelSectionsConstruct>,
+      common::Indirection<OpenMPWorkshareConstruct>,
+      common::Indirection<OpenMPLoopConstruct>,
+      common::Indirection<OpenMPBlockConstruct>,
+      common::Indirection<OpenMPCancellationPointConstruct>,
+      common::Indirection<OpenMPCancelConstruct>,
+      common::Indirection<OpenMPFlushConstruct>,
+      common::Indirection<OpenMPAtomicConstruct>,
+      common::Indirection<OpenMPCriticalConstruct>, OmpSection>
       u;
 };
 
index 8b07373..d65602e 100644 (file)
@@ -77,7 +77,8 @@ constexpr auto stmtErrorRecoveryStart{ignoredStatementPrefix};
 constexpr auto skipBadLine{SkipPast<'\n'>{} >> construct<ErrorRecovery>()};
 constexpr auto executionPartErrorRecovery{stmtErrorRecoveryStart >>
     !"END"_tok >> !"CONTAINS"_tok >> !"ELSE"_tok >> !"CASE"_tok >>
-    !"TYPE IS"_tok >> !"CLASS"_tok >> !"RANK"_tok >> skipBadLine};
+    !"TYPE IS"_tok >> !"CLASS"_tok >> !"RANK"_tok >>
+    !("!$OMP "_sptok >> "END"_tok) >> skipBadLine};
 
 }  // namespace Fortran::parser
 #endif  // FORTRAN_PARSER_STMT_PARSER_H_
index fd3cae1..85a42cf 100644 (file)
@@ -143,6 +143,8 @@ constexpr Parser<EntryStmt> entryStmt;  // R1541
 constexpr Parser<ContainsStmt> containsStmt;  // R1543
 constexpr Parser<CompilerDirective> compilerDirective;
 constexpr Parser<OpenMPConstruct> openmpConstruct;
+constexpr Parser<OpenMPDeclarativeConstruct> openmpDeclarativeConstruct;
+constexpr Parser<OpenMPEndLoopDirective> openmpEndLoopDirective;
 
 }  // namespace Fortran::parser
 #endif  // FORTRAN_PARSER_TYPE_PARSERS_H_
index 6bc5a64..c94c8e8 100644 (file)
@@ -1673,15 +1673,16 @@ public:
     Walk(std::get<Name>(x.t));
   }
   // OpenMP Clauses & Directives
-  void Unparse(const OmpNameList &x) {
-    bool isCommon{
-        std::get<OmpNameList::Kind>(x.t) == OmpNameList::Kind::Common};
+  void Unparse(const OmpObject &x) {
+    bool isCommon{std::get<OmpObject::Kind>(x.t) == OmpObject::Kind::Common};
     const char *slash{isCommon ? "/" : ""};
-    Put(slash), Walk(std::get<Name>(x.t)), Put(slash);
+    Put(slash), Walk(std::get<Designator>(x.t)), Put(slash);
   }
+  void Unparse(const OmpMapType::Always &x) { Word("ALWAYS,"); }
   void Unparse(const OmpMapClause &x) {
-    Word(" MAP("), Walk(std::get<std::optional<OmpMapClause::Type>>(x.t), ":");
-    Walk(std::get<std::list<Name>>(x.t), ", ");
+    Word("MAP(");
+    Walk(std::get<std::optional<OmpMapType>>(x.t), ":");
+    Walk(std::get<OmpObjectList>(x.t));
     Put(") ");
   }
   void Unparse(const OmpScheduleModifier &x) {
@@ -1689,48 +1690,36 @@ public:
     Walk(",", std::get<std::optional<OmpScheduleModifier::Modifier2>>(x.t));
   }
   void Unparse(const OmpScheduleClause &x) {
-    Word(" SCHEDULE(");
+    Word("SCHEDULE(");
     Walk(std::get<std::optional<OmpScheduleModifier>>(x.t));
     Walk(std::get<OmpScheduleClause::ScheduleType>(x.t));
     Walk(",", std::get<std::optional<ScalarIntExpr>>(x.t));
     Put(")");
   }
   void Unparse(const OmpAlignedClause &x) {
-    Word(" ALIGNED("), Walk(std::get<std::list<Name>>(x.t), ",");
+    Word("ALIGNED("), Walk(std::get<std::list<Name>>(x.t), ",");
     Walk(std::get<std::optional<ScalarIntConstantExpr>>(x.t));
     Put(") ");
   }
   void Unparse(const OmpIfClause &x) {
-    Word(" IF("),
+    Word("IF("),
         Walk(std::get<std::optional<OmpIfClause::DirectiveNameModifier>>(x.t),
             ":");
     Walk(std::get<ScalarLogicalExpr>(x.t));
     Put(") ");
   }
   void Unparse(const OmpLinearClause::WithoutModifier &x) {
-    Word(" LINEAR("), Walk(x.names, ", ");
+    Word("LINEAR("), Walk(x.names, ", ");
     Walk(":", x.step);
     Put(")");
   }
   void Unparse(const OmpLinearClause::WithModifier &x) {
-    Word(" LINEAR("), Walk(x.modifier), Put("("), Walk(x.names, ","), Put(")");
+    Word("LINEAR("), Walk(x.modifier), Put("("), Walk(x.names, ","), Put(")");
     Walk(":", x.step);
     Put(")");
   }
-  void Unparse(const OmpReductionOperator::BinaryOperator &x) {
-    switch (x) {
-    case OmpReductionOperator::BinaryOperator::Add: Put("+"); break;
-    case OmpReductionOperator::BinaryOperator::Subtract: Put("-"); break;
-    case OmpReductionOperator::BinaryOperator::Multiply: Put("*"); break;
-    case OmpReductionOperator::BinaryOperator::AND: Word(".AND."); break;
-    case OmpReductionOperator::BinaryOperator::OR: Word(".OR."); break;
-    case OmpReductionOperator::BinaryOperator::EQV: Word(".EQV."); break;
-    case OmpReductionOperator::BinaryOperator::NEQV: Word(".NEQV."); break;
-    default: break;
-    }
-  }
   void Unparse(const OmpReductionClause &x) {
-    Word(" REDUCTION(");
+    Word("REDUCTION(");
     Walk(std::get<OmpReductionOperator>(x.t));
     Put(":");
     Walk(std::get<std::list<Designator>>(x.t), ",");
@@ -1745,35 +1734,48 @@ public:
     Walk(std::get<std::optional<OmpDependSinkVecLength>>(x.t));
   }
   void Unparse(const OmpDependClause::InOut &x) {
+    Put("(");
     Walk(std::get<OmpDependenceType>(x.t));
     Put(":");
     Walk(std::get<std::list<Designator>>(x.t), ",");
+    Put(")");
   }
-  void Unparse(const OmpDependClause &x) {
-    std::visit(common::visitors{[&](const OmpDependClause::Source &y) {
-                                  Word("DEPEND(SOURCE)");
-                                },
-                   [&](const OmpDependClause::Sink &y) {
-                     Word("DEPEND(SINK:");
-                     Walk(y.v);
-                     Put(")");
-                   },
-                   [&](const OmpDependClause::InOut &y) {
-                     Word("DEPEND(");
-                     Walk(y.t);
-                     Put(")");
-                   }},
+  bool Pre(const OmpDependClause &x) {
+    return std::visit(common::visitors{[&](const OmpDependClause::Source &y) {
+                                         Word("DEPEND(SOURCE)");
+                                         return false;
+                                       },
+                          [&](const OmpDependClause::Sink &y) {
+                            Word("DEPEND(SINK:");
+                            Walk(y.v);
+                            Put(")");
+                            return false;
+                          },
+                          [&](const OmpDependClause::InOut &y) {
+                            Word("DEPEND");
+                            return true;
+                          }},
         x.u);
   }
+  bool Pre(const OmpDefaultClause &x) {
+    Word("DEFAULT(");
+    return true;
+  }
+  void Post(const OmpDefaultClause &x) { Put(")"); }
+  bool Pre(const OmpProcBindClause &x) {
+    Word("PROC_BIND(");
+    return true;
+  }
+  void Post(const OmpProcBindClause &x) { Put(")"); }
   void Before(const OmpClause::Defaultmap &x) {
-    Word(" DEFAULTMAP(TOFROM:SCALAR)");
+    Word("DEFAULTMAP(TOFROM:SCALAR)");
   }
   void Before(const OmpClause::Inbranch &x) { Word("INBRANCH"); }
   void Before(const OmpClause::Mergeable &x) { Word("MERGEABLE"); }
   void Before(const OmpClause::Nogroup &x) { Word("NOGROUP"); }
   void Before(const OmpClause::Notinbranch &x) { Word("NOTINBRANCH"); }
-  void Before(const OmpClause::Nowait &x) { Word("NOWAIT"); }
   void Before(const OmpClause::Untied &x) { Word("UNTIED"); }
+  void Unparse(const OmpNowait &) { Word("NOWAIT"); }
   void Unparse(const OmpClause::Collapse &x) {
     Word("COLLAPSE(");
     Walk(x.v);
@@ -1781,12 +1783,12 @@ public:
   }
   void Unparse(const OmpClause::Copyin &x) {
     Word("COPYIN(");
-    Walk(x.v, ",");
+    Walk(x.v);
     Put(")");
   }
   void Unparse(const OmpClause::Copyprivate &x) {
     Word("COPYPRIVATE(");
-    Walk(x.v, ",");
+    Walk(x.v);
     Put(")");
   }
   void Unparse(const OmpClause::Device &x) {
@@ -1806,7 +1808,7 @@ public:
   }
   void Unparse(const OmpClause::Firstprivate &x) {
     Word("FIRSTPRIVATE(");
-    Walk(x.v, ",");
+    Walk(x.v);
     Put(")");
   }
   void Unparse(const OmpClause::From &x) {
@@ -1821,12 +1823,7 @@ public:
   }
   void Unparse(const OmpClause::Lastprivate &x) {
     Word("LASTPRIVATE(");
-    Walk(x.v, ",");
-    Put(")");
-  }
-  void Unparse(const OmpClause::Link &x) {
-    Word("LINK(");
-    Walk(x.v, ",");
+    Walk(x.v);
     Put(")");
   }
   void Unparse(const OmpClause::NumTasks &x) {
@@ -1855,7 +1852,7 @@ public:
   }
   void Unparse(const OmpClause::Private &x) {
     Word("PRIVATE(");
-    Walk(x.v, ",");
+    Walk(x.v);
     Put(")");
   }
   void Unparse(const OmpClause::Safelen &x) {
@@ -1875,7 +1872,7 @@ public:
   }
   void Unparse(const OmpClause::Shared &x) {
     Word("SHARED(");
-    Walk(x.v, ",");
+    Walk(x.v);
     Put(")");
   }
   void Unparse(const OmpClause::To &x) {
@@ -1896,159 +1893,401 @@ public:
   void Unparse(const OmpLoopDirective &x) {
     std::visit(
         common::visitors{
-            [&](const OmpLoopDirective::DistributeParallelDoSimd &y) {
+            [&](const OmpLoopDirective::DistributeParallelDoSimd &) {
               Word("DISTRIBUTE PARALLEL DO SIMD ");
-              Walk(y.v, " ");
             },
-            [&](const OmpLoopDirective::DistributeParallelDo &y) {
+            [&](const OmpLoopDirective::DistributeParallelDo &) {
               Word("DISTRIBUTE PARALLEL DO ");
-              Walk(y.v, " ");
             },
-            [&](const OmpLoopDirective::DistributeSimd &y) {
+            [&](const OmpLoopDirective::DistributeSimd &) {
               Word("DISTRIBUTE SIMD ");
-              Walk(y.v, " ");
-            },
-            [&](const OmpLoopDirective::Distribute &y) {
-              Word("DISTRIBUTE ");
-              Walk(y.v, " ");
-            },
-            [&](const OmpLoopDirective::DoSimd &y) {
-              Word("DO SIMD ");
-              Walk(y.v, " ");
-            },
-            [&](const OmpLoopDirective::Do &y) {
-              Word("DO ");
-              Walk(y.v, " ");
             },
-            [&](const OmpLoopDirective::ParallelDoSimd &y) {
+            [&](const OmpLoopDirective::Distribute &) { Word("DISTRIBUTE "); },
+            [&](const OmpLoopDirective::ParallelDoSimd &) {
               Word("PARALLEL DO SIMD ");
-              Walk(y.v, " ");
             },
-            [&](const OmpLoopDirective::ParallelDo &y) {
-              Word("PARALLEL DO ");
-              Walk(y.v, " ");
-            },
-            [&](const OmpLoopDirective::Simd &y) {
-              Word("SIMD ");
-              Walk(y.v, " ");
-            },
-            [&](const OmpLoopDirective::TargetParallelDoSimd &y) {
+            [&](const OmpLoopDirective::ParallelDo &) { Word("PARALLEL DO "); },
+            [&](const OmpLoopDirective::Do &) { Word("DO "); },
+            [&](const OmpLoopDirective::DoSimd &) { Word("Do SIMD "); },
+            [&](const OmpLoopDirective::Simd &) { Word("SIMD "); },
+            [&](const OmpLoopDirective::TargetParallelDoSimd &) {
               Word("TARGET PARALLEL DO SIMD ");
-              Walk(y.v, " ");
             },
-            [&](const OmpLoopDirective::TargetParallelDo &y) {
+            [&](const OmpLoopDirective::TargetParallelDo &) {
               Word("TARGET PARALLEL DO ");
-              Walk(y.v, " ");
             },
-            [&](const OmpLoopDirective::TargetTeamsDistributeParallelDoSimd
-                    &y) {
+            [&](const OmpLoopDirective::TargetTeamsDistributeParallelDoSimd &) {
               Word("TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD ");
-              Walk(y.v, " ");
             },
-            [&](const OmpLoopDirective::TargetTeamsDistributeParallelDo &y) {
+            [&](const OmpLoopDirective::TargetTeamsDistributeParallelDo &) {
               Word("TARGET TEAMS DISTRIBUTE PARALLEL DO ");
-              Walk(y.v, " ");
             },
-            [&](const OmpLoopDirective::TargetTeamsDistributeSimd &y) {
+            [&](const OmpLoopDirective::TargetTeamsDistributeSimd &) {
               Word("TARGET TEAMS DISTRIBUTE SIMD ");
-              Walk(y.v, " ");
             },
-            [&](const OmpLoopDirective::TargetTeamsDistribute &y) {
+            [&](const OmpLoopDirective::TargetTeamsDistribute &) {
               Word("TARGET TEAMS DISTRIBUTE ");
-              Walk(y.v, " ");
-            },
-            [&](const OmpLoopDirective::TargetSimd &y) {
-              Word("TARGET SIMD ");
-              Walk(y.v, " ");
             },
-            [&](const OmpLoopDirective::TaskloopSimd &y) {
+            [&](const OmpLoopDirective::TargetSimd &) { Word("TARGET SIMD "); },
+            [&](const OmpLoopDirective::TaskloopSimd &) {
               Word("TASKLOOP SIMD ");
-              Walk(y.v, " ");
             },
-            [&](const OmpLoopDirective::Taskloop &y) {
-              Word("TASKLOOP ");
-              Walk(y.v, " ");
-            },
-            [&](const OmpLoopDirective::TeamsDistributeParallelDoSimd &y) {
+            [&](const OmpLoopDirective::Taskloop &) { Word("TASKLOOP "); },
+            [&](const OmpLoopDirective::TeamsDistributeParallelDoSimd &) {
               Word("TEAMS DISTRIBUTE PARALLEL DO SIMD ");
-              Walk(y.v, " ");
             },
-            [&](const OmpLoopDirective::TeamsDistributeParallelDo &y) {
+            [&](const OmpLoopDirective::TeamsDistributeParallelDo &) {
               Word("TEAMS DISTRIBUTE PARALLEL DO ");
-              Walk(y.v, " ");
             },
-            [&](const OmpLoopDirective::TeamsDistributeSimd &y) {
+            [&](const OmpLoopDirective::TeamsDistributeSimd &) {
               Word("TEAMS DISTRIBUTE SIMD ");
-              Walk(y.v, " ");
             },
-            [&](const OmpLoopDirective::TeamsDistribute &y) {
+            [&](const OmpLoopDirective::TeamsDistribute &) {
               Word("TEAMS DISTRIBUTE ");
-              Walk(y.v, " ");
             }},
         x.u);
-    Put("\n");
-    Indent();
   }
+  void Unparse(const OmpObjectList &x) { Walk(x.v, ","); }
   void Unparse(const OmpStandaloneDirective &x) {
-    std::visit(common::visitors{[&](const OmpStandaloneDirective::Barrier &y) {
-                                  Word("BARRIER ");
-                                  Walk(y.v, " ");
-                                },
-                   [&](const OmpStandaloneDirective::CancellationPoint &y) {
-                     Word("CANCELLATION POINT ");
-                     Walk(y.v, " ");
-                   },
-                   [&](const OmpStandaloneDirective::Cancel &y) {
-                     Word("CANCEL ");
-                     Walk(y.v, " ");
-                   },
-                   [&](const OmpStandaloneDirective::Flush &y) {
-                     Word("FLUSH ");
-                     Walk(y.v, " ");
-                   },
-                   [&](const OmpStandaloneDirective::TargetEnterData &y) {
-                     Word("TARGET ENTER DATA ");
-                     Walk(y.v, " ");
-                   },
-                   [&](const OmpStandaloneDirective::TargetExitData &y) {
-                     Word("TARGET EXIT DATA ");
-                     Walk(y.v, " ");
-                   },
-                   [&](const OmpStandaloneDirective::TargetUpdate &y) {
-                     Word("TARGET UPDATE ");
-                     Walk(y.v, " ");
-                   },
-                   [&](const OmpStandaloneDirective::Taskwait &y) {
-                     Word("TASKWAIT ");
-                     Walk(y.v, " ");
-                   },
-                   [&](const OmpStandaloneDirective::Taskyield &y) {
-                     Word("TASKYIELD ");
-                     Walk(y.v, " ");
-                   }},
+    std::visit(
+        common::visitors{[&](const OmpStandaloneDirective::TargetEnterData &) {
+                           Word("TARGET ENTER DATA ");
+                         },
+            [&](const OmpStandaloneDirective::TargetExitData &) {
+              Word("TARGET EXIT DATA ");
+            },
+            [&](const OmpStandaloneDirective::TargetUpdate &) {
+              Word("TARGET UPDATE ");
+            }},
         x.u);
+  }
+  void Unparse(const OmpBlockDirective &x) {
+    std::visit(
+        common::visitors{
+            [&](const OmpBlockDirective::Master &y) { Word("MASTER"); },
+            [&](const OmpBlockDirective::Ordered &) { Word("ORDERED "); },
+            [&](const OmpBlockDirective::ParallelWorkshare &) {
+              Word("PARALLEL WORKSHARE ");
+            },
+            [&](const OmpBlockDirective::Parallel &) { Word("PARALLEL "); },
+            [&](const OmpBlockDirective::TargetData &) {
+              Word("TARGET DATA ");
+            },
+            [&](const OmpBlockDirective::TargetParallel &) {
+              Word("TARGET PARALLEL ");
+            },
+            [&](const OmpBlockDirective::TargetTeams &) {
+              Word("TARGET TEAMS ");
+            },
+            [&](const OmpBlockDirective::Target &) { Word("TARGET "); },
+            [&](const OmpBlockDirective::Taskgroup &) { Word("TASKGROUP "); },
+            [&](const OmpBlockDirective::Task &) { Word("TASK "); },
+            [&](const OmpBlockDirective::Teams &) { Word("TEAMS "); }},
+        x.u);
+  }
+  void Unparse(const OmpAtomic &x) {
+    BeginOpenMP();
+    Word("!$OMP ATOMIC");
+    Walk(std::get<std::optional<OmpAtomic::SeqCst>>(x.t), " SEQ_CST");
     Put("\n");
-    Indent();
+    EndOpenMP();
+    Walk(std::get<Statement<AssignmentStmt>>(x.t));
+    BeginOpenMP();
+    Walk(std::get<std::optional<OmpEndAtomic>>(x.t), "!$OMP END ATOMIC\n");
+    EndOpenMP();
+  }
+  void Unparse(const OmpAtomicCapture &x) {
+    BeginOpenMP();
+    Word("!$OMP ATOMIC");
+    Walk(std::get<std::optional<OmpAtomicCapture::SeqCst1>>(x.t), " SEQ_CST,");
+    Word(" CAPTURE");
+    Walk(std::get<std::optional<OmpAtomicCapture::SeqCst2>>(x.t), " ,SEQ_CST");
+    Put("\n");
+    EndOpenMP();
+    Walk(std::get<OmpAtomicCapture::Stmt1>(x.t));
+    Put("\n");
+    Walk(std::get<OmpAtomicCapture::Stmt2>(x.t));
+    BeginOpenMP();
+    Word("!$OMP END ATOMIC\n");
+    EndOpenMP();
+  }
+  void Unparse(const OmpAtomicRead &x) {
+    BeginOpenMP();
+    Word("!$OMP ATOMIC");
+    Walk(std::get<std::optional<OmpAtomicRead::SeqCst1>>(x.t), " SEQ_CST,");
+    Word(" READ");
+    Walk(std::get<std::optional<OmpAtomicRead::SeqCst2>>(x.t), " ,SEQ_CST");
+    Put("\n");
+    EndOpenMP();
+    Walk(std::get<Statement<AssignmentStmt>>(x.t));
+    BeginOpenMP();
+    Walk(std::get<std::optional<OmpEndAtomic>>(x.t), "!$OMP END ATOMIC\n");
+    EndOpenMP();
+  }
+  void Unparse(const OmpAtomicUpdate &x) {
+    BeginOpenMP();
+    Word("!$OMP ATOMIC");
+    Walk(std::get<std::optional<OmpAtomicUpdate::SeqCst1>>(x.t), " SEQ_CST,");
+    Word(" UPDATE");
+    Walk(std::get<std::optional<OmpAtomicUpdate::SeqCst2>>(x.t), " ,SEQ_CST");
+    Put("\n");
+    EndOpenMP();
+    Walk(std::get<Statement<AssignmentStmt>>(x.t));
+    BeginOpenMP();
+    Walk(std::get<std::optional<OmpEndAtomic>>(x.t), "!$OMP END ATOMIC\n");
+    EndOpenMP();
+  }
+  void Unparse(const OmpAtomicWrite &x) {
+    BeginOpenMP();
+    Word("!$OMP ATOMIC");
+    Walk(std::get<std::optional<OmpAtomicWrite::SeqCst1>>(x.t), " SEQ_CST,");
+    Word(" WRITE");
+    Walk(std::get<std::optional<OmpAtomicWrite::SeqCst2>>(x.t), " ,SEQ_CST");
+    Put("\n");
+    EndOpenMP();
+    Walk(std::get<Statement<AssignmentStmt>>(x.t));
+    BeginOpenMP();
+    Walk(std::get<std::optional<OmpEndAtomic>>(x.t), "!$OMP END ATOMIC\n");
+    EndOpenMP();
+  }
+  void Unparse(const OmpEndCritical &x) {
+    Walk(" (", x.v, ")");
+    EndOpenMP();
+  }
+  void Unparse(const OpenMPCriticalConstruct &x) {
+    BeginOpenMP();
+    Word("!$OMP CRITICAL");
+    Walk(" (", std::get<std::optional<Name>>(x.t), ")");
+    Walk(" HINT(", std::get<std::optional<OpenMPCriticalConstruct::Hint>>(x.t),
+        ")");
+    Put("\n");
+    EndOpenMP();
+    Walk(std::get<Block>(x.t), "");
+    BeginOpenMP();
+    Word("!$OMP END CRITICAL");
+    Walk(std::get<OmpEndCritical>(x.t));
+    Put("\n");
+    EndOpenMP();
   }
-  void Unparse(const OmpEndDirective &x) {
-    Outdent();
-    std::visit(common::visitors{[&](const OmpLoopDirective &y) {
-      Word("!$OMP END ");
-      Walk(y);
-    }},
+  void Unparse(const OpenMPDeclareTargetConstruct::WithClause &x) {
+    Walk(x.maptype), Put("("), Walk(x.names), Put(")");
+  }
+  void Unparse(const OpenMPDeclareTargetConstruct::WithExtendedList &x) {
+    Put("("), Walk(x.names), Put(")");
+  }
+  void Unparse(const OmpReductionInitializerClause &x) {
+    Word(" INITIALIZER(OMP_PRIV = ");
+    Walk(x.v);
+    Put(")");
+  }
+  void Unparse(const OmpReductionCombiner::FunctionCombiner &x) {
+    const auto &pd = std::get<ProcedureDesignator>(x.v.t);
+    const auto &args = std::get<std::list<ActualArgSpec>>(x.v.t);
+    Walk(pd);
+    if (args.empty()) {
+      if (std::holds_alternative<ProcComponentRef>(pd.u)) {
+        Put("()");
+      }
+    } else {
+      Walk("(", args, ", ", ")");
+    }
+  }
+  void Unparse(const OpenMPDeclareReductionConstruct &x) {
+    Put("(");
+    Walk(std::get<OmpReductionOperator>(x.t)), Put(" : ");
+    Walk(std::get<std::list<DeclarationTypeSpec>>(x.t), ","), Put(" : ");
+    Walk(std::get<OmpReductionCombiner>(x.t));
+    Put(")");
+    Walk(std::get<std::optional<OmpReductionInitializerClause>>(x.t));
+  }
+  bool Pre(const OpenMPDeclarativeConstruct &x) {
+    BeginOpenMP();
+    Word("!$OMP ");
+    return std::visit(
+        common::visitors{[&](const OpenMPDeclareReductionConstruct &y) {
+                           Word("DECLARE REDUCTION ");
+                           return true;
+                         },
+            [&](const OpenMPDeclareSimdConstruct &y) {
+              Word("DECLARE SIMD ");
+              Walk("(", std::get<std::optional<Name>>(y.t), ")");
+              Walk(std::get<OmpClauseList>(y.t));
+              Put("\n");
+              EndOpenMP();
+              return false;
+            },
+            [&](const OpenMPDeclareTargetConstruct &y) {
+              Word("DECLARE TARGET ");
+              return true;
+            },
+            [&](const OpenMPDeclarativeConstruct::Threadprivate &y) {
+              Word("THREADPRIVATE (");
+              return true;
+            }},
         x.u);
   }
+  void Post(const OpenMPDeclarativeConstruct &x) {
+    Put("\n");
+    EndOpenMP();
+  }
+  void Post(const OpenMPDeclarativeConstruct::Threadprivate &x) {
+    Put(")\n");
+    EndOpenMP();
+  }
+  void Unparse(const OmpEndDoSimd &x) {
+    BeginOpenMP();
+    Word("DO SIMD ");
+    Walk(x.v);
+    EndOpenMP();
+  }
+  void Unparse(const OmpEndDo &x) {
+    BeginOpenMP();
+    Word("DO ");
+    Walk(x.v);
+    EndOpenMP();
+  }
+  bool Pre(const OpenMPBarrierConstruct &x) {
+    BeginOpenMP();
+    Word("!$OMP BARRIER");
+    Put("\n");
+    EndOpenMP();
+    return false;
+  }
+  void Unparse(const OpenMPSingleConstruct &x) {
+    BeginOpenMP();
+    Word("!$OMP SINGLE");
+    Walk(std::get<OmpClauseList>(x.t));
+    EndOpenMP();
+    Put("\n");
+    Walk(std::get<Block>(x.t), "");
+    BeginOpenMP();
+    Word("!$OMP END SINGLE ");
+    Walk(std::get<OmpEndSingle>(x.t));
+    Put("\n");
+    EndOpenMP();
+  }
+  void Unparse(const OmpSection &x) {
+    BeginOpenMP();
+    Word("!$OMP SECTION");
+    Put("\n");
+    EndOpenMP();
+  }
+  void Unparse(const OpenMPSectionsConstruct &x) {
+    BeginOpenMP();
+    Word("!$OMP SECTIONS");
+    Walk(std::get<OmpClauseList>(x.t));
+    Put("\n");
+    EndOpenMP();
+    Walk(std::get<Block>(x.t), "");
+    BeginOpenMP();
+    Word("!$OMP END SECTIONS");
+    Put("\n");
+    EndOpenMP();
+  }
+  void Unparse(const OpenMPParallelSectionsConstruct &x) {
+    BeginOpenMP();
+    Word("!$OMP PARALLEL SECTIONS");
+    Walk(std::get<OmpClauseList>(x.t));
+    Put("\n");
+    EndOpenMP();
+    Walk(std::get<Block>(x.t), "");
+    BeginOpenMP();
+    Word("!$OMP END PARALLEL SECTIONS");
+    Put("\n");
+    EndOpenMP();
+  }
+  void Unparse(const OpenMPWorkshareConstruct &x) {
+    BeginOpenMP();
+    Word("!$OMP WORKSHARE");
+    Put("\n");
+    EndOpenMP();
+    Walk(std::get<Block>(x.t), "");
+    BeginOpenMP();
+    Word("!$OMP END WORKSHARE ");
+    Walk(std::get<std::optional<OmpNowait>>(x.t));
+    Put("\n");
+    EndOpenMP();
+  }
+  bool Pre(const OpenMPTaskyieldConstruct &x) {
+    BeginOpenMP();
+    Word("!$OMP TASKYIELD");
+    Put("\n");
+    EndOpenMP();
+    return false;
+  }
+  bool Pre(const OpenMPTaskwaitConstruct &x) {
+    BeginOpenMP();
+    Word("!$OMP TASKWAIT");
+    Put("\n");
+    EndOpenMP();
+    return false;
+  }
+  void Unparse(const OpenMPCancellationPointConstruct &x) {
+    BeginOpenMP();
+    Word("!$OMP CANCELLATION POINT ");
+    Walk(x.v);
+    Put("\n");
+    EndOpenMP();
+  }
+  void Unparse(const OpenMPCancelConstruct &x) {
+    BeginOpenMP();
+    Word("!$OMP CANCEL ");
+    Walk(std::get<OmpCancelType>(x.t));
+    Walk(std::get<std::optional<OpenMPCancelConstruct::If>>(x.t));
+    Put("\n");
+    EndOpenMP();
+  }
+  void Unparse(const OpenMPFlushConstruct &x) {
+    BeginOpenMP();
+    Word("!$OMP FLUSH");
+    if ((x.v).has_value()) {
+      Put("(");
+      Walk(x.v);
+      Put(")");
+    }
+    Put("\n");
+    EndOpenMP();
+  }
+  bool Pre(const OpenMPEndLoopDirective &x) {
+    BeginOpenMP();
+    Word("!$OMP END ");
+    return true;
+  }
+  void Post(const OpenMPEndLoopDirective &x) {
+    Put("\n");
+    EndOpenMP();
+  }
+  void Unparse(const OmpClauseList &x) { Walk(" ", x.v, " "); }
   void Unparse(const OpenMPStandaloneConstruct &x) {
-    Outdent();
+    BeginOpenMP();
     Word("!$OMP ");
-    Walk(x.v);
+    Walk(std::get<OmpStandaloneDirective>(x.t));
+    Walk(std::get<OmpClauseList>(x.t));
+    Put("\n");
+    EndOpenMP();
   }
-  bool Pre(const OpenMPLoopConstruct &x) {
-    Outdent();
+  void Unparse(const OpenMPBlockConstruct &x) {
+    BeginOpenMP();
     Word("!$OMP ");
-    return true;
+    Walk(std::get<OmpBlockDirective>(x.t));
+    Walk(std::get<OmpClauseList>(x.t));
+    Put("\n");
+    EndOpenMP();
+    Walk(std::get<Block>(x.t), "");
+    BeginOpenMP();
+    Word("!$OMP END ");
+    Walk(std::get<OmpEndBlockDirective>(x.t));
+    Put("\n");
+    EndOpenMP();
+  }
+  void Unparse(const OpenMPLoopConstruct &x) {
+    BeginOpenMP();
+    Word("!$OMP ");
+    Walk(std::get<OmpLoopDirective>(x.t));
+    Walk(std::get<OmpClauseList>(x.t));
+    Put("\n");
+    EndOpenMP();
   }
-
   void Unparse(const BasedPointerStmt &x) {
     Word("POINTER ("), Walk(std::get<0>(x.t)), Put(", ");
     Walk(std::get<1>(x.t));
@@ -2116,13 +2355,13 @@ public:
   WALK_NESTED_ENUM(OmpDefaultClause, Type)  // OMP DEFAULT
   WALK_NESTED_ENUM(OmpScheduleModifierType, ModType)  // OMP schedule-modifier
   WALK_NESTED_ENUM(OmpLinearModifier, Type)  // OMP linear-modifier
-  WALK_NESTED_ENUM(
-      OmpReductionOperator, ProcedureOperator)  // OMP reduction-identifier
   WALK_NESTED_ENUM(OmpDependenceType, Type)  // OMP dependence-type
-  WALK_NESTED_ENUM(OmpMapClause, Type)  // OMP map-type
+  WALK_NESTED_ENUM(OmpMapType, Type)  // OMP map-type
   WALK_NESTED_ENUM(OmpScheduleClause, ScheduleType)  // OMP schedule-type
   WALK_NESTED_ENUM(
       OmpIfClause, DirectiveNameModifier)  // OMP directive-modifier
+  WALK_NESTED_ENUM(OmpDeclareTargetMapType, Type)  // OMP DeclareTarget map-type
+  WALK_NESTED_ENUM(OmpCancelType, Type)  // OMP cancel-type
 #undef WALK_NESTED_ENUM
 
   void Done() const { CHECK(indent_ == 0); }
@@ -2139,6 +2378,8 @@ private:
     CHECK(indent_ >= indentationAmount_);
     indent_ -= indentationAmount_;
   }
+  void BeginOpenMP() { openmpDirective_ = true; }
+  void EndOpenMP() { openmpDirective_ = false; }
 
   // Call back to the traversal framework.
   template<typename T> void Walk(const T &x) {
@@ -2208,11 +2449,16 @@ private:
   std::set<CharBlock> structureComponents_;
   Encoding encoding_{Encoding::UTF8};
   bool capitalizeKeywords_{true};
+  bool openmpDirective_{false};
   bool backslashEscapes_{false};
   preStatementType *preStatement_{nullptr};
 };
 
 void UnparseVisitor::Put(char ch) {
+  int sav = indent_;
+  if (openmpDirective_) {
+    indent_ = 0;
+  }
   if (column_ <= 1) {
     if (ch == '\n') {
       return;
@@ -2228,10 +2474,18 @@ void UnparseVisitor::Put(char ch) {
     for (int j{0}; j < indent_; ++j) {
       out_ << ' ';
     }
-    out_ << '&';
-    column_ = indent_ + 3;
+    if (openmpDirective_) {
+      out_ << "!$OMP&";
+      column_ = 8;
+    } else {
+      out_ << '&';
+      column_ = indent_ + 3;
+    }
   }
   out_ << ch;
+  if (openmpDirective_) {
+    indent_ = sav;
+  }
 }
 
 void UnparseVisitor::Put(const char *str) {
index 00c95e2..e0014e3 100644 (file)
@@ -394,7 +394,46 @@ public:
   NODE(parser, ObjectDecl)
   NODE(parser, OldParameterStmt)
   NODE(parser, OmpAlignedClause)
+  NODE(parser, OpenMPAtomicConstruct)
+  NODE(parser, OmpEndAtomic)
+  NODE(parser, OpenMPCriticalConstruct)
+  NODE(parser::OpenMPCriticalConstruct, Hint)
+  NODE(parser, OmpEndCritical)
+  NODE(parser, OmpAtomic)
+  NODE(parser::OmpAtomic, SeqCst)
+  NODE(parser, OmpAtomicCapture)
+  NODE(parser::OmpAtomicCapture, SeqCst1)
+  NODE(parser::OmpAtomicCapture, SeqCst2)
+  NODE(parser::OmpAtomicCapture, Stmt1)
+  NODE(parser::OmpAtomicCapture, Stmt2)
+  NODE(parser, OmpAtomicRead)
+  NODE(parser::OmpAtomicRead, SeqCst1)
+  NODE(parser::OmpAtomicRead, SeqCst2)
+  NODE(parser, OmpAtomicUpdate)
+  NODE(parser::OmpAtomicUpdate, SeqCst1)
+  NODE(parser::OmpAtomicUpdate, SeqCst2)
+  NODE(parser, OmpAtomicWrite)
+  NODE(parser::OmpAtomicWrite, SeqCst1)
+  NODE(parser::OmpAtomicWrite, SeqCst2)
+  NODE(parser, OmpBlockDirective)
+  NODE(parser::OmpBlockDirective, Master)
+  NODE(parser::OmpBlockDirective, Ordered)
+  NODE(parser::OmpBlockDirective, Parallel)
+  NODE(parser::OmpBlockDirective, ParallelWorkshare)
+  NODE(parser, OpenMPSingleConstruct)
+  NODE(parser, OmpEndSingle)
+  NODE(parser, OpenMPWorkshareConstruct)
+  NODE(parser, OmpEndDo)
+  NODE(parser, OmpEndDoSimd)
+  NODE(parser::OmpBlockDirective, Target)
+  NODE(parser::OmpBlockDirective, TargetData)
+  NODE(parser::OmpBlockDirective, TargetParallel)
+  NODE(parser::OmpBlockDirective, TargetTeams)
+  NODE(parser::OmpBlockDirective, Task)
+  NODE(parser::OmpBlockDirective, Taskgroup)
+  NODE(parser::OmpBlockDirective, Teams)
   NODE(parser, OmpClause)
+  NODE(parser, OmpClauseList)
   NODE(parser::OmpClause, Collapse)
   NODE(parser::OmpClause, Copyin)
   NODE(parser::OmpClause, Copyprivate)
@@ -407,11 +446,9 @@ public:
   NODE(parser::OmpClause, Grainsize)
   NODE(parser::OmpClause, Inbranch)
   NODE(parser::OmpClause, Lastprivate)
-  NODE(parser::OmpClause, Link)
   NODE(parser::OmpClause, Mergeable)
   NODE(parser::OmpClause, Nogroup)
   NODE(parser::OmpClause, Notinbranch)
-  NODE(parser::OmpClause, Nowait)
   NODE(parser::OmpClause, NumTasks)
   NODE(parser::OmpClause, NumTeams)
   NODE(parser::OmpClause, NumThreads)
@@ -436,21 +473,37 @@ public:
   NODE(parser::OmpDependenceType, Type)
   NODE(parser, OmpDependSinkVec)
   NODE(parser, OmpDependSinkVecLength)
-  NODE(parser, OmpEndDirective)
+  NODE(parser, OmpEndBlockDirective)
+  NODE(parser, OmpIfClause)
+  NODE(parser::OmpIfClause, DirectiveNameModifier)
   NODE(parser, OmpLinearClause)
   NODE(parser::OmpLinearClause, WithModifier)
   NODE(parser::OmpLinearClause, WithoutModifier)
   NODE(parser, OmpLinearModifier)
   NODE(parser::OmpLinearModifier, Type)
+  NODE(parser, OpenMPDeclareReductionConstruct)
+  NODE(parser, OmpReductionInitializerClause)
+  NODE(parser, OmpReductionCombiner)
+  NODE(parser::OmpReductionCombiner, FunctionCombiner)
+  NODE(parser, OpenMPDeclareSimdConstruct)
+  NODE(parser, OmpDeclareTargetMapType)
+  NODE(parser::OmpDeclareTargetMapType, Type)
+  NODE(parser, OpenMPEndLoopDirective)
+  NODE(parser, OpenMPDeclareTargetConstruct)
+  NODE(parser::OpenMPDeclareTargetConstruct, Implicit)
+  NODE(parser::OpenMPDeclareTargetConstruct, WithClause)
+  NODE(parser::OpenMPDeclareTargetConstruct, WithExtendedList)
+  NODE(parser::OpenMPDeclarativeConstruct, Threadprivate)
+  NODE(parser, OpenMPLoopConstruct)
   NODE(parser, OmpLoopDirective)
   NODE(parser::OmpLoopDirective, Distribute)
   NODE(parser::OmpLoopDirective, DistributeParallelDo)
   NODE(parser::OmpLoopDirective, DistributeParallelDoSimd)
   NODE(parser::OmpLoopDirective, DistributeSimd)
-  NODE(parser::OmpLoopDirective, Do)
-  NODE(parser::OmpLoopDirective, DoSimd)
   NODE(parser::OmpLoopDirective, ParallelDo)
   NODE(parser::OmpLoopDirective, ParallelDoSimd)
+  NODE(parser::OmpLoopDirective, DoSimd)
+  NODE(parser::OmpLoopDirective, Do)
   NODE(parser::OmpLoopDirective, Simd)
   NODE(parser::OmpLoopDirective, TargetParallelDo)
   NODE(parser::OmpLoopDirective, TargetParallelDoSimd)
@@ -465,8 +518,7 @@ public:
   NODE(parser::OmpLoopDirective, TeamsDistributeParallelDo)
   NODE(parser::OmpLoopDirective, TeamsDistributeParallelDoSimd)
   NODE(parser::OmpLoopDirective, TeamsDistributeSimd)
-  NODE(parser, OmpIfClause)
-  NODE(parser::OmpIfClause, DirectiveNameModifier)
+  NODE(parser, OmpNowait)
   NODE(parser, OmpScheduleClause)
   NODE(parser::OmpScheduleClause, ScheduleType)
   NODE(parser, OmpScheduleModifier)
@@ -475,28 +527,38 @@ public:
   NODE(parser, OmpScheduleModifierType)
   NODE(parser::OmpScheduleModifierType, ModType)
   NODE(parser, OmpMapClause)
-  NODE(parser::OmpMapClause, Type)
-  NODE(parser, OmpNameList)
-  NODE(parser::OmpNameList, Kind)
+  NODE(parser, OmpMapType)
+  NODE(parser::OmpMapType, Always)
+  NODE(parser::OmpMapType, Type)
+  NODE(parser, OmpObject)
+  NODE(parser::OmpObject, Kind)
+  NODE(parser, OmpObjectList)
   NODE(parser, OmpProcBindClause)
   NODE(parser::OmpProcBindClause, Type)
   NODE(parser, OmpReductionOperator)
-  NODE(parser::OmpReductionOperator, ProcedureOperator)
-  NODE(parser::OmpReductionOperator, BinaryOperator)
+  NODE(parser, OmpSection)
   NODE(parser, OmpStandaloneDirective)
-  NODE(parser::OmpStandaloneDirective, Barrier)
-  NODE(parser::OmpStandaloneDirective, Cancel)
-  NODE(parser::OmpStandaloneDirective, CancellationPoint)
-  NODE(parser::OmpStandaloneDirective, Flush)
+  NODE(parser, OpenMPCancellationPointConstruct)
+  NODE(parser, OpenMPCancelConstruct)
+  NODE(parser::OpenMPCancelConstruct, If)
+  NODE(parser, OmpCancelType)
+  NODE(parser::OmpCancelType, Type)
+  NODE(parser, OpenMPFlushConstruct)
   NODE(parser::OmpStandaloneDirective, TargetEnterData)
   NODE(parser::OmpStandaloneDirective, TargetExitData)
   NODE(parser::OmpStandaloneDirective, TargetUpdate)
-  NODE(parser::OmpStandaloneDirective, Taskwait)
-  NODE(parser::OmpStandaloneDirective, Taskyield)
+  NODE(parser, OpenMPBarrierConstruct)
+  NODE(parser, OpenMPTaskwaitConstruct)
+  NODE(parser, OpenMPTaskyieldConstruct)
   NODE(parser, OpenMPConstruct)
-  NODE(parser, OpenMPLoopConstruct)
+  NODE(parser, OpenMPBlockConstruct)
+  NODE(parser, OpenMPDeclarativeConstruct)
   NODE(parser, OpenMPStandaloneConstruct)
   NODE(parser, OmpReductionClause)
+  NODE(parser, OpenMPSectionsConstruct)
+  NODE(parser, OpenMPParallelSectionsConstruct)
+  NODE(parser, OmpEndSections)
+  NODE(parser, OmpEndParallelSections)
   NODE(parser, Only)
   NODE(parser, OpenStmt)
   NODE(parser, Optional)