[flang] Refactor ModFileReader to use parser::Parsing
authorTim Keith <tkeith@nvidia.com>
Thu, 26 Jul 2018 17:57:51 +0000 (10:57 -0700)
committerTim Keith <tkeith@nvidia.com>
Thu, 26 Jul 2018 17:57:51 +0000 (10:57 -0700)
parser::Parsing does most of the work needed to prescan and parse a file.
The only problem is that for module files we need to take ownership of
the cooked character stream so that it lives as long as the module scope
does.

To achieve this, change Parsing::cooked_ to be a unique_ptr and add a
member function to allow the caller to take ownership of it.

Original-commit: flang-compiler/f18@9088891ab29d91a51c55edb031b5a974cc8254b9
Reviewed-on: https://github.com/flang-compiler/f18/pull/149
Tree-same-pre-rewrite: false

flang/lib/parser/parsing.cc
flang/lib/parser/parsing.h
flang/lib/semantics/mod-file.cc

index d2ca8a4..ae835ac 100644 (file)
@@ -63,7 +63,7 @@ void Parsing::Prescan(const std::string &path, Options options) {
       preprocessor.Undefine(predef.first);
     }
   }
-  Prescanner prescanner{messages_, cooked_, preprocessor, options.features};
+  Prescanner prescanner{messages_, *cooked_, preprocessor, options.features};
   prescanner.set_fixedForm(options.isFixedForm)
       .set_fixedFormColumnLimit(options.fixedFormColumns)
       .set_encoding(options.encoding)
@@ -75,30 +75,30 @@ void Parsing::Prescan(const std::string &path, Options options) {
   ProvenanceRange range{
       allSources_.AddIncludedFile(*sourceFile, ProvenanceRange{})};
   prescanner.Prescan(range);
-  cooked_.Marshal();
+  cooked_->Marshal();
 }
 
 void Parsing::DumpCookedChars(std::ostream &out) const {
-  UserState userState{cooked_, LanguageFeatureControl{}};
-  ParseState parseState{cooked_};
+  UserState userState{*cooked_, LanguageFeatureControl{}};
+  ParseState parseState{*cooked_};
   parseState.set_inFixedForm(options_.isFixedForm).set_userState(&userState);
   while (std::optional<const char *> p{parseState.GetNextChar()}) {
     out << **p;
   }
 }
 
