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