✨ add demo format executable
This commit is contained in:
parent
c228dcc149
commit
277ddb9c0f
|
@ -50,7 +50,9 @@ cmake-windows-*
|
|||
*.out
|
||||
*.app
|
||||
nasal
|
||||
nasal-format
|
||||
nasal.exe
|
||||
nasal-format.exe
|
||||
|
||||
# Visual Studio specific
|
||||
*.sln
|
||||
|
|
|
@ -41,6 +41,7 @@ set(NASAL_OBJECT_SOURCE_FILE
|
|||
${CMAKE_SOURCE_DIR}/src/util/fs.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/util/util.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/ast_dumper.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/ast_format.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/ast_visitor.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/nasal_ast.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/nasal_codegen.cpp
|
||||
|
@ -62,12 +63,18 @@ target_include_directories(nasal-object PRIVATE ${CMAKE_SOURCE_DIR}/src)
|
|||
add_executable(nasal ${CMAKE_SOURCE_DIR}/src/main.cpp)
|
||||
target_link_libraries(nasal nasal-object)
|
||||
|
||||
# build nasal-format
|
||||
add_executable(nasal-format ${CMAKE_SOURCE_DIR}/src/format.cpp)
|
||||
target_link_libraries(nasal-format nasal-object)
|
||||
|
||||
# link ldl and lpthread
|
||||
if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
|
||||
target_link_libraries(nasal dl)
|
||||
target_link_libraries(nasal pthread)
|
||||
target_link_libraries(nasal-format pthread)
|
||||
endif()
|
||||
target_include_directories(nasal PRIVATE ${CMAKE_SOURCE_DIR}/src)
|
||||
target_include_directories(nasal-format PRIVATE ${CMAKE_SOURCE_DIR}/src)
|
||||
|
||||
# copy nasal from build dir to the outside dir
|
||||
if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
|
||||
|
@ -77,6 +84,12 @@ if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
|
|||
${CMAKE_SOURCE_DIR}/build/nasal
|
||||
${CMAKE_SOURCE_DIR}/nasal
|
||||
)
|
||||
add_custom_command(
|
||||
TARGET nasal-format POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
${CMAKE_SOURCE_DIR}/build/nasal-format
|
||||
${CMAKE_SOURCE_DIR}/nasal-format
|
||||
)
|
||||
endif()
|
||||
|
||||
# build module
|
||||
|
|
|
@ -38,7 +38,7 @@ private:
|
|||
if (indent.size() && indent.back()=="│ ") {
|
||||
indent.back() = "├──";
|
||||
}
|
||||
for(const auto& i : indent) {
|
||||
for (const auto& i : indent) {
|
||||
std::cout << i;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,412 @@
|
|||
#include "ast_format.h"
|
||||
#include "util/util.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace nasal {
|
||||
|
||||
bool ast_format::visit_use_stmt(use_stmt* node) {
|
||||
dump_formating_node_info(node, "use statement");
|
||||
out << "use ";
|
||||
for(auto i : node->get_path()) {
|
||||
i->accept(this);
|
||||
if (i != node->get_path().back()) {
|
||||
out << ".";
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_null_expr(null_expr* node) {
|
||||
dump_formating_node_info(node, "null expression");
|
||||
out << "null";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_nil_expr(nil_expr* node) {
|
||||
dump_formating_node_info(node, "nil expression");
|
||||
out << "nil";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_number_literal(number_literal* node) {
|
||||
dump_formating_node_info(node, "number expression");
|
||||
out << node->get_number();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_string_literal(string_literal* node) {
|
||||
dump_formating_node_info(node, "string expression");
|
||||
out << "\"" << util::rawstr(node->get_content()) << "\"";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_identifier(identifier* node) {
|
||||
dump_formating_node_info(node, "identifier");
|
||||
out << node->get_name();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_bool_literal(bool_literal* node) {
|
||||
dump_formating_node_info(node, "bool expression");
|
||||
out << (node->get_flag()? "true" : "false");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_vector_expr(vector_expr* node) {
|
||||
dump_formating_node_info(node, "vector expression");
|
||||
out << "[";
|
||||
for(auto i : node->get_elements()) {
|
||||
i->accept(this);
|
||||
if (i != node->get_elements().back()) {
|
||||
out << ", ";
|
||||
}
|
||||
}
|
||||
out << "]";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_hash_expr(hash_expr* node) {
|
||||
dump_formating_node_info(node, "hash expression");
|
||||
out << "{";
|
||||
for(auto i : node->get_members()) {
|
||||
i->accept(this);
|
||||
if (i != node->get_members().back()) {
|
||||
out << ", ";
|
||||
}
|
||||
}
|
||||
out << "}";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_hash_pair(hash_pair* node) {
|
||||
dump_formating_node_info(node, "hash pair");
|
||||
out << node->get_name();
|
||||
if (node->get_value()) {
|
||||
out << " : ";
|
||||
node->get_value()->accept(this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_function(function* node) {
|
||||
dump_formating_node_info(node, "function");
|
||||
out << "func(";
|
||||
for(auto i : node->get_parameter_list()) {
|
||||
i->accept(this);
|
||||
if (i != node->get_parameter_list().back()) {
|
||||
out << ", ";
|
||||
}
|
||||
}
|
||||
out << ") ";
|
||||
node->get_code_block()->accept(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_code_block(code_block* node) {
|
||||
dump_formating_node_info(node, "code block");
|
||||
out << "{\n";
|
||||
push_indent();
|
||||
for(auto i : node->get_expressions()) {
|
||||
dump_indent();
|
||||
i->accept(this);
|
||||
if (need_dump_semi(i)) {
|
||||
out << ";\n";
|
||||
} else {
|
||||
out << "\n";
|
||||
}
|
||||
}
|
||||
pop_indent();
|
||||
dump_indent();
|
||||
out << "}";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_parameter(parameter* node) {
|
||||
dump_formating_node_info(node, "parameter");
|
||||
out << node->get_parameter_name();
|
||||
switch (node->get_parameter_type()) {
|
||||
case parameter::kind::normal_parameter: break;
|
||||
case parameter::kind::dynamic_parameter: out << "..."; break;
|
||||
case parameter::kind::default_parameter: out << " = "; break;
|
||||
}
|
||||
if (node->get_default_value()) {
|
||||
node->get_default_value()->accept(this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_ternary_operator(ternary_operator* node) {
|
||||
dump_formating_node_info(node, "ternary operator");
|
||||
node->get_condition()->accept(this);
|
||||
out << " ? ";
|
||||
node->get_left()->accept(this);
|
||||
out << " : ";
|
||||
node->get_right()->accept(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_binary_operator(binary_operator* node) {
|
||||
dump_formating_node_info(node, "binary operator");
|
||||
out << "(";
|
||||
node->get_left()->accept(this);
|
||||
switch(node->get_operator_type()) {
|
||||
case binary_operator::kind::add: out << " + "; break;
|
||||
case binary_operator::kind::sub: out << " - "; break;
|
||||
case binary_operator::kind::mult: out << " * "; break;
|
||||
case binary_operator::kind::div: out << " / "; break;
|
||||
case binary_operator::kind::concat: out << " ~ "; break;
|
||||
case binary_operator::kind::bitwise_and: out << " & "; break;
|
||||
case binary_operator::kind::bitwise_or: out << " | "; break;
|
||||
case binary_operator::kind::bitwise_xor: out << " ^ "; break;
|
||||
case binary_operator::kind::cmpeq: out << " == "; break;
|
||||
case binary_operator::kind::cmpneq: out << " != "; break;
|
||||
case binary_operator::kind::grt: out << " > "; break;
|
||||
case binary_operator::kind::geq: out << " >= "; break;
|
||||
case binary_operator::kind::less: out << " < "; break;
|
||||
case binary_operator::kind::leq: out << " <= "; break;
|
||||
case binary_operator::kind::condition_and: out << " and "; break;
|
||||
case binary_operator::kind::condition_or: out << " or "; break;
|
||||
case binary_operator::kind::null_chain: out << " ?? "; break;
|
||||
}
|
||||
node->get_right()->accept(this);
|
||||
out << ")";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_unary_operator(unary_operator* node) {
|
||||
dump_formating_node_info(node, "unary operator");
|
||||
switch(node->get_operator_type()) {
|
||||
case unary_operator::kind::negative: out << "-"; break;
|
||||
case unary_operator::kind::logical_not: out << "!"; break;
|
||||
case unary_operator::kind::bitwise_not: out << "~"; break;
|
||||
}
|
||||
node->get_value()->accept(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_call_expr(call_expr* node) {
|
||||
dump_formating_node_info(node, "call expression");
|
||||
node->get_first()->accept(this);
|
||||
for(auto i : node->get_calls()) {
|
||||
i->accept(this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_call_hash(call_hash* node) {
|
||||
dump_formating_node_info(node, "call hash");
|
||||
out << "." << node->get_field();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_null_access(null_access* node) {
|
||||
dump_formating_node_info(node, "null access operator(?.)");
|
||||
out << "?." << node->get_field();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_call_vector(call_vector* node) {
|
||||
dump_formating_node_info(node, "call vector");
|
||||
out << "[";
|
||||
for(auto i : node->get_slices()) {
|
||||
i->accept(this);
|
||||
if (i != node->get_slices().back()) {
|
||||
out << ", ";
|
||||
}
|
||||
}
|
||||
out << "]";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_call_function(call_function* node) {
|
||||
dump_formating_node_info(node, "call function");
|
||||
out << "(";
|
||||
for(auto i : node->get_argument()) {
|
||||
i->accept(this);
|
||||
if (i != node->get_argument().back()) {
|
||||
out << ", ";
|
||||
}
|
||||
}
|
||||
out << ")";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_slice_vector(slice_vector* node) {
|
||||
dump_formating_node_info(node, "slice vector");
|
||||
node->get_begin()->accept(this);
|
||||
if (node->get_end()) {
|
||||
out << " : ";
|
||||
node->get_end()->accept(this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_definition_expr(definition_expr* node) {
|
||||
dump_formating_node_info(node, "definition");
|
||||
out << "var ";
|
||||
if (node->get_variable_name()) {
|
||||
node->get_variable_name()->accept(this);
|
||||
} else {
|
||||
node->get_variables()->accept(this);
|
||||
}
|
||||
out << " = ";
|
||||
if (node->get_tuple()) {
|
||||
node->get_tuple()->accept(this);
|
||||
} else {
|
||||
node->get_value()->accept(this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_assignment_expr(assignment_expr* node) {
|
||||
dump_formating_node_info(node, "assignment");
|
||||
node->get_left()->accept(this);
|
||||
switch(node->get_assignment_type()) {
|
||||
case assignment_expr::kind::add_equal: out << " += "; break;
|
||||
case assignment_expr::kind::sub_equal: out << " -= "; break;
|
||||
case assignment_expr::kind::mult_equal: out << " *= "; break;
|
||||
case assignment_expr::kind::div_equal: out << " /= "; break;
|
||||
case assignment_expr::kind::concat_equal: out << " ~= "; break;
|
||||
case assignment_expr::kind::equal: out << " = "; break;
|
||||
case assignment_expr::kind::bitwise_and_equal: out << " &= "; break;
|
||||
case assignment_expr::kind::bitwise_or_equal: out << " |= "; break;
|
||||
case assignment_expr::kind::bitwise_xor_equal: out << " ^= "; break;
|
||||
}
|
||||
node->get_right()->accept(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_multi_identifier(multi_identifier* node) {
|
||||
dump_formating_node_info(node, "multi identifier");
|
||||
out << "(";
|
||||
for(auto i : node->get_variables()) {
|
||||
i->accept(this);
|
||||
if (i != node->get_variables().back()) {
|
||||
out << ", ";
|
||||
}
|
||||
}
|
||||
out << ")";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_tuple_expr(tuple_expr* node) {
|
||||
dump_formating_node_info(node, "tuple expression");
|
||||
out << "(";
|
||||
for(auto i : node->get_elements()) {
|
||||
i->accept(this);
|
||||
if (i != node->get_elements().back()) {
|
||||
out << ", ";
|
||||
}
|
||||
}
|
||||
out << ")";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_multi_assign(multi_assign* node) {
|
||||
dump_formating_node_info(node, "multi assign");
|
||||
node->get_tuple()->accept(this);
|
||||
out << " = ";
|
||||
node->get_value()->accept(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_while_expr(while_expr* node) {
|
||||
dump_formating_node_info(node, "while statement");
|
||||
out << "while (";
|
||||
node->get_condition()->accept(this);
|
||||
out << ") ";
|
||||
node->get_code_block()->accept(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_for_expr(for_expr* node) {
|
||||
dump_formating_node_info(node, "for statement");
|
||||
out << "for (";
|
||||
node->get_initial()->accept(this);
|
||||
out << "; ";
|
||||
node->get_condition()->accept(this);
|
||||
out << "; ";
|
||||
node->get_step()->accept(this);
|
||||
out << ") ";
|
||||
node->get_code_block()->accept(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_iter_expr(iter_expr* node) {
|
||||
dump_formating_node_info(node, "iteration expression");
|
||||
if (node->is_definition()) {
|
||||
out << "var ";
|
||||
}
|
||||
if (node->get_name()) {
|
||||
node->get_name()->accept(this);
|
||||
} else {
|
||||
node->get_call()->accept(this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_forei_expr(forei_expr* node) {
|
||||
dump_formating_node_info(node, "forindex/foreach statement");
|
||||
if (node->get_loop_type()==forei_expr::kind::foreach) {
|
||||
out << "foreach ";
|
||||
} else {
|
||||
out << "forindex ";
|
||||
}
|
||||
out << "(";
|
||||
node->get_iterator()->accept(this);
|
||||
out << "; ";
|
||||
node->get_value()->accept(this);
|
||||
out << ") ";
|
||||
node->get_code_block()->accept(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_condition_expr(condition_expr* node) {
|
||||
dump_formating_node_info(node, "condition statement");
|
||||
out << "if ";
|
||||
node->get_if_statement()->accept(this);
|
||||
for (auto i : node->get_elsif_stataments()) {
|
||||
out << " elsif ";
|
||||
i->accept(this);
|
||||
}
|
||||
if (node->get_else_statement()) {
|
||||
out << " else ";
|
||||
node->get_else_statement()->accept(this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_if_expr(if_expr* node) {
|
||||
dump_formating_node_info(node, "if statement");
|
||||
if (node->get_condition()) {
|
||||
out << "(";
|
||||
node->get_condition()->accept(this);
|
||||
out << ") ";
|
||||
}
|
||||
node->get_code_block()->accept(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_continue_expr(continue_expr* node) {
|
||||
dump_formating_node_info(node, "continue statement");
|
||||
out << "continue";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_break_expr(break_expr* node) {
|
||||
dump_formating_node_info(node, "break statement");
|
||||
out << "break";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_format::visit_return_expr(return_expr* node) {
|
||||
dump_formating_node_info(node, "return statement");
|
||||
out << "return ";
|
||||
if (node->get_value()) {
|
||||
node->get_value()->accept(this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
#pragma once
|
||||
|
||||
#include "ast_visitor.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
namespace nasal {
|
||||
|
||||
class ast_format: public ast_visitor {
|
||||
private:
|
||||
std::ofstream out;
|
||||
std::vector<std::string> indent;
|
||||
|
||||
private:
|
||||
void push_indent() {
|
||||
indent.push_back(" ");
|
||||
}
|
||||
void pop_indent() {
|
||||
if (indent.size()) {
|
||||
indent.pop_back();
|
||||
}
|
||||
}
|
||||
void dump_indent() {
|
||||
for (const auto& i : indent) {
|
||||
out << i;
|
||||
}
|
||||
}
|
||||
void dump_formating_node_info(expr* n, const char* name) {
|
||||
std::cout << " formating " << name << " @ 0x";
|
||||
std::cout << std::hex << n << std::dec << "\n";
|
||||
}
|
||||
bool need_dump_semi(expr* n) {
|
||||
switch (n->get_type()) {
|
||||
case expr_type::ast_use:
|
||||
case expr_type::ast_null:
|
||||
case expr_type::ast_nil:
|
||||
case expr_type::ast_num:
|
||||
case expr_type::ast_str:
|
||||
case expr_type::ast_bool:
|
||||
case expr_type::ast_vec:
|
||||
case expr_type::ast_hash:
|
||||
case expr_type::ast_call: return true;
|
||||
case expr_type::ast_def: {
|
||||
auto dn = reinterpret_cast<definition_expr*>(n);
|
||||
if (dn->get_value() &&
|
||||
dn->get_value()->get_type() == expr_type::ast_func) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case expr_type::ast_assign: {
|
||||
auto dn = reinterpret_cast<assignment_expr*>(n);
|
||||
if (dn->get_right() &&
|
||||
dn->get_right()->get_type() == expr_type::ast_func) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case expr_type::ast_ret: {
|
||||
auto dn = reinterpret_cast<return_expr*>(n);
|
||||
if (dn->get_value() &&
|
||||
dn->get_value()->get_type() == expr_type::ast_func) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
bool visit_use_stmt(use_stmt*) override;
|
||||
bool visit_null_expr(null_expr*) override;
|
||||
bool visit_nil_expr(nil_expr*) override;
|
||||
bool visit_number_literal(number_literal*) override;
|
||||
bool visit_string_literal(string_literal*) override;
|
||||
bool visit_identifier(identifier*) override;
|
||||
bool visit_bool_literal(bool_literal*) override;
|
||||
bool visit_vector_expr(vector_expr*) override;
|
||||
bool visit_hash_expr(hash_expr*) override;
|
||||
bool visit_hash_pair(hash_pair*) override;
|
||||
bool visit_function(function*) override;
|
||||
bool visit_code_block(code_block*) override;
|
||||
bool visit_parameter(parameter*) override;
|
||||
bool visit_ternary_operator(ternary_operator*) override;
|
||||
bool visit_binary_operator(binary_operator*) override;
|
||||
bool visit_unary_operator(unary_operator*) override;
|
||||
bool visit_call_expr(call_expr*) override;
|
||||
bool visit_call_hash(call_hash*) override;
|
||||
bool visit_null_access(null_access*) override;
|
||||
bool visit_call_vector(call_vector*) override;
|
||||
bool visit_call_function(call_function*) override;
|
||||
bool visit_slice_vector(slice_vector*) override;
|
||||
bool visit_definition_expr(definition_expr*) override;
|
||||
bool visit_assignment_expr(assignment_expr*) override;
|
||||
bool visit_multi_identifier(multi_identifier*) override;
|
||||
bool visit_tuple_expr(tuple_expr*) override;
|
||||
bool visit_multi_assign(multi_assign*) override;
|
||||
bool visit_while_expr(while_expr*) override;
|
||||
bool visit_for_expr(for_expr*) override;
|
||||
bool visit_iter_expr(iter_expr*) override;
|
||||
bool visit_forei_expr(forei_expr*) override;
|
||||
bool visit_condition_expr(condition_expr*) override;
|
||||
bool visit_if_expr(if_expr*) override;
|
||||
bool visit_continue_expr(continue_expr*) override;
|
||||
bool visit_break_expr(break_expr*) override;
|
||||
bool visit_return_expr(return_expr*) override;
|
||||
|
||||
public:
|
||||
ast_format(const std::string output_file): out(output_file) {
|
||||
if (out.fail()) {
|
||||
throw std::runtime_error("can't open file: " + output_file);
|
||||
}
|
||||
}
|
||||
|
||||
void do_format(code_block* root) {
|
||||
std::cout << "nasal-format is not stable right now, ";
|
||||
std::cout << "take care of source code!\n";
|
||||
dump_formating_node_info(root, "program root");
|
||||
bool is_use_statement = true;
|
||||
for (auto i : root->get_expressions()) {
|
||||
if (is_use_statement && i->get_type() != expr_type::ast_use) {
|
||||
is_use_statement = false;
|
||||
out << "\n";
|
||||
}
|
||||
|
||||
i->accept(this);
|
||||
if (need_dump_semi(i)) {
|
||||
out << ";\n";
|
||||
} else {
|
||||
out << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -1,6 +1,12 @@
|
|||
#include "nasal.h"
|
||||
#include "cli/cli.h"
|
||||
#include "util/util.h"
|
||||
#include "nasal_parse.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
|
||||
namespace nasal::cli {
|
||||
|
||||
|
@ -59,4 +65,75 @@ std::ostream& help(std::ostream& out) {
|
|||
return out;
|
||||
}
|
||||
|
||||
std::ostream& nasal_format_help(std::ostream& out) {
|
||||
out
|
||||
<< "\n"
|
||||
<< " ,--#-,\n"
|
||||
<< "<3 / \\____\\ <3\n"
|
||||
<< " |_|__A_|\n"
|
||||
<< "\nnasal-format <option>\n"
|
||||
<< "option:\n"
|
||||
<< " -h, --help | get help.\n"
|
||||
<< " -v, --version | get version.\n"
|
||||
<< "\nnasal-format <file>\n"
|
||||
<< "file:\n"
|
||||
<< " <filename> | file to be formatted.\n"
|
||||
<< "\n";
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& logo(std::ostream& out) {
|
||||
out
|
||||
<< "\n"
|
||||
<< " __ _\n"
|
||||
<< " /\\ \\ \\__ _ ___ __ _| |\n"
|
||||
<< " / \\/ / _` / __|/ _` | |\n"
|
||||
<< " / /\\ / (_| \\__ \\ (_| | |\n"
|
||||
<< " \\_\\ \\/ \\__,_|___/\\__,_|_|\n"
|
||||
<< "\n"
|
||||
<< "ver : " << __nasver__
|
||||
<< " " << nasal::util::get_platform()
|
||||
<< " " << nasal::util::get_arch()
|
||||
<< " (" << __DATE__ << " " << __TIME__ << ")\n"
|
||||
<< "std : c++ " << __cplusplus << "\n"
|
||||
<< "core : " << std::thread::hardware_concurrency() << " core(s)\n"
|
||||
<< "repo : https://github.com/ValKmjolnir/Nasal-Interpreter\n"
|
||||
<< "repo : https://gitee.com/valkmjolnir/Nasal-Interpreter\n"
|
||||
<< "wiki : https://wiki.flightgear.org/Nasal_scripting_language\n"
|
||||
<< "\n"
|
||||
<< "presented by fgprc members:\n"
|
||||
<< " - http://fgprc.org\n"
|
||||
<< " - http://fgprc.org.cn\n"
|
||||
<< "\n"
|
||||
<< "input <nasal-format -h> to get help.\n\n";
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& version(std::ostream& out) {
|
||||
std::srand(static_cast<u32>(std::time(nullptr)));
|
||||
|
||||
f64 num = 0;
|
||||
for(u32 i = 0; i<5; ++i) {
|
||||
num = (num+rand())*(1.0/(RAND_MAX+1.0));
|
||||
}
|
||||
// give you 5% to see this easter egg
|
||||
if (num<0.05) {
|
||||
nasal::parse::easter_egg();
|
||||
}
|
||||
|
||||
out << "nasal version " << __nasver__;
|
||||
out << " " << nasal::util::get_platform();
|
||||
out << " " << nasal::util::get_arch();
|
||||
out << " (" << __DATE__ << " " << __TIME__ << ")\n";
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& nasal_format_version(std::ostream& out) {
|
||||
out << "nasal-format version " << __nasver__ << "-beta";
|
||||
out << " " << nasal::util::get_platform();
|
||||
out << " " << nasal::util::get_arch();
|
||||
out << " (" << __DATE__ << " " << __TIME__ << ")\n";
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
|
@ -69,5 +69,10 @@ const std::unordered_map<std::string, option> cli_options = {
|
|||
cli_config parse(const std::vector<std::string>&);
|
||||
|
||||
std::ostream& help(std::ostream&);
|
||||
std::ostream& nasal_format_help(std::ostream&);
|
||||
|
||||
std::ostream& logo(std::ostream&);
|
||||
std::ostream& version(std::ostream&);
|
||||
std::ostream& nasal_format_version(std::ostream&);
|
||||
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
#include "nasal.h"
|
||||
#include "nasal_lexer.h"
|
||||
#include "nasal_ast.h"
|
||||
#include "nasal_parse.h"
|
||||
#include "util/util.h"
|
||||
#include "cli/cli.h"
|
||||
#include "ast_format.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
[[noreturn]]
|
||||
void err() {
|
||||
std::cerr << "invalid argument(s), use <nasal-format -h> to get help.\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
void execute(const nasal::cli::cli_config& config) {
|
||||
nasal::lexer lex;
|
||||
nasal::parse parse;
|
||||
|
||||
// lexer scans file to get tokens
|
||||
lex.scan(config.input_file_path).chkerr();
|
||||
|
||||
// parser gets lexer's token list to compile
|
||||
parse.compile(lex).chkerr();
|
||||
|
||||
nasal::ast_format("nasal-format-out.nas").do_format(parse.tree());
|
||||
}
|
||||
|
||||
int main(i32 argc, const char* argv[]) {
|
||||
// output version info
|
||||
if (argc <= 1) {
|
||||
err();
|
||||
} else if (argc > 2) {
|
||||
err();
|
||||
}
|
||||
|
||||
// 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) {
|
||||
if (config.has(nasal::cli::option::cli_help)) {
|
||||
std::clog << nasal::cli::nasal_format_help;
|
||||
} else if (config.has(nasal::cli::option::cli_version)) {
|
||||
std::clog << nasal::cli::nasal_format_version;
|
||||
} else if (config.input_file_path.size()) {
|
||||
execute(config);
|
||||
} else {
|
||||
err();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
55
src/main.cpp
55
src/main.cpp
|
@ -18,55 +18,8 @@
|
|||
#include "repl/repl.h"
|
||||
#include "cli/cli.h"
|
||||
|
||||
#include <thread>
|
||||
#include <cstdlib>
|
||||
|
||||
std::ostream& logo(std::ostream& out) {
|
||||
out
|
||||
<< "\n"
|
||||
<< " __ _\n"
|
||||
<< " /\\ \\ \\__ _ ___ __ _| |\n"
|
||||
<< " / \\/ / _` / __|/ _` | |\n"
|
||||
<< " / /\\ / (_| \\__ \\ (_| | |\n"
|
||||
<< " \\_\\ \\/ \\__,_|___/\\__,_|_|\n"
|
||||
<< "\n"
|
||||
<< "ver : " << __nasver__
|
||||
<< " " << nasal::util::get_platform()
|
||||
<< " " << nasal::util::get_arch()
|
||||
<< " (" << __DATE__ << " " << __TIME__ << ")\n"
|
||||
<< "std : c++ " << __cplusplus << "\n"
|
||||
<< "core : " << std::thread::hardware_concurrency() << " core(s)\n"
|
||||
<< "repo : https://github.com/ValKmjolnir/Nasal-Interpreter\n"
|
||||
<< "repo : https://gitee.com/valkmjolnir/Nasal-Interpreter\n"
|
||||
<< "wiki : https://wiki.flightgear.org/Nasal_scripting_language\n"
|
||||
<< "\n"
|
||||
<< "presented by fgprc members:\n"
|
||||
<< " - http://fgprc.org\n"
|
||||
<< " - http://fgprc.org.cn\n"
|
||||
<< "\n"
|
||||
<< "input <nasal -h> to get help.\n\n";
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& version(std::ostream& out) {
|
||||
std::srand(static_cast<u32>(std::time(nullptr)));
|
||||
|
||||
f64 num = 0;
|
||||
for(u32 i = 0; i<5; ++i) {
|
||||
num = (num+rand())*(1.0/(RAND_MAX+1.0));
|
||||
}
|
||||
// give you 5% to see this easter egg
|
||||
if (num<0.05) {
|
||||
nasal::parse::easter_egg();
|
||||
}
|
||||
|
||||
out << "nasal version " << __nasver__;
|
||||
out << " " << nasal::util::get_platform();
|
||||
out << " " << nasal::util::get_arch();
|
||||
out << " (" << __DATE__ << " " << __TIME__ << ")\n";
|
||||
return out;
|
||||
}
|
||||
|
||||
[[noreturn]]
|
||||
void err() {
|
||||
std::cerr << "invalid argument(s), use <nasal -h> to get help.\n";
|
||||
|
@ -157,8 +110,8 @@ void execute(const nasal::cli::cli_config& config) {
|
|||
|
||||
i32 main(i32 argc, const char* argv[]) {
|
||||
// output version info
|
||||
if (argc<=1) {
|
||||
std::clog << logo;
|
||||
if (argc <= 1) {
|
||||
std::clog << nasal::cli::logo;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -166,11 +119,11 @@ i32 main(i32 argc, const char* argv[]) {
|
|||
const auto config = nasal::cli::parse({argv+1, argv+argc});
|
||||
|
||||
// run directly or show help
|
||||
if (argc==2) {
|
||||
if (argc == 2) {
|
||||
if (config.has(nasal::cli::option::cli_help)) {
|
||||
std::clog << nasal::cli::help;
|
||||
} else if (config.has(nasal::cli::option::cli_version)) {
|
||||
std::clog << version;
|
||||
std::clog << nasal::cli::version;
|
||||
} else if (config.has(nasal::cli::option::cli_repl_mode)) {
|
||||
auto repl = std::make_unique<nasal::repl::repl>();
|
||||
repl->execute();
|
||||
|
|
Loading…
Reference in New Issue