xref: /llvm-project/flang/lib/Parser/parsing.cpp (revision 46ade6d0ef8fea94fbc28c75bb4bed4d928fd64b)
164ab3302SCarolineConcatto //===-- lib/Parser/parsing.cpp --------------------------------------------===//
264ab3302SCarolineConcatto //
364ab3302SCarolineConcatto // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
464ab3302SCarolineConcatto // See https://llvm.org/LICENSE.txt for license information.
564ab3302SCarolineConcatto // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
664ab3302SCarolineConcatto //
764ab3302SCarolineConcatto //===----------------------------------------------------------------------===//
864ab3302SCarolineConcatto 
964ab3302SCarolineConcatto #include "flang/Parser/parsing.h"
1064ab3302SCarolineConcatto #include "preprocessor.h"
1164ab3302SCarolineConcatto #include "prescan.h"
1264ab3302SCarolineConcatto #include "type-parsers.h"
1364ab3302SCarolineConcatto #include "flang/Parser/message.h"
1464ab3302SCarolineConcatto #include "flang/Parser/provenance.h"
1564ab3302SCarolineConcatto #include "flang/Parser/source.h"
168670e499SCaroline Concatto #include "llvm/Support/raw_ostream.h"
1764ab3302SCarolineConcatto 
1864ab3302SCarolineConcatto namespace Fortran::parser {
1964ab3302SCarolineConcatto 
2092a54197Speter klausler Parsing::Parsing(AllCookedSources &allCooked) : allCooked_{allCooked} {}
2164ab3302SCarolineConcatto Parsing::~Parsing() {}
2264ab3302SCarolineConcatto 
2364ab3302SCarolineConcatto const SourceFile *Parsing::Prescan(const std::string &path, Options options) {
2464ab3302SCarolineConcatto   options_ = options;
2592a54197Speter klausler   AllSources &allSources{allCooked_.allSources()};
2664ab3302SCarolineConcatto   if (options.isModuleFile) {
2764ab3302SCarolineConcatto     for (const auto &path : options.searchDirectories) {
286110e771Speter klausler       allSources.AppendSearchPathDirectory(path);
2964ab3302SCarolineConcatto     }
3064ab3302SCarolineConcatto   }
3164ab3302SCarolineConcatto 
328670e499SCaroline Concatto   std::string buf;
338670e499SCaroline Concatto   llvm::raw_string_ostream fileError{buf};
3464ab3302SCarolineConcatto   const SourceFile *sourceFile;
3564ab3302SCarolineConcatto   if (path == "-") {
368670e499SCaroline Concatto     sourceFile = allSources.ReadStandardInput(fileError);
3764ab3302SCarolineConcatto   } else {
386110e771Speter klausler     std::optional<std::string> currentDirectory{"."};
396110e771Speter klausler     sourceFile = allSources.Open(path, fileError, std::move(currentDirectory));
4064ab3302SCarolineConcatto   }
4164ab3302SCarolineConcatto   if (!fileError.str().empty()) {
4264ab3302SCarolineConcatto     ProvenanceRange range{allSources.AddCompilerInsertion(path)};
4364ab3302SCarolineConcatto     messages_.Say(range, "%s"_err_en_US, fileError.str());
4464ab3302SCarolineConcatto     return sourceFile;
4564ab3302SCarolineConcatto   }
4664ab3302SCarolineConcatto   CHECK(sourceFile);
4764ab3302SCarolineConcatto 
4864ab3302SCarolineConcatto   if (!options.isModuleFile) {
4964ab3302SCarolineConcatto     // For .mod files we always want to look in the search directories.
506110e771Speter klausler     // For normal source files we don't add them until after the primary
5164ab3302SCarolineConcatto     // source file has been opened.  If foo.f is missing from the current
5264ab3302SCarolineConcatto     // working directory, we don't want to accidentally read another foo.f
5364ab3302SCarolineConcatto     // from another directory that's on the search path.
5464ab3302SCarolineConcatto     for (const auto &path : options.searchDirectories) {
556110e771Speter klausler       allSources.AppendSearchPathDirectory(path);
5664ab3302SCarolineConcatto     }
5764ab3302SCarolineConcatto   }
5864ab3302SCarolineConcatto 
5964ab3302SCarolineConcatto   Preprocessor preprocessor{allSources};
608880a63aSpeter klausler   if (!options.predefinitions.empty()) {
618880a63aSpeter klausler     preprocessor.DefineStandardMacros();
6264ab3302SCarolineConcatto     for (const auto &predef : options.predefinitions) {
6364ab3302SCarolineConcatto       if (predef.second) {
6464ab3302SCarolineConcatto         preprocessor.Define(predef.first, *predef.second);
6564ab3302SCarolineConcatto       } else {
6664ab3302SCarolineConcatto         preprocessor.Undefine(predef.first);
6764ab3302SCarolineConcatto       }
6864ab3302SCarolineConcatto     }
698880a63aSpeter klausler   }
7092a54197Speter klausler   currentCooked_ = &allCooked_.NewCookedSource();
7192a54197Speter klausler   Prescanner prescanner{
7201def7f7Speter klausler       messages_, *currentCooked_, preprocessor, options.features};
7364ab3302SCarolineConcatto   prescanner.set_fixedForm(options.isFixedForm)
7464ab3302SCarolineConcatto       .set_fixedFormColumnLimit(options.fixedFormColumns)
7564ab3302SCarolineConcatto       .AddCompilerDirectiveSentinel("dir$");
760a90ffa7SValentin Clement   if (options.features.IsEnabled(LanguageFeature::OpenACC)) {
770a90ffa7SValentin Clement     prescanner.AddCompilerDirectiveSentinel("$acc");
780a90ffa7SValentin Clement   }
7964ab3302SCarolineConcatto   if (options.features.IsEnabled(LanguageFeature::OpenMP)) {
8064ab3302SCarolineConcatto     prescanner.AddCompilerDirectiveSentinel("$omp");
8164ab3302SCarolineConcatto     prescanner.AddCompilerDirectiveSentinel("$"); // OMP conditional line
8264ab3302SCarolineConcatto   }
8364ab3302SCarolineConcatto   ProvenanceRange range{allSources.AddIncludedFile(
8464ab3302SCarolineConcatto       *sourceFile, ProvenanceRange{}, options.isModuleFile)};
8564ab3302SCarolineConcatto   prescanner.Prescan(range);
8692a54197Speter klausler   if (currentCooked_->BufferedBytes() == 0 && !options.isModuleFile) {
8764ab3302SCarolineConcatto     // Input is empty.  Append a newline so that any warning
8864ab3302SCarolineConcatto     // message about nonstandard usage will have provenance.
8992a54197Speter klausler     currentCooked_->Put('\n', range.start());
9064ab3302SCarolineConcatto   }
91*46ade6d0Speter klausler   currentCooked_->Marshal(allCooked_);
9264ab3302SCarolineConcatto   if (options.needProvenanceRangeToCharBlockMappings) {
9392a54197Speter klausler     currentCooked_->CompileProvenanceRangeToOffsetMappings(allSources);
9464ab3302SCarolineConcatto   }
9564ab3302SCarolineConcatto   return sourceFile;
9664ab3302SCarolineConcatto }
9764ab3302SCarolineConcatto 
988670e499SCaroline Concatto void Parsing::DumpCookedChars(llvm::raw_ostream &out) const {
9992a54197Speter klausler   UserState userState{allCooked_, common::LanguageFeatureControl{}};
10092a54197Speter klausler   ParseState parseState{cooked()};
10164ab3302SCarolineConcatto   parseState.set_inFixedForm(options_.isFixedForm).set_userState(&userState);
10264ab3302SCarolineConcatto   while (std::optional<const char *> p{parseState.GetNextChar()}) {
10364ab3302SCarolineConcatto     out << **p;
10464ab3302SCarolineConcatto   }
10564ab3302SCarolineConcatto }
10664ab3302SCarolineConcatto 
1078670e499SCaroline Concatto void Parsing::DumpProvenance(llvm::raw_ostream &out) const {
10892a54197Speter klausler   allCooked_.Dump(out);
1098670e499SCaroline Concatto }
11064ab3302SCarolineConcatto 
1118670e499SCaroline Concatto void Parsing::DumpParsingLog(llvm::raw_ostream &out) const {
11292a54197Speter klausler   log_.Dump(out, allCooked_);
11364ab3302SCarolineConcatto }
11464ab3302SCarolineConcatto 
1158670e499SCaroline Concatto void Parsing::Parse(llvm::raw_ostream &out) {
11692a54197Speter klausler   UserState userState{allCooked_, options_.features};
11764ab3302SCarolineConcatto   userState.set_debugOutput(out)
11864ab3302SCarolineConcatto       .set_instrumentedParse(options_.instrumentedParse)
11964ab3302SCarolineConcatto       .set_log(&log_);
12092a54197Speter klausler   ParseState parseState{cooked()};
12164ab3302SCarolineConcatto   parseState.set_inFixedForm(options_.isFixedForm).set_userState(&userState);
12264ab3302SCarolineConcatto   parseTree_ = program.Parse(parseState);
12364ab3302SCarolineConcatto   CHECK(
12464ab3302SCarolineConcatto       !parseState.anyErrorRecovery() || parseState.messages().AnyFatalError());
12564ab3302SCarolineConcatto   consumedWholeFile_ = parseState.IsAtEnd();
12664ab3302SCarolineConcatto   messages_.Annex(std::move(parseState.messages()));
12764ab3302SCarolineConcatto   finalRestingPlace_ = parseState.GetLocation();
12864ab3302SCarolineConcatto }
12964ab3302SCarolineConcatto 
13064ab3302SCarolineConcatto void Parsing::ClearLog() { log_.clear(); }
13164ab3302SCarolineConcatto 
1321f879005STim Keith } // namespace Fortran::parser
133