-void Parsing::DumpProvenance(std::ostream &out) const { cooked_.Dump(out); }
+void Parsing::DumpProvenance(std::ostream &out) const { cooked_->Dump(out); }
 
 void Parsing::DumpParsingLog(std::ostream &out) const {
-  log_.Dump(out, cooked_);
+  log_.Dump(out, *cooked_);
 }
 
 void Parsing::Parse(std::ostream *out) {
-  UserState userState{cooked_, options_.features};
+  UserState userState{*cooked_, options_.features};
   userState.set_debugOutput(out)
       .set_instrumentedParse(options_.instrumentedParse)
       .set_log(&log_);
-  ParseState parseState{cooked_};
+  ParseState parseState{*cooked_};
   parseState.set_inFixedForm(options_.isFixedForm)
       .set_encoding(options_.encoding)
       .set_userState(&userState);
@@ -115,12 +115,12 @@ void Parsing::ClearLog() { log_.clear(); }
 bool Parsing::ForTesting(std::string path, std::ostream &err) {
   Prescan(path, Options{});
   if (messages_.AnyFatalError()) {
-    messages_.Emit(err, cooked_);
+    messages_.Emit(err, *cooked_);
     err << "could not scan " << path << '\n';
     return false;
   }
   Parse();
-  messages_.Emit(err, cooked_);
+  messages_.Emit(err, *cooked_);
   if (!consumedWholeFile_) {
     EmitMessage(err, finalRestingPlace_, "parser FAIL; final position");
     return false;
index 5c6cf18..334474f 100644 (file)
@@ -50,7 +50,8 @@ public:
 
   bool consumedWholeFile() const { return consumedWholeFile_; }
   const char *finalRestingPlace() const { return finalRestingPlace_; }
-  CookedSource &cooked() { return cooked_; }
+  CookedSource &cooked() { return *cooked_; }
+  std::unique_ptr<CookedSource> MoveCooked() { return std::move(cooked_); }
   Messages &messages() { return messages_; }
   std::optional<Program> &parseTree() { return parseTree_; }
 
@@ -64,7 +65,7 @@ public:
   void EmitMessage(std::ostream &o, const char *at, const std::string &message,
       bool echoSourceLine = false) const {
     allSources_.EmitMessage(
-        o, cooked_.GetProvenanceRange(at).start(), message, echoSourceLine);
+        o, cooked_->GetProvenanceRange(at).start(), message, echoSourceLine);
   }
 
   bool ForTesting(std::string path, std::ostream &);
@@ -72,7 +73,8 @@ public:
 private:
   Options options_;
   AllSources allSources_;
-  CookedSource cooked_{allSources_};
+  std::unique_ptr<parser::CookedSource> cooked_{
+      std::make_unique<parser::CookedSource>(allSources_)};
   Messages messages_;
   bool consumedWholeFile_{false};
   const char *finalRestingPlace_{nullptr};
index f524189..52d48a1 100644 (file)
 #include "mod-file.h"
 #include "scope.h"
 #include "symbol.h"
-#include "../parser/grammar.h"
 #include "../parser/message.h"
-#include "../parser/openmp-grammar.h"
-#include "../parser/preprocessor.h"
-#include "../parser/prescan.h"
+#include "../parser/parsing.h"
 #include <algorithm>
 #include <cerrno>
 #include <fstream>
@@ -27,8 +24,6 @@
 #include <ostream>
 #include <set>
 #include <sstream>
-#include <sys/stat.h>
-#include <sys/types.h>
 #include <vector>
 
 namespace Fortran::semantics {
@@ -358,19 +353,20 @@ bool ModFileReader::Read(const SourceName &modName) {
   if (!path.has_value()) {
     return false;
   }
-  if (!Prescan(modName, *path)) {
-    return false;
-  }
-  parser::ParseState parseState{*cooked_};
-  auto parseTree{parser::program.Parse(parseState)};
-  if (!parseState.messages().empty()) {
-    errors_.emplace_back(modName,
-        parser::MessageFormattedText{
-            "Module file for '%s' is corrupt: %s"_err_en_US,
-            modName.ToString().data(), path->data()});
+  parser::Parsing parsing;
+  parsing.Prescan(*path, {});
+  parsing.Parse(&std::cout);
+  auto &parseTree{parsing.parseTree()};
+  if (!parsing.messages().empty() || !parsing.consumedWholeFile() ||
+      !parseTree.has_value()) {
+    errors_.push_back(
+        Error(modName, "Module file for '%s' is corrupt: %s"_err_en_US,
+            modName.ToString(), *path));
     return false;
   }
+  std::unique_ptr<parser::CookedSource> cooked_{parsing.MoveCooked()};
   ResolveNames(*parseTree, *cooked_, directories_);
+
   const auto &it{Scope::globalScope.find(modName)};
   if (it == Scope::globalScope.end()) {
     return false;
@@ -407,31 +403,6 @@ std::optional<std::string> ModFileReader::FindModFile(
   return std::nullopt;
 }
 
-bool ModFileReader::Prescan(
-    const SourceName &modName, const std::string &path) {
-  std::stringstream fileError;
-  const auto *sourceFile{allSources_.Open(path, &fileError)};
-  if (sourceFile == nullptr) {
-    errors_.push_back(
-        Error(modName, "Cannot read %s: %s"_err_en_US, path, fileError.str()));
-    return false;
-  }
-  parser::Preprocessor preprocessor{allSources_};
-  parser::Messages messages;
-  parser::Prescanner prescanner{messages, *cooked_, preprocessor, {}};
-  parser::ProvenanceRange range{
-      allSources_.AddIncludedFile(*sourceFile, parser::ProvenanceRange{})};
-  prescanner.Prescan(range);
-  if (!messages.empty()) {
-    errors_.push_back(
-        Error(modName, "Module file for '%s' is corrupt: %s"_err_en_US,
-            modName.ToString(), path));
-    return false;
-  }
-  cooked_->Marshal();
-  return true;
-}
-
 static std::string ModFilePath(
     const std::string &dir, const std::string &modName) {
   if (dir == "."s) {