forked from solstice/solstice
Add argument parser, output files
This commit is contained in:
133
src/main.cpp
133
src/main.cpp
@@ -1,5 +1,6 @@
|
||||
#include <cctype>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <groundvm.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
@@ -867,17 +868,137 @@ namespace Solstice {
|
||||
|
||||
} // namespace Solstice
|
||||
|
||||
namespace ArgParser {
|
||||
|
||||
enum class ArgType {
|
||||
FILE, OUTPUT, OUTPUTTYPE
|
||||
};
|
||||
|
||||
class Argument {
|
||||
public:
|
||||
ArgType type;
|
||||
std::string value;
|
||||
Argument() = default;
|
||||
Argument(ArgType type, std::string value) : type(type), value(value) {}
|
||||
};
|
||||
|
||||
class Args {
|
||||
public:
|
||||
std::optional<Argument> output = {};
|
||||
std::optional<Argument> outputtype = {};
|
||||
std::optional<Argument> file = {};
|
||||
};
|
||||
|
||||
void printHelp() {
|
||||
std::cout << "Solstice compiler\n";
|
||||
std::cout << "This program takes a Solstice source file (.sols) and compiles it to Ground\n";
|
||||
std::cout << "Usage:\n";
|
||||
std::cout << " solstice inputFile [-h] [--help] [-o file] [--output file] [-t type] [--type type]\n";
|
||||
std::cout << "Options:\n";
|
||||
std::cout << " -h or --help\n";
|
||||
std::cout << " Shows this help message\n";
|
||||
std::cout << " -o file or --output file\n";
|
||||
std::cout << " Specifies where to output the compiled Ground program.\n";
|
||||
std::cout << " If this option is omitted, the program is automatically run.\n";
|
||||
std::cout << " -t type or --type type\n";
|
||||
std::cout << " Specifies the type of output.\n";
|
||||
std::cout << " Currently supported options:\n";
|
||||
std::cout << " text\n";
|
||||
}
|
||||
|
||||
Args parseArgs(int argc, char** argv) {
|
||||
if (argc < 2) {
|
||||
printHelp();
|
||||
exit(1);
|
||||
}
|
||||
Args args;
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
|
||||
printHelp();
|
||||
exit(1);
|
||||
}
|
||||
if (strcmp(argv[i], "-o") == 0 || strcmp(argv[i], "--output") == 0) {
|
||||
i++;
|
||||
if (i < argc) {
|
||||
if (args.output.has_value()) {
|
||||
std::cout << "(error) Multiple output values provided\n";
|
||||
exit(1);
|
||||
}
|
||||
args.output = Argument(ArgType::OUTPUT, std::string(argv[i]));
|
||||
continue;
|
||||
} else {
|
||||
std::cout << "(error) Please provide a filename to output to\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[i], "-t") == 0 || strcmp(argv[i], "--type") == 0) {
|
||||
i++;
|
||||
if (i < argc) {
|
||||
if (args.output.has_value()) {
|
||||
std::cout << "(error) Multiple type values provided\n";
|
||||
exit(1);
|
||||
}
|
||||
args.outputtype = Argument(ArgType::OUTPUTTYPE, std::string(argv[i]));
|
||||
continue;
|
||||
} else {
|
||||
std::cout << "(error) Please provide an output type\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (args.file.has_value()) {
|
||||
std::cout << "(error) Multiple input files provided\n";
|
||||
exit(1);
|
||||
}
|
||||
args.file = Argument(ArgType::FILE, std::string(argv[i]));
|
||||
}
|
||||
}
|
||||
if (!args.file.has_value()) {
|
||||
std::cout << "(error) No input file provided\n";
|
||||
exit(1);
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
} // namespace ArgParser
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 2) {
|
||||
std::cout << "Usage: " << argv[0] << " (file)\n";
|
||||
exit(1);
|
||||
}
|
||||
std::ifstream file(argv[1]);
|
||||
auto args = ArgParser::parseArgs(argc, argv);
|
||||
std::ifstream file(args.file->value);
|
||||
std::ostringstream ss;
|
||||
ss << file.rdbuf();
|
||||
auto lexed = Solstice::Lexer(ss.str()).lex();
|
||||
auto parsed = Solstice::Parser::Parser(lexed).parse();
|
||||
GroundProgram program = Solstice::Parser::assembleProgram(parsed);
|
||||
groundRunProgram(&program);
|
||||
if (args.output.has_value()) {
|
||||
std::FILE* originalStdout = stdout;
|
||||
std::FILE* tmp = std::tmpfile();
|
||||
if (!tmp) {
|
||||
std::cout << "Failed to create tmp file\n";
|
||||
exit(1);
|
||||
}
|
||||
stdout = tmp;
|
||||
groundPrintProgram(&program);
|
||||
std::fflush(tmp);
|
||||
std::fseek(tmp, 0, SEEK_END);
|
||||
long size = std::ftell(tmp);
|
||||
std::fseek(tmp, 0, SEEK_SET);
|
||||
|
||||
std::string result(size, '\0');
|
||||
std::fread(&result[0], 1, size, tmp);
|
||||
|
||||
stdout = originalStdout;
|
||||
std::fclose(tmp);
|
||||
|
||||
std::ofstream outputFile(args.output.value().value);
|
||||
if (!outputFile) {
|
||||
std::cout << "Failed to write to " << args.output.value().value << "\n";
|
||||
}
|
||||
outputFile << result;
|
||||
outputFile.close();
|
||||
exit(0);
|
||||
} else {
|
||||
groundRunProgram(&program);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user