✨ using new cli parser
This commit is contained in:
parent
40a53a4224
commit
2c6a0fd84d
|
@ -1,7 +1,26 @@
|
|||
#include "cli/cli.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace nasal::cli {
|
||||
|
||||
cli_config parse(const std::vector<std::string>& args) {
|
||||
cli_config result;
|
||||
|
||||
for(const auto& arg : args) {
|
||||
if (cli_options.count(arg)) {
|
||||
result.options.insert(cli_options.at(arg));
|
||||
} else if (!result.input_file_path.length()) {
|
||||
result.input_file_path = arg;
|
||||
} else {
|
||||
result.nasal_vm_args.push_back(arg);
|
||||
}
|
||||
}
|
||||
|
||||
if (result.input_file_path.length() && result.options.empty()) {
|
||||
result.options.insert(option::cli_execute);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
|
@ -3,6 +3,8 @@
|
|||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
namespace nasal::cli {
|
||||
|
||||
|
@ -16,7 +18,7 @@ enum class option {
|
|||
cli_show_symbol,
|
||||
cli_execute,
|
||||
cli_show_execute_time,
|
||||
cli_show_detail_info,
|
||||
cli_detail_info,
|
||||
cli_show_referenced_file,
|
||||
cli_debug_mode,
|
||||
cli_profile,
|
||||
|
@ -24,9 +26,17 @@ enum class option {
|
|||
cli_limit_mode
|
||||
};
|
||||
|
||||
using config = std::unordered_map<option, std::string>;
|
||||
struct cli_config {
|
||||
std::string input_file_path = "";
|
||||
std::unordered_set<option> options = {};
|
||||
std::vector<std::string> nasal_vm_args = {};
|
||||
|
||||
const std::unordered_map<std::string, option> options = {
|
||||
bool has(option opt) const {
|
||||
return options.count(opt);
|
||||
}
|
||||
};
|
||||
|
||||
const std::unordered_map<std::string, option> cli_options = {
|
||||
{"-h", option::cli_help},
|
||||
{"--help", option::cli_help},
|
||||
{"-v", option::cli_version},
|
||||
|
@ -44,6 +54,8 @@ const std::unordered_map<std::string, option> options = {
|
|||
{"--exec", option::cli_execute},
|
||||
{"-t", option::cli_show_execute_time},
|
||||
{"--time", option::cli_show_execute_time},
|
||||
{"-d", option::cli_detail_info},
|
||||
{"--detail", option::cli_detail_info},
|
||||
{"-f", option::cli_show_referenced_file},
|
||||
{"--ref-file", option::cli_show_referenced_file},
|
||||
{"-dbg", option::cli_debug_mode},
|
||||
|
@ -53,4 +65,6 @@ const std::unordered_map<std::string, option> options = {
|
|||
{"--limit", option::cli_limit_mode}
|
||||
};
|
||||
|
||||
cli_config parse(const std::vector<std::string>&);
|
||||
|
||||
}
|
100
src/main.cpp
100
src/main.cpp
|
@ -119,10 +119,8 @@ void err() {
|
|||
std::exit(1);
|
||||
}
|
||||
|
||||
void execute(const std::string& file,
|
||||
const std::vector<std::string>& argv,
|
||||
const u32 cmd) {
|
||||
|
||||
void execute(const nasal::cli::cli_config& config) {
|
||||
using option = nasal::cli::option;
|
||||
using clk = std::chrono::high_resolution_clock;
|
||||
const auto den = clk::duration::period::den;
|
||||
|
||||
|
@ -132,17 +130,17 @@ void execute(const std::string& file,
|
|||
nasal::codegen gen;
|
||||
|
||||
// lexer scans file to get tokens
|
||||
lex.scan(file).chkerr();
|
||||
lex.scan(config.input_file_path).chkerr();
|
||||
|
||||
// parser gets lexer's token list to compile
|
||||
parse.compile(lex).chkerr();
|
||||
if (cmd&VM_RAW_AST) {
|
||||
if (config.has(option::cli_view_raw_ast)) {
|
||||
nasal::ast_dumper().dump(parse.tree());
|
||||
}
|
||||
|
||||
// linker gets parser's ast and load import files to this ast
|
||||
ld.link(parse, cmd&VM_DETAIL).chkerr();
|
||||
if (cmd&VM_REF_FILE) {
|
||||
ld.link(parse, config.has(option::cli_detail_info)).chkerr();
|
||||
if (config.has(option::cli_show_referenced_file)) {
|
||||
if (ld.get_file_list().size()) {
|
||||
std::cout << "referenced file(s):\n";
|
||||
}
|
||||
|
@ -154,34 +152,43 @@ void execute(const std::string& file,
|
|||
// optimizer does simple optimization on ast
|
||||
auto opt = std::make_unique<nasal::optimizer>();
|
||||
opt->do_optimization(parse.tree());
|
||||
if (cmd&VM_AST) {
|
||||
if (config.has(option::cli_view_ast)) {
|
||||
nasal::ast_dumper().dump(parse.tree());
|
||||
}
|
||||
|
||||
// code generator gets parser's ast and import file list to generate code
|
||||
gen.compile(parse, ld, false, cmd&VM_LIMIT).chkerr();
|
||||
if (cmd&VM_CODE) {
|
||||
gen.compile(parse, ld, false, config.has(option::cli_limit_mode)).chkerr();
|
||||
if (config.has(option::cli_view_code)) {
|
||||
gen.print(std::cout);
|
||||
}
|
||||
if (cmd&VM_SYMINFO) {
|
||||
if (config.has(option::cli_show_symbol)) {
|
||||
gen.symbol_dump(std::cout);
|
||||
}
|
||||
|
||||
// run
|
||||
const auto start = clk::now();
|
||||
if (cmd&VM_DEBUG) {
|
||||
if (config.has(option::cli_debug_mode)) {
|
||||
auto debugger = std::make_unique<nasal::dbg>();
|
||||
debugger->run(gen, ld, argv, cmd&VM_PROFILE, cmd&VM_PROF_ALL);
|
||||
} else if (cmd&VM_TIME || cmd&VM_EXEC) {
|
||||
debugger->run(
|
||||
gen,
|
||||
ld,
|
||||
config.nasal_vm_args,
|
||||
config.has(option::cli_profile),
|
||||
config.has(option::cli_profile_all)
|
||||
);
|
||||
} else if (config.has(option::cli_show_execute_time) ||
|
||||
config.has(option::cli_detail_info) ||
|
||||
config.has(option::cli_limit_mode) ||
|
||||
config.has(option::cli_execute)) {
|
||||
auto runtime = std::make_unique<nasal::vm>();
|
||||
runtime->set_detail_report_info(cmd&VM_DETAIL);
|
||||
runtime->set_limit_mode_flag(cmd&VM_LIMIT);
|
||||
runtime->run(gen, ld, argv);
|
||||
runtime->set_detail_report_info(config.has(option::cli_detail_info));
|
||||
runtime->set_limit_mode_flag(config.has(option::cli_limit_mode));
|
||||
runtime->run(gen, ld, config.nasal_vm_args);
|
||||
}
|
||||
|
||||
// get running time
|
||||
const auto end = clk::now();
|
||||
if (cmd&VM_TIME) {
|
||||
if (config.has(option::cli_show_execute_time)) {
|
||||
std::clog << "process exited after ";
|
||||
std::clog << static_cast<f64>((end-start).count())/den << "s.\n\n";
|
||||
}
|
||||
|
@ -194,18 +201,20 @@ i32 main(i32 argc, const char* argv[]) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
// the first argument is the executable itself, ignore it
|
||||
const auto config = nasal::cli::parse({argv+1, argv+argc});
|
||||
|
||||
// run directly or show help
|
||||
if (argc==2) {
|
||||
std::string s(argv[1]);
|
||||
if (s=="-h" || s=="--help") {
|
||||
if (config.has(nasal::cli::option::cli_help)) {
|
||||
std::clog << help;
|
||||
} else if (s=="-v" || s=="--version") {
|
||||
} else if (config.has(nasal::cli::option::cli_version)) {
|
||||
std::clog << version;
|
||||
} else if (s=="-r" || s=="--repl") {
|
||||
} else if (config.has(nasal::cli::option::cli_repl_mode)) {
|
||||
auto repl = std::make_unique<nasal::repl::repl>();
|
||||
repl->execute();
|
||||
} else if (s[0]!='-') {
|
||||
execute(s, {}, VM_EXEC);
|
||||
} else if (config.input_file_path.size()) {
|
||||
execute(config);
|
||||
} else {
|
||||
err();
|
||||
}
|
||||
|
@ -213,45 +222,6 @@ i32 main(i32 argc, const char* argv[]) {
|
|||
}
|
||||
|
||||
// execute with arguments
|
||||
const std::unordered_map<std::string, u32> command_list = {
|
||||
{"--raw-ast", VM_RAW_AST},
|
||||
{"--ast", VM_AST},
|
||||
{"-a", VM_AST},
|
||||
{"--code", VM_CODE},
|
||||
{"-c", VM_CODE},
|
||||
{"--symbol", VM_SYMINFO},
|
||||
{"-s", VM_SYMINFO},
|
||||
{"--exec", VM_EXEC},
|
||||
{"-e", VM_EXEC},
|
||||
{"--time", VM_TIME|VM_EXEC},
|
||||
{"-t", VM_TIME|VM_EXEC},
|
||||
{"--detail", VM_DETAIL|VM_EXEC},
|
||||
{"-d", VM_DETAIL|VM_EXEC},
|
||||
{"--debug", VM_DEBUG},
|
||||
{"-dbg", VM_DEBUG},
|
||||
{"--prof", VM_PROFILE},
|
||||
{"--prof-all", VM_PROF_ALL},
|
||||
{"-f", VM_REF_FILE},
|
||||
{"--ref-file", VM_REF_FILE},
|
||||
{"--limit", VM_LIMIT|VM_EXEC}
|
||||
};
|
||||
|
||||
u32 commands = 0;
|
||||
std::string filename = "";
|
||||
std::vector<std::string> vm_argv;
|
||||
for(i32 i = 1; i<argc; ++i) {
|
||||
if (command_list.count(argv[i])) {
|
||||
commands |= command_list.at(argv[i]);
|
||||
} else if (!filename.length()) {
|
||||
filename = argv[i];
|
||||
} else {
|
||||
vm_argv.push_back(argv[i]);
|
||||
}
|
||||
}
|
||||
if (!filename.length()) {
|
||||
err();
|
||||
}
|
||||
|
||||
execute(filename, vm_argv, commands? commands:VM_EXEC);
|
||||
execute(config);
|
||||
return 0;
|
||||
}
|
|
@ -75,6 +75,11 @@ void lexer::open(const std::string& file) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (file.empty()) {
|
||||
err.err("lexer", "empty input file");
|
||||
err.chkerr();
|
||||
}
|
||||
|
||||
// check file exsits and it is a regular file
|
||||
if (!fs::is_regular(file)) {
|
||||
err.err("lexer", "<"+file+"> is not a regular file");
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
use std.runtime;
|
||||
|
||||
runtime.windows.set_utf8_output();
|
||||
|
||||
var table_character_set = [
|
||||
"─", "━", "│", "┃", "╌", "╍", "╎", "╏", "┄", "┅",
|
||||
"┆", "┇", "┈", "┉", "┊", "┋", "┌", "┍", "┎", "┏",
|
||||
|
@ -83,6 +87,9 @@ var choice = func(above_block_char,
|
|||
append(possible, bcs);
|
||||
}
|
||||
}
|
||||
if (!size(possible)) {
|
||||
return " ";
|
||||
}
|
||||
|
||||
func() {
|
||||
if (vecindex(possible, " ")!=nil) {
|
||||
|
|
Loading…
Reference in New Issue