diff --git a/clang-tools-extra/pseudo/gen/Main.cpp b/clang-tools-extra/pseudo/gen/Main.cpp --- a/clang-tools-extra/pseudo/gen/Main.cpp +++ b/clang-tools-extra/pseudo/gen/Main.cpp @@ -15,13 +15,17 @@ #include "clang-pseudo/Grammar.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/ToolOutputFile.h" #include using llvm::cl::desc; using llvm::cl::init; using llvm::cl::opt; +using llvm::cl::Required; +using llvm::cl::value_desc; using llvm::cl::values; namespace { @@ -31,13 +35,17 @@ }; opt Grammar("grammar", desc("Parse a BNF grammar file."), - init("")); + Required); opt Emit(desc("which information to emit:"), values(clEnumValN(EmitSymbolList, "emit-symbol-list", "Print nonterminal symbols (default)"), clEnumValN(EmitGrammarContent, "emit-grammar-content", "Print the BNF grammar content as a string"))); + +opt OutputFilename("o", init("-"), desc("Output"), + value_desc("file")); + std::string readOrDie(llvm::StringRef Path) { llvm::ErrorOr> Text = llvm::MemoryBuffer::getFile(Path); @@ -52,10 +60,6 @@ int main(int argc, char *argv[]) { llvm::cl::ParseCommandLineOptions(argc, argv, ""); - if (!Grammar.getNumOccurrences()) { - llvm::errs() << "Grammar file must be provided!\n"; - return 1; - } std::string GrammarText = readOrDie(Grammar); std::vector Diags; @@ -65,25 +69,34 @@ llvm::errs() << llvm::join(Diags, "\n"); return 1; } - switch (Emit) { + std::error_code EC; + llvm::ToolOutputFile Out{OutputFilename, EC, llvm::sys::fs::OF_None}; + if (EC) { + llvm::errs() << EC.message() << '\n'; + return 1; + } + + switch (Emit) { case EmitSymbolList: for (clang::pseudo::SymbolID ID = 0; ID < G->table().Nonterminals.size(); ++ID) { std::string Name = G->symbolName(ID).str(); // translation-unit -> translation_unit std::replace(Name.begin(), Name.end(), '-', '_'); - llvm::outs() << (llvm::formatv("NONTERMINAL({0}, {1})\n", Name, ID)); + Out.os() << llvm::formatv("NONTERMINAL({0}, {1})\n", Name, ID); } break; case EmitGrammarContent: for (llvm::StringRef Line : llvm::split(GrammarText, '\n')) { - llvm::outs() << '"'; - llvm::outs().write_escaped((Line + "\n").str()); - llvm::outs() << "\"\n"; + Out.os() << '"'; + Out.os().write_escaped((Line + "\n").str()); + Out.os() << "\"\n"; } break; } + Out.keep(); + return 0; } diff --git a/clang-tools-extra/pseudo/include/CMakeLists.txt b/clang-tools-extra/pseudo/include/CMakeLists.txt --- a/clang-tools-extra/pseudo/include/CMakeLists.txt +++ b/clang-tools-extra/pseudo/include/CMakeLists.txt @@ -7,7 +7,7 @@ COMMAND "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/pseudo-gen" --grammar ${cxx_bnf} --emit-symbol-list - > ${cxx_symbols_inc} + -o ${cxx_symbols_inc} COMMENT "Generating nonterminal symbol file for cxx grammar..." DEPENDS pseudo-gen VERBATIM) @@ -17,7 +17,7 @@ COMMAND "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/pseudo-gen" --grammar ${cxx_bnf} --emit-grammar-content - > ${cxx_bnf_inc} + -o ${cxx_bnf_inc} COMMENT "Generating bnf string file for cxx grammar..." DEPENDS pseudo-gen VERBATIM)