// Temporary Fortran front end driver main program for development scaffolding. #include "basic-parsers.h" #include "char-buffer.h" #include "cooked-chars.h" #include "grammar.h" #include "idioms.h" #include "message.h" #include "parse-tree.h" #include "prescan.h" #include "source.h" #include "user-state.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace { std::list argList(int argc, char *const argv[]) { std::list result; for (int j = 0; j < argc; ++j) { result.emplace_back(argv[j]); } return result; } } // namespace namespace Fortran { constexpr auto grammar = program; } // namespace Fortran using Fortran::grammar; int main(int argc, char *const argv[]) { auto args = argList(argc, argv); std::string progName{args.front()}; args.pop_front(); bool dumpCookedChars{false}; bool fixedForm{false}; bool backslashEscapes{true}; bool standard{false}; bool enableOldDebugLines{false}; int columns{72}; bool prescan{true}; while (!args.empty()) { if (args.front().empty()) { args.pop_front(); } else if (args.front().at(0) != '-' || args.front() == "-") { break; } else if (args.front() == "--") { args.pop_front(); break; } else { std::string flag{std::move(args.front())}; args.pop_front(); if (flag == "-Mfixed") { fixedForm = true; } else if (flag == "-Mbackslash") { backslashEscapes = false; } else if (flag == "-Mstandard") { standard = false; } else if (flag == "-Mextend") { columns = 132; } else if (flag == "-fdebug-dump-cooked-chars") { dumpCookedChars = true; } else if (flag == "-fno-prescan") { prescan = false; } else if (flag == "-ed") { enableOldDebugLines = true; } else { std::cerr << "unknown flag: '" << flag << "'\n"; return 1; } } } std::string path{"-"}; if (!args.empty()) { path = std::move(args.front()); args.pop_front(); if (!args.empty()) { std::cerr << "multiple input files\n"; ; return 1; } } Fortran::SourceFile source; std::stringstream error; if (!source.Open(path, &error)) { std::cerr << error.str() << '\n'; return 1; } const char *sourceContent{source.content()}; size_t sourceBytes{source.bytes()}; std::unique_ptr prescanned; if (prescan) { Fortran::Messages messages; Fortran::Prescanner prescanner{messages}; Fortran::CharBuffer buffer{ prescanner.set_fixedForm(fixedForm) .set_enableBackslashEscapesInCharLiterals(backslashEscapes) .set_fixedFormColumnLimit(columns) .set_enableOldDebugLines(enableOldDebugLines) .Prescan(source)}; std::cerr << messages; if (prescanner.anyFatalErrors()) { return 1; } sourceBytes = buffer.bytes(); char *contig{new char[sourceBytes]}; buffer.CopyToContiguous(contig); sourceContent = contig; prescanned.reset(contig); columns = std::numeric_limits::max(); } Fortran::ParseState state{sourceContent, sourceBytes}; state.set_prescanned(prescan); state.set_inFixedForm(fixedForm); state.set_enableBackslashEscapesInCharLiterals(backslashEscapes); state.set_strictConformance(standard); state.set_columns(columns); state.set_enableOldDebugLines(enableOldDebugLines); state.PushContext("source file '"s + path + "'"); Fortran::UserState ustate; state.set_userState(&ustate); if (dumpCookedChars) { while (std::optional och{Fortran::cookedNextChar.Parse(&state)}) { std::cout << *och; } return 0; } std::optional result; #if 0 for (int j = 0; j < 1000; ++j) { Fortran::ParseState state1{state}; result = grammar.Parse(&state1); if (!result) { std::cerr << "demo FAIL in timing loop\n"; break; } } #endif result = grammar.Parse(&state); if (result.has_value() && !state.anyErrorRecovery()) { std::cout << "demo PASS\n" << *result << '\n'; } else { std::cerr << "demo FAIL " << state.position() << '\n' << *state.messages(); return EXIT_FAILURE; } }