[flang] Simplify CommonStmt in parse tree
authorTim Keith <tkeith@nvidia.com>
Wed, 13 Feb 2019 00:13:58 +0000 (16:13 -0800)
committerTim Keith <tkeith@nvidia.com>
Wed, 13 Feb 2019 00:13:58 +0000 (16:13 -0800)
The grammar requires parsing the first common block in a common stmt
differently from the others: the '//' is optional for the blank common.

But once it's parsed, it is easier to work with if each is represented
as a `parser::CommonStmt::Block`. This is achieved by using the same
constructor for `CommonStmt` but then including the first block in
the list of blocks.

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

flang/lib/parser/parse-tree-visitor.h
flang/lib/parser/parse-tree.cc
flang/lib/parser/parse-tree.h
flang/lib/parser/unparse.cc

index fc7a918..ae1181f 100644 (file)
@@ -498,6 +498,18 @@ template<typename T, typename M> void Walk(LoopBounds<T> &x, M &mutator) {
     mutator.Post(x);
   }
 }
+template<typename V> void Walk(const CommonStmt &x, V &visitor) {
+  if (visitor.Pre(x)) {
+    Walk(x.blocks, visitor);
+    visitor.Post(x);
+  }
+}
+template<typename M> void Walk(CommonStmt &x, M &mutator) {
+  if (mutator.Pre(x)) {
+    Walk(x.blocks, mutator);
+    mutator.Post(x);
+  }
+}
 template<typename V> void Walk(const Expr &x, V &visitor) {
   if (visitor.Pre(x)) {
     Walk(x.source, visitor);
index ec8c393..efa0ece 100644 (file)
@@ -27,6 +27,13 @@ ImportStmt::ImportStmt(common::ImportKind &&k, std::list<Name> &&n)
       kind == common::ImportKind::Only || names.empty());
 }
 
+// R873
+CommonStmt::CommonStmt(std::optional<Name> &&name,
+    std::list<CommonBlockObject> &&objects, std::list<Block> &&others) {
+  blocks.emplace_front(std::move(name), std::move(objects));
+  blocks.splice(blocks.end(), std::move(others));
+}
+
 // R901 designator
 bool Designator::EndsInBareName() const {
   return std::visit(
index e3e409b..00af09d 100644 (file)
@@ -1535,10 +1535,10 @@ struct CommonStmt {
     TUPLE_CLASS_BOILERPLATE(Block);
     std::tuple<std::optional<Name>, std::list<CommonBlockObject>> t;
   };
-  TUPLE_CLASS_BOILERPLATE(CommonStmt);
-  std::tuple<std::optional<Name>, std::list<CommonBlockObject>,
-      std::list<Block>>
-      t;
+  BOILERPLATE(CommonStmt);
+  CommonStmt(std::optional<Name> &&, std::list<CommonBlockObject> &&,
+      std::list<Block> &&);
+  std::list<Block> blocks;
 };
 
 // R872 equivalence-object -> variable-name | array-element | substring
index 2ffd9a5..891f5c3 100644 (file)
@@ -703,9 +703,7 @@ public:
   }
   void Unparse(const CommonStmt &x) {  // R873
     Word("COMMON ");
-    Walk("/", std::get<std::optional<Name>>(x.t), "/");
-    Walk(std::get<std::list<CommonBlockObject>>(x.t), ", ");
-    Walk(", ", std::get<std::list<CommonStmt::Block>>(x.t), ", ");
+    Walk(x.blocks);
   }
   void Unparse(const CommonBlockObject &x) {  // R874
     Walk(std::get<Name>(x.t));