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