llvm/flang/lib/parser/parsing.cc
peter klausler 75b29335ab [flang] Clean out obsolete parsing code. Handle !cdir$ fixed and free in parser.
Work on scanning compiler directive lines.

Fix glitch in earlier change to parse-state.h.

Add ClassifyLine(), simplify some token sequence data lifetimes and interfaces.

Handle continued directives.  Obey !DIR$ FIXED and FREE in prescanner.

Some refactoring of TokenSequence API, then support initial directives (FIXED, FREE, IGNORE_TKR).

Fix !DIR$ IGNORE_TKR syntax, manual was wrong.

Debugging directive scanning & parsing.

Profiling-directed speed-up - do not map cooked source locations to Provenance until a Message is emitted.  Turn some non-nullable pointers into references.

Debugging.

Handle !DIR$ IVDEP too, it is in a test.

Accept directives in the execution part.

Original-commit: flang-compiler/f18@fb2ff367ec
Reviewed-on: https://github.com/flang-compiler/f18/pull/34
Tree-same-pre-rewrite: false
2018-03-28 15:04:36 -07:00

99 lines
3.1 KiB
C++

#include "parsing.h"
#include "grammar.h"
#include "message.h"
#include "preprocessor.h"
#include "prescan.h"
#include "provenance.h"
#include "source.h"
#include <sstream>
namespace Fortran {
namespace parser {
bool Parsing::Prescan(const std::string &path, Options options) {
options_ = options;
std::stringstream fileError;
const auto *sourceFile = allSources_.Open(path, &fileError);
if (sourceFile == nullptr) {
ProvenanceRange range{allSources_.AddCompilerInsertion(path)};
MessageFormattedText msg("%s"_en_US, fileError.str().data());
messages_.Put(Message(range.start(), std::move(msg)));
anyFatalError_ = true;
return false;
}
if (sourceFile->bytes() == 0) {
ProvenanceRange range{allSources_.AddCompilerInsertion(path)};
messages_.Put(Message{range.start(), "file is empty"_en_US});
anyFatalError_ = true;
return false;
}
for (const auto &path : options.searchDirectories) {
allSources_.PushSearchPathDirectory(path);
}
Preprocessor preprocessor{allSources_};
for (const auto &predef : options.predefinitions) {
if (predef.second.has_value()) {
preprocessor.Define(predef.first, *predef.second);
} else {
preprocessor.Undefine(predef.first);
}
}
Prescanner prescanner{messages_, cooked_, preprocessor};
prescanner.set_fixedForm(options.isFixedForm)
.set_fixedFormColumnLimit(options.fixedFormColumns)
.set_encoding(options.encoding)
.set_enableBackslashEscapesInCharLiterals(options.enableBackslashEscapes)
.set_enableOldDebugLines(options.enableOldDebugLines)
.AddCompilerDirectiveSentinel("dir$");
ProvenanceRange range{
allSources_.AddIncludedFile(*sourceFile, ProvenanceRange{})};
anyFatalError_ = !prescanner.Prescan(range);
if (anyFatalError_) {
return false;
}
cooked_.Marshal();
return true;
}
void Parsing::DumpCookedChars(std::ostream &out) const {
if (anyFatalError_) {
return;
}
UserState userState;
ParseState parseState{cooked_};
parseState.set_inFixedForm(options_.isFixedForm).set_userState(&userState);
while (std::optional<char> ch{parseState.GetNextChar()}) {
out << *ch;
}
}
void Parsing::DumpProvenance(std::ostream &out) const { cooked_.Dump(out); }
bool Parsing::Parse() {
if (anyFatalError_) {
return false;
}
UserState userState;
ParseState parseState{cooked_};
parseState.set_inFixedForm(options_.isFixedForm)
.set_encoding(options_.encoding)
.set_warnOnNonstandardUsage(options_.isStrictlyStandard)
.set_warnOnDeprecatedUsage(options_.isStrictlyStandard)
.set_userState(&userState);
parseTree_ = program.Parse(&parseState);
anyFatalError_ = parseState.anyErrorRecovery();
#if 0 // pgf90 -Mstandard enables warnings only, they aren't fatal.
// TODO: -Werror
|| (options_.isStrictlyStandard && parseState.anyConformanceViolation());
#endif
consumedWholeFile_ = parseState.IsAtEnd();
finalRestingPlace_ = parseState.GetProvenance();
messages_.Annex(parseState.messages());
return parseTree_.has_value() && !anyFatalError_;
}
} // namespace parser
} // namespace Fortran