forked from OSchip/llvm-project
[flang] Refactor ModFileReader to use parser::Parsing
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@9088891ab2 Reviewed-on: https://github.com/flang-compiler/f18/pull/149 Tree-same-pre-rewrite: false
This commit is contained in:
parent
fb8950ee93
commit
9e48304374
|
@ -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;
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -15,11 +15,8 @@
|
|||
#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) {
|
||||
|
|
Loading…
Reference in New Issue