✨ change ast used in parser
This commit is contained in:
parent
0132ca0870
commit
2ce13e2134
|
@ -58,3 +58,301 @@ hash_pair::~hash_pair() {
|
||||||
void hash_pair::accept(ast_visitor* visitor) {
|
void hash_pair::accept(ast_visitor* visitor) {
|
||||||
visitor->visit_hash_pair(this);
|
visitor->visit_hash_pair(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function::~function() {
|
||||||
|
for(auto i : parameter_list) {
|
||||||
|
delete i;
|
||||||
|
}
|
||||||
|
if (block) {
|
||||||
|
delete block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void function::accept(ast_visitor* visitor) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
code_block::~code_block() {
|
||||||
|
for(auto i : expressions) {
|
||||||
|
delete i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void code_block::accept(ast_visitor* visitor) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
parameter::~parameter() {
|
||||||
|
if (name) {
|
||||||
|
delete name;
|
||||||
|
}
|
||||||
|
if (default_value) {
|
||||||
|
delete default_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void parameter::accept(ast_visitor* visitor) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
ternary_operator::~ternary_operator() {
|
||||||
|
if (condition) {
|
||||||
|
delete condition;
|
||||||
|
}
|
||||||
|
if (left) {
|
||||||
|
delete left;
|
||||||
|
}
|
||||||
|
if (right) {
|
||||||
|
delete right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ternary_operator::accept(ast_visitor* visitor) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
binary_operator::~binary_operator() {
|
||||||
|
if (left) {
|
||||||
|
delete left;
|
||||||
|
}
|
||||||
|
if (right) {
|
||||||
|
delete right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void binary_operator::accept(ast_visitor* visitor) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
unary_operator::~unary_operator() {
|
||||||
|
if (value) {
|
||||||
|
delete value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void unary_operator::accept(ast_visitor* visitor) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
call_expr::~call_expr() {
|
||||||
|
if(first) {
|
||||||
|
delete first;
|
||||||
|
}
|
||||||
|
for(auto i : calls) {
|
||||||
|
delete i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void call_expr::accept(ast_visitor* visitor) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void call_hash::accept(ast_visitor* visitor) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
call_vector::~call_vector() {
|
||||||
|
for(auto i : calls) {
|
||||||
|
delete i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void call_vector::accept(ast_visitor* visitor) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
call_function::~call_function() {
|
||||||
|
for(auto i : args) {
|
||||||
|
delete i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void call_function::accept(ast_visitor* visitor) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
slice_vector::~slice_vector() {
|
||||||
|
if (begin) {
|
||||||
|
delete begin;
|
||||||
|
}
|
||||||
|
if (end) {
|
||||||
|
delete end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void slice_vector::accept(ast_visitor* visitor) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
definition_expr::~definition_expr() {
|
||||||
|
if (variable_name) {
|
||||||
|
delete variable_name;
|
||||||
|
}
|
||||||
|
if (variables) {
|
||||||
|
delete variables;
|
||||||
|
}
|
||||||
|
if (value) {
|
||||||
|
delete value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void definition_expr::accept(ast_visitor* visitor) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
assignment_expr::~assignment_expr() {
|
||||||
|
if (left) {
|
||||||
|
delete left;
|
||||||
|
}
|
||||||
|
if (right) {
|
||||||
|
delete right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void assignment_expr::accept(ast_visitor* visitor) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
multi_define::~multi_define() {
|
||||||
|
for(auto i : variables) {
|
||||||
|
delete i;
|
||||||
|
}
|
||||||
|
if (value) {
|
||||||
|
delete value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void multi_define::accept(ast_visitor* visitor) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
tuple_expr::~tuple_expr() {
|
||||||
|
for(auto i : elements) {
|
||||||
|
delete i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tuple_expr::accept(ast_visitor* visitor) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
multi_assign::~multi_assign() {
|
||||||
|
if (left) {
|
||||||
|
delete left;
|
||||||
|
}
|
||||||
|
if (right) {
|
||||||
|
delete right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void multi_assign::accept(ast_visitor* visitor) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
while_expr::~while_expr() {
|
||||||
|
if (condition) {
|
||||||
|
delete condition;
|
||||||
|
}
|
||||||
|
if (block) {
|
||||||
|
delete block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void while_expr::accept(ast_visitor* visitor) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
for_expr::~for_expr() {
|
||||||
|
if (initializing) {
|
||||||
|
delete initializing;
|
||||||
|
}
|
||||||
|
if (condition) {
|
||||||
|
delete condition;
|
||||||
|
}
|
||||||
|
if (step) {
|
||||||
|
delete step;
|
||||||
|
}
|
||||||
|
if (block) {
|
||||||
|
delete block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void for_expr::accept(ast_visitor* visitor) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
iter_expr::~iter_expr() {
|
||||||
|
if (name) {
|
||||||
|
delete name;
|
||||||
|
}
|
||||||
|
if (call) {
|
||||||
|
delete call;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void iter_expr::accept(ast_visitor* visitor) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
forei_expr::~forei_expr() {
|
||||||
|
if (iterator) {
|
||||||
|
delete iterator;
|
||||||
|
}
|
||||||
|
if (vector_node) {
|
||||||
|
delete vector_node;
|
||||||
|
}
|
||||||
|
if (block) {
|
||||||
|
delete block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void forei_expr::accept(ast_visitor* visitor) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
condition_expr::~condition_expr() {
|
||||||
|
if (if_stmt) {
|
||||||
|
delete if_stmt;
|
||||||
|
}
|
||||||
|
for(auto i : elsif_stmt) {
|
||||||
|
delete i;
|
||||||
|
}
|
||||||
|
if (else_stmt) {
|
||||||
|
delete else_stmt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void condition_expr::accept(ast_visitor* visitor) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
if_expr::~if_expr() {
|
||||||
|
if (condition) {
|
||||||
|
delete condition;
|
||||||
|
}
|
||||||
|
if (block) {
|
||||||
|
delete block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void if_expr::accept(ast_visitor* visitor) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void continue_expr::accept(ast_visitor* visitor) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void break_expr::accept(ast_visitor* visitor) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
return_expr::~return_expr() {
|
||||||
|
if (value) {
|
||||||
|
delete value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void return_expr::accept(ast_visitor* visitor) {
|
||||||
|
// TODO
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "nasal.h"
|
#include "nasal_new_header.h"
|
||||||
#include "nasal_err.h"
|
#include "nasal_new_err.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
@ -51,6 +51,7 @@ enum class expr_type:u32 {
|
||||||
ast_multi_id, // multi identifiers sub-tree
|
ast_multi_id, // multi identifiers sub-tree
|
||||||
ast_tuple,
|
ast_tuple,
|
||||||
ast_def, // definition
|
ast_def, // definition
|
||||||
|
ast_assign,
|
||||||
ast_multi_assign,
|
ast_multi_assign,
|
||||||
ast_continue, // continue keyword, only used in loop
|
ast_continue, // continue keyword, only used in loop
|
||||||
ast_break, // break keyword, only used in loop
|
ast_break, // break keyword, only used in loop
|
||||||
|
@ -88,7 +89,7 @@ public:
|
||||||
nd_loc.end_line = location.end_line;
|
nd_loc.end_line = location.end_line;
|
||||||
nd_loc.end_column = location.end_column;
|
nd_loc.end_column = location.end_column;
|
||||||
}
|
}
|
||||||
virtual void accept(ast_visitor*);
|
void accept(ast_visitor*);
|
||||||
};
|
};
|
||||||
|
|
||||||
class null_expr:public expr {
|
class null_expr:public expr {
|
||||||
|
@ -115,6 +116,7 @@ public:
|
||||||
number_literal(const span& location, const f64 num):
|
number_literal(const span& location, const f64 num):
|
||||||
expr(location, expr_type::ast_num), number(num) {}
|
expr(location, expr_type::ast_num), number(num) {}
|
||||||
~number_literal() = default;
|
~number_literal() = default;
|
||||||
|
f64 get_number() const {return number;}
|
||||||
void accept(ast_visitor*) override;
|
void accept(ast_visitor*) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -126,6 +128,7 @@ public:
|
||||||
string_literal(const span& location, const std::string& str):
|
string_literal(const span& location, const std::string& str):
|
||||||
expr(location, expr_type::ast_str), content(str) {}
|
expr(location, expr_type::ast_str), content(str) {}
|
||||||
~string_literal() = default;
|
~string_literal() = default;
|
||||||
|
const std::string get_content() const {return content;}
|
||||||
void accept(ast_visitor*) override;
|
void accept(ast_visitor*) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -137,6 +140,7 @@ public:
|
||||||
identifier(const span& location, const std::string& str):
|
identifier(const span& location, const std::string& str):
|
||||||
expr(location, expr_type::ast_id), name(str) {}
|
expr(location, expr_type::ast_id), name(str) {}
|
||||||
~identifier() = default;
|
~identifier() = default;
|
||||||
|
const std::string get_name() const {return name;}
|
||||||
void accept(ast_visitor*) override;
|
void accept(ast_visitor*) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -346,7 +350,7 @@ public:
|
||||||
call_hash(const span& location, const std::string& name):
|
call_hash(const span& location, const std::string& name):
|
||||||
expr(location, expr_type::ast_callh),
|
expr(location, expr_type::ast_callh),
|
||||||
field(name) {}
|
field(name) {}
|
||||||
~call_hash();
|
~call_hash() = default;
|
||||||
void accept(ast_visitor*) override;
|
void accept(ast_visitor*) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -405,6 +409,42 @@ public:
|
||||||
void set_identifier(identifier* node) {variable_name = node;}
|
void set_identifier(identifier* node) {variable_name = node;}
|
||||||
void set_multi_define(multi_define* node) {variables = node;}
|
void set_multi_define(multi_define* node) {variables = node;}
|
||||||
void set_value(expr* node) {value = node;}
|
void set_value(expr* node) {value = node;}
|
||||||
|
|
||||||
|
expr* get_value() {return value;}
|
||||||
|
void accept(ast_visitor*) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class assignment_expr:public expr {
|
||||||
|
public:
|
||||||
|
enum class assign_type {
|
||||||
|
equal,
|
||||||
|
add_equal,
|
||||||
|
sub_equal,
|
||||||
|
mult_equal,
|
||||||
|
div_equal,
|
||||||
|
concat_equal,
|
||||||
|
bitwise_and_equal,
|
||||||
|
bitwise_or_equal,
|
||||||
|
bitwise_xor_equal
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
assign_type type;
|
||||||
|
expr* left;
|
||||||
|
expr* right;
|
||||||
|
|
||||||
|
public:
|
||||||
|
assignment_expr(const span& location):
|
||||||
|
expr(location, expr_type::ast_assign),
|
||||||
|
left(nullptr), right(nullptr) {}
|
||||||
|
~assignment_expr();
|
||||||
|
void set_type(assign_type operator_type) {type = operator_type;}
|
||||||
|
void set_left(expr* node) {left = node;}
|
||||||
|
void set_right(expr* node) {right = node;}
|
||||||
|
|
||||||
|
assign_type get_type() const {return type;}
|
||||||
|
expr* get_left() {return left;}
|
||||||
|
expr* get_right() {return right;}
|
||||||
void accept(ast_visitor*) override;
|
void accept(ast_visitor*) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,163 @@
|
||||||
|
#include "nasal_new_err.h"
|
||||||
|
|
||||||
|
std::ostream& back_white(std::ostream& s) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0xf0);
|
||||||
|
#else
|
||||||
|
s<<"\033[7m";
|
||||||
|
#endif
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& red(std::ostream& s) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0c);
|
||||||
|
#else
|
||||||
|
s<<"\033[91;1m";
|
||||||
|
#endif
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& cyan(std::ostream& s) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x03);
|
||||||
|
#else
|
||||||
|
s<<"\033[36;1m";
|
||||||
|
#endif
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& orange(std::ostream& s) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0e);
|
||||||
|
#else
|
||||||
|
s<<"\033[93;1m";
|
||||||
|
#endif
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& white(std::ostream& s) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0f);
|
||||||
|
#else
|
||||||
|
s<<"\033[0m\033[1m";
|
||||||
|
#endif
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& reset(std::ostream& s) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), reset_ter_color.scr.wAttributes);
|
||||||
|
#else
|
||||||
|
s<<"\033[0m";
|
||||||
|
#endif
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void flstream::load(const std::string& f) {
|
||||||
|
if (file==f) { // don't need to load a loaded file
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
file=f;
|
||||||
|
}
|
||||||
|
|
||||||
|
res.clear();
|
||||||
|
std::ifstream in(f, std::ios::binary);
|
||||||
|
if (in.fail()) {
|
||||||
|
std::cerr<<red<<"src: "<<reset<<"cannot open <"<<f<<">\n";
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
while(!in.eof()) {
|
||||||
|
std::string line;
|
||||||
|
std::getline(in, line);
|
||||||
|
res.push_back(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void error::fatal(const std::string& stage, const std::string& info) {
|
||||||
|
std::cerr<<red<<stage<<": "<<white<<info<<reset<<"\n";
|
||||||
|
if (file.length()) {
|
||||||
|
std::cerr<<cyan<<" --> "<<red<<file<<reset<<"\n\n";
|
||||||
|
} else {
|
||||||
|
std::cerr<<reset<<"\n";
|
||||||
|
}
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void error::err(const std::string& stage, const std::string& info) {
|
||||||
|
++cnt;
|
||||||
|
std::cerr<<red<<stage<<": "<<white<<info<<reset<<"\n";
|
||||||
|
if (file.length()) {
|
||||||
|
std::cerr<<cyan<<" --> "<<red<<file<<reset<<"\n\n";
|
||||||
|
} else {
|
||||||
|
std::cerr<<reset<<"\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void error::err(
|
||||||
|
const std::string& stage, const span& loc, const std::string& info) {
|
||||||
|
// load error occurred file into string lines
|
||||||
|
load(loc.file);
|
||||||
|
|
||||||
|
++cnt;
|
||||||
|
|
||||||
|
std::cerr
|
||||||
|
<<red<<stage<<": "<<white<<info<<reset<<"\n"<<cyan<<" --> "
|
||||||
|
<<red<<loc.file<<":"<<loc.begin_line<<":"<<loc.begin_column+1<<reset<<"\n";
|
||||||
|
|
||||||
|
const usize maxlen = std::to_string(loc.end_line).length();
|
||||||
|
const std::string iden = identation(maxlen);
|
||||||
|
|
||||||
|
for(u32 line=loc.begin_line; line<=loc.end_line; ++line) {
|
||||||
|
if (!line) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loc.begin_line<line && line<loc.end_line) {
|
||||||
|
if (line==loc.begin_line+1) {
|
||||||
|
std::cerr<<cyan<<iden<<" | "<<reset<<"...\n"<<cyan<<iden<<" | "<<reset<<"\n";
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this line has nothing, skip
|
||||||
|
if (!res[line-1].length() && line!=loc.end_line) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& code=res[line-1];
|
||||||
|
std::cerr<<cyan<<leftpad(line, maxlen)<<" | "<<reset<<code<<"\n";
|
||||||
|
// output underline
|
||||||
|
std::cerr<<cyan<<iden<<" | "<<reset;
|
||||||
|
if (loc.begin_line==loc.end_line) {
|
||||||
|
for(u32 i=0; i<loc.begin_column; ++i) {
|
||||||
|
std::cerr<<char(" \t"[code[i]=='\t']);
|
||||||
|
}
|
||||||
|
for(u32 i=loc.begin_column ;i<loc.end_column; ++i) {
|
||||||
|
std::cerr<<red<<(code[i]=='\t'?"^^^^":"^")<<reset;
|
||||||
|
}
|
||||||
|
} else if (line==loc.begin_line) {
|
||||||
|
for(u32 i=0; i<loc.begin_column; ++i) {
|
||||||
|
std::cerr<<char(" \t"[code[i]=='\t']);
|
||||||
|
}
|
||||||
|
for(u32 i=loc.begin_column; i<code.size(); ++i) {
|
||||||
|
std::cerr<<red<<(code[i]=='\t'?"^^^^":"^")<<reset;
|
||||||
|
}
|
||||||
|
} else if (loc.begin_line<line && line<loc.end_line) {
|
||||||
|
for(u32 i=0; i<code.size(); ++i) {
|
||||||
|
std::cerr<<red<<(code[i]=='\t'?"^^^^":"^");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for(u32 i=0; i<loc.end_column; ++i) {
|
||||||
|
std::cerr<<red<<(code[i]=='\t'?"^^^^":"^");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (line==loc.end_line) {
|
||||||
|
std::cerr<<reset;
|
||||||
|
} else {
|
||||||
|
std::cerr<<reset<<"\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cerr<<"\n\n";
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream> // MSVC need this to use std::getline
|
||||||
|
#include <cstring>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "nasal_new_header.h"
|
||||||
|
|
||||||
|
struct span {
|
||||||
|
u32 begin_line;
|
||||||
|
u32 begin_column;
|
||||||
|
u32 end_line;
|
||||||
|
u32 end_column;
|
||||||
|
std::string file;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h> // use SetConsoleTextAttribute
|
||||||
|
struct for_reset {
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO scr;
|
||||||
|
for_reset() {
|
||||||
|
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &scr);
|
||||||
|
}
|
||||||
|
} reset_ter_color;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::ostream& back_white(std::ostream&);
|
||||||
|
std::ostream& red(std::ostream&);
|
||||||
|
std::ostream& cyan(std::ostream&);
|
||||||
|
std::ostream& orange(std::ostream&);
|
||||||
|
std::ostream& white(std::ostream&);
|
||||||
|
std::ostream& reset(std::ostream&);
|
||||||
|
|
||||||
|
class flstream {
|
||||||
|
protected:
|
||||||
|
std::string file;
|
||||||
|
std::vector<std::string> res;
|
||||||
|
public:
|
||||||
|
flstream():file("") {}
|
||||||
|
void load(const std::string&);
|
||||||
|
const std::string& operator[](usize n) const {return res[n];}
|
||||||
|
const std::string& name() const {return file;}
|
||||||
|
usize size() const {return res.size();}
|
||||||
|
};
|
||||||
|
|
||||||
|
class error:public flstream {
|
||||||
|
private:
|
||||||
|
u32 cnt; // counter for errors
|
||||||
|
|
||||||
|
std::string identation(usize len) {
|
||||||
|
return std::string(len,' ');
|
||||||
|
}
|
||||||
|
std::string leftpad(u32 num, usize len) {
|
||||||
|
auto tmp = std::to_string(num);
|
||||||
|
while(tmp.length()<len) {
|
||||||
|
tmp=" "+tmp;
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
error():cnt(0) {}
|
||||||
|
void fatal(const std::string&, const std::string&);
|
||||||
|
void err(const std::string&, const std::string&);
|
||||||
|
void err(const std::string&, const span&, const std::string&);
|
||||||
|
|
||||||
|
void chkerr() const {
|
||||||
|
if (cnt) {
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,51 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef __nasver
|
||||||
|
#define __nasver "10.1"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <cstring>
|
||||||
|
#include <cmath>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
bool is_windows();
|
||||||
|
bool is_linux();
|
||||||
|
bool is_macos();
|
||||||
|
bool is_x86();
|
||||||
|
bool is_amd64();
|
||||||
|
bool is_x86_64();
|
||||||
|
bool is_arm();
|
||||||
|
bool is_aarch64();
|
||||||
|
bool is_ia64();
|
||||||
|
bool is_powerpc();
|
||||||
|
bool is_superh();
|
||||||
|
|
||||||
|
using i32 = std::int32_t;
|
||||||
|
using i64 = std::int64_t;
|
||||||
|
using u8 = std::uint8_t;
|
||||||
|
using u16 = std::uint16_t;
|
||||||
|
using u32 = std::uint32_t;
|
||||||
|
using u64 = std::uint64_t;
|
||||||
|
using usize = std::size_t;
|
||||||
|
using f64 = double;
|
||||||
|
|
||||||
|
const u32 STACK_DEPTH=1024;
|
||||||
|
|
||||||
|
f64 hex2f(const char*);
|
||||||
|
f64 oct2f(const char*);
|
||||||
|
|
||||||
|
// we have the same reason not using atof here
|
||||||
|
// just as andy's interpreter does.
|
||||||
|
// it is not platform independent, and may have strange output.
|
||||||
|
// so we write a new function here to convert str to number manually.
|
||||||
|
// but this also makes 0.1+0.2==0.3,
|
||||||
|
// not another result that you may get in other languages.
|
||||||
|
f64 dec2f(const char*);
|
||||||
|
|
||||||
|
f64 str2num(const char*);
|
||||||
|
i32 utf8_hdchk(const char);
|
||||||
|
std::string chrhex(const char);
|
||||||
|
std::string rawstr(const std::string&, const usize maxlen=0);
|
|
@ -59,7 +59,7 @@ void lexer::err_char() {
|
||||||
err.fatal("lexer", "fatal error occurred, stop");
|
err.fatal("lexer", "fatal error occurred, stop");
|
||||||
}
|
}
|
||||||
|
|
||||||
void lexer::open(const string& file) {
|
void lexer::open(const std::string& file) {
|
||||||
// check file exsits and it is a regular file
|
// check file exsits and it is a regular file
|
||||||
struct stat buffer;
|
struct stat buffer;
|
||||||
if (stat(file.c_str(), &buffer)==0 && !S_ISREG(buffer.st_mode)) {
|
if (stat(file.c_str(), &buffer)==0 && !S_ISREG(buffer.st_mode)) {
|
||||||
|
@ -80,14 +80,14 @@ void lexer::open(const string& file) {
|
||||||
res=ss.str();
|
res=ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
tok lexer::get_type(const string& str) {
|
tok lexer::get_type(const std::string& str) {
|
||||||
return typetbl.count(str)?typetbl.at(str):tok::null;
|
return typetbl.count(str)?typetbl.at(str):tok::null;
|
||||||
}
|
}
|
||||||
|
|
||||||
string lexer::utf8_gen() {
|
std::string lexer::utf8_gen() {
|
||||||
string str="";
|
std::string str="";
|
||||||
while(ptr<res.size() && res[ptr]<0) {
|
while(ptr<res.size() && res[ptr]<0) {
|
||||||
string tmp="";
|
std::string tmp="";
|
||||||
u32 nbytes=utf8_hdchk(res[ptr]);
|
u32 nbytes=utf8_hdchk(res[ptr]);
|
||||||
if (!nbytes) {
|
if (!nbytes) {
|
||||||
++ptr;
|
++ptr;
|
||||||
|
@ -105,7 +105,7 @@ string lexer::utf8_gen() {
|
||||||
// utf8 character's total length is 1+nbytes
|
// utf8 character's total length is 1+nbytes
|
||||||
if (tmp.length()!=1+nbytes) {
|
if (tmp.length()!=1+nbytes) {
|
||||||
++column;
|
++column;
|
||||||
string utf_info="0x"+chrhex(tmp[0]);
|
std::string utf_info="0x"+chrhex(tmp[0]);
|
||||||
for(u32 i=1;i<tmp.size();++i) {
|
for(u32 i=1;i<tmp.size();++i) {
|
||||||
utf_info+=" 0x"+chrhex(tmp[i]);
|
utf_info+=" 0x"+chrhex(tmp[i]);
|
||||||
}
|
}
|
||||||
|
@ -121,7 +121,7 @@ string lexer::utf8_gen() {
|
||||||
token lexer::id_gen() {
|
token lexer::id_gen() {
|
||||||
u32 begin_line=line;
|
u32 begin_line=line;
|
||||||
u32 begin_column=column;
|
u32 begin_column=column;
|
||||||
string str="";
|
std::string str="";
|
||||||
while(ptr<res.size() && (is_id(res[ptr])||is_dec(res[ptr]))) {
|
while(ptr<res.size() && (is_id(res[ptr])||is_dec(res[ptr]))) {
|
||||||
if (res[ptr]<0) { // utf-8
|
if (res[ptr]<0) { // utf-8
|
||||||
str+=utf8_gen();
|
str+=utf8_gen();
|
||||||
|
@ -139,7 +139,7 @@ token lexer::num_gen() {
|
||||||
u32 begin_column=column;
|
u32 begin_column=column;
|
||||||
// generate hex number
|
// generate hex number
|
||||||
if (ptr+1<res.size() && res[ptr]=='0' && res[ptr+1]=='x') {
|
if (ptr+1<res.size() && res[ptr]=='0' && res[ptr+1]=='x') {
|
||||||
string str="0x";
|
std::string str="0x";
|
||||||
ptr+=2;
|
ptr+=2;
|
||||||
while(ptr<res.size() && is_hex(res[ptr])) {
|
while(ptr<res.size() && is_hex(res[ptr])) {
|
||||||
str+=res[ptr++];
|
str+=res[ptr++];
|
||||||
|
@ -150,7 +150,7 @@ token lexer::num_gen() {
|
||||||
}
|
}
|
||||||
return {{begin_line, begin_column, line, column, filename}, tok::num, str};
|
return {{begin_line, begin_column, line, column, filename}, tok::num, str};
|
||||||
} else if (ptr+1<res.size() && res[ptr]=='0' && res[ptr+1]=='o') { // generate oct number
|
} else if (ptr+1<res.size() && res[ptr]=='0' && res[ptr+1]=='o') { // generate oct number
|
||||||
string str="0o";
|
std::string str="0o";
|
||||||
ptr+=2;
|
ptr+=2;
|
||||||
while(ptr<res.size() && is_oct(res[ptr])) {
|
while(ptr<res.size() && is_oct(res[ptr])) {
|
||||||
str+=res[ptr++];
|
str+=res[ptr++];
|
||||||
|
@ -168,7 +168,7 @@ token lexer::num_gen() {
|
||||||
}
|
}
|
||||||
// generate dec number
|
// generate dec number
|
||||||
// dec number -> [0~9][0~9]*(.[0~9]*)(e|E(+|-)0|[1~9][0~9]*)
|
// dec number -> [0~9][0~9]*(.[0~9]*)(e|E(+|-)0|[1~9][0~9]*)
|
||||||
string str="";
|
std::string str="";
|
||||||
while(ptr<res.size() && is_dec(res[ptr])) {
|
while(ptr<res.size() && is_dec(res[ptr])) {
|
||||||
str+=res[ptr++];
|
str+=res[ptr++];
|
||||||
}
|
}
|
||||||
|
@ -206,7 +206,7 @@ token lexer::num_gen() {
|
||||||
token lexer::str_gen() {
|
token lexer::str_gen() {
|
||||||
u32 begin_line=line;
|
u32 begin_line=line;
|
||||||
u32 begin_column=column;
|
u32 begin_column=column;
|
||||||
string str="";
|
std::string str="";
|
||||||
const char begin=res[ptr];
|
const char begin=res[ptr];
|
||||||
++column;
|
++column;
|
||||||
while(++ptr<res.size() && res[ptr]!=begin) {
|
while(++ptr<res.size() && res[ptr]!=begin) {
|
||||||
|
@ -257,7 +257,7 @@ token lexer::str_gen() {
|
||||||
token lexer::single_opr() {
|
token lexer::single_opr() {
|
||||||
u32 begin_line=line;
|
u32 begin_line=line;
|
||||||
u32 begin_column=column;
|
u32 begin_column=column;
|
||||||
string str(1,res[ptr]);
|
std::string str(1,res[ptr]);
|
||||||
++column;
|
++column;
|
||||||
tok type=get_type(str);
|
tok type=get_type(str);
|
||||||
if (type==tok::null) {
|
if (type==tok::null) {
|
||||||
|
@ -270,7 +270,7 @@ token lexer::single_opr() {
|
||||||
token lexer::dots() {
|
token lexer::dots() {
|
||||||
u32 begin_line=line;
|
u32 begin_line=line;
|
||||||
u32 begin_column=column;
|
u32 begin_column=column;
|
||||||
string str=".";
|
std::string str=".";
|
||||||
if (ptr+2<res.size() && res[ptr+1]=='.' && res[ptr+2]=='.') {
|
if (ptr+2<res.size() && res[ptr+1]=='.' && res[ptr+2]=='.') {
|
||||||
str+="..";
|
str+="..";
|
||||||
}
|
}
|
||||||
|
@ -283,7 +283,7 @@ token lexer::calc_opr() {
|
||||||
u32 begin_line=line;
|
u32 begin_line=line;
|
||||||
u32 begin_column=column;
|
u32 begin_column=column;
|
||||||
// get calculation operator
|
// get calculation operator
|
||||||
string str(1,res[ptr++]);
|
std::string str(1,res[ptr++]);
|
||||||
if (ptr<res.size() && res[ptr]=='=') {
|
if (ptr<res.size() && res[ptr]=='=') {
|
||||||
str+=res[ptr++];
|
str+=res[ptr++];
|
||||||
}
|
}
|
||||||
|
@ -291,7 +291,7 @@ token lexer::calc_opr() {
|
||||||
return {{begin_line, begin_column, line, column, filename}, get_type(str), str};
|
return {{begin_line, begin_column, line, column, filename}, get_type(str), str};
|
||||||
}
|
}
|
||||||
|
|
||||||
const error& lexer::scan(const string& file) {
|
const error& lexer::scan(const std::string& file) {
|
||||||
line=1;
|
line=1;
|
||||||
column=0;
|
column=0;
|
||||||
ptr=0;
|
ptr=0;
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include "nasal.h"
|
#include "nasal_new_header.h"
|
||||||
#include "nasal_err.h"
|
#include "nasal_new_err.h"
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#define S_ISREG(m) (((m)&0xF000)==0x8000)
|
#define S_ISREG(m) (((m)&0xF000)==0x8000)
|
||||||
|
@ -83,7 +83,7 @@ enum class tok:u32 {
|
||||||
struct token {
|
struct token {
|
||||||
span loc; // location
|
span loc; // location
|
||||||
tok type; // token type
|
tok type; // token type
|
||||||
string str; // content
|
std::string str; // content
|
||||||
token() = default;
|
token() = default;
|
||||||
token(const token&) = default;
|
token(const token&) = default;
|
||||||
};
|
};
|
||||||
|
@ -93,11 +93,11 @@ private:
|
||||||
u32 line;
|
u32 line;
|
||||||
u32 column;
|
u32 column;
|
||||||
usize ptr;
|
usize ptr;
|
||||||
string filename;
|
std::string filename;
|
||||||
string res;
|
std::string res;
|
||||||
error& err;
|
error& err;
|
||||||
std::vector<token> toks;
|
std::vector<token> toks;
|
||||||
const std::unordered_map<string,tok> typetbl {
|
const std::unordered_map<std::string, tok> typetbl {
|
||||||
{"true" ,tok::tktrue },
|
{"true" ,tok::tktrue },
|
||||||
{"false" ,tok::tkfalse },
|
{"false" ,tok::tkfalse },
|
||||||
{"for" ,tok::rfor },
|
{"for" ,tok::rfor },
|
||||||
|
@ -153,7 +153,7 @@ private:
|
||||||
{">=" ,tok::geq }
|
{">=" ,tok::geq }
|
||||||
};
|
};
|
||||||
|
|
||||||
tok get_type(const string&);
|
tok get_type(const std::string&);
|
||||||
bool skip(char);
|
bool skip(char);
|
||||||
bool is_id(char);
|
bool is_id(char);
|
||||||
bool is_hex(char);
|
bool is_hex(char);
|
||||||
|
@ -166,8 +166,8 @@ private:
|
||||||
void skip_note();
|
void skip_note();
|
||||||
void err_char();
|
void err_char();
|
||||||
|
|
||||||
void open(const string&);
|
void open(const std::string&);
|
||||||
string utf8_gen();
|
std::string utf8_gen();
|
||||||
token id_gen();
|
token id_gen();
|
||||||
token num_gen();
|
token num_gen();
|
||||||
token str_gen();
|
token str_gen();
|
||||||
|
@ -175,7 +175,9 @@ private:
|
||||||
token dots();
|
token dots();
|
||||||
token calc_opr();
|
token calc_opr();
|
||||||
public:
|
public:
|
||||||
lexer(error& e): line(1), column(0), ptr(0), filename(""), res(""), err(e) {}
|
lexer(error& e):
|
||||||
const error& scan(const string&);
|
line(1), column(0),
|
||||||
|
ptr(0), filename(""), res(""), err(e) {}
|
||||||
|
const error& scan(const std::string&);
|
||||||
const std::vector<token>& result() const {return toks;}
|
const std::vector<token>& result() const {return toks;}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,15 +1,9 @@
|
||||||
#include "nasal.h"
|
#include "nasal_new_header.h"
|
||||||
#include "nasal_err.h"
|
#include "nasal_new_err.h"
|
||||||
#include "nasal_lexer.h"
|
#include "nasal_new_lexer.h"
|
||||||
#include "nasal_ast.h"
|
#include "nasal_new_ast.h"
|
||||||
#include "nasal_parse.h"
|
#include "nasal_new_parse.h"
|
||||||
#include "nasal_import.h"
|
#include "ast_visitor.h"
|
||||||
#include "nasal_opt.h"
|
|
||||||
#include "nasal_gc.h"
|
|
||||||
#include "nasal_builtin.h"
|
|
||||||
#include "nasal_codegen.h"
|
|
||||||
#include "nasal_vm.h"
|
|
||||||
#include "nasal_dbg.h"
|
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
@ -73,8 +67,8 @@ void err() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute(
|
void execute(
|
||||||
const string& file,
|
const std::string& file,
|
||||||
const std::vector<string>& argv,
|
const std::vector<std::string>& argv,
|
||||||
const u32 cmd
|
const u32 cmd
|
||||||
) {
|
) {
|
||||||
using clk=std::chrono::high_resolution_clock;
|
using clk=std::chrono::high_resolution_clock;
|
||||||
|
@ -83,9 +77,9 @@ void execute(
|
||||||
error err;
|
error err;
|
||||||
lexer lex(err);
|
lexer lex(err);
|
||||||
parse parse(err);
|
parse parse(err);
|
||||||
linker ld(err);
|
// linker ld(err);
|
||||||
codegen gen(err);
|
// codegen gen(err);
|
||||||
vm ctx;
|
// vm ctx;
|
||||||
|
|
||||||
// lexer scans file to get tokens
|
// lexer scans file to get tokens
|
||||||
lex.scan(file).chkerr();
|
lex.scan(file).chkerr();
|
||||||
|
@ -94,27 +88,27 @@ void execute(
|
||||||
parse.compile(lex).chkerr();
|
parse.compile(lex).chkerr();
|
||||||
|
|
||||||
// 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, file, cmd&VM_DETAIL).chkerr();
|
// ld.link(parse, file, cmd&VM_DETAIL).chkerr();
|
||||||
|
|
||||||
// optimizer does simple optimization on ast
|
// optimizer does simple optimization on ast
|
||||||
optimize(parse.tree());
|
// optimize(parse.tree());
|
||||||
if (cmd&VM_AST) {
|
// if (cmd&VM_AST) {
|
||||||
parse.tree().dump();
|
// parse.tree().dump();
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 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).chkerr();
|
// gen.compile(parse, ld).chkerr();
|
||||||
if (cmd&VM_CODE) {
|
// if (cmd&VM_CODE) {
|
||||||
gen.print();
|
// gen.print();
|
||||||
}
|
// }
|
||||||
|
|
||||||
// run
|
// run
|
||||||
auto start=clk::now();
|
auto start=clk::now();
|
||||||
if (cmd&VM_DEBUG) {
|
// if (cmd&VM_DEBUG) {
|
||||||
dbg(err).run(gen, ld, argv);
|
// dbg(err).run(gen, ld, argv);
|
||||||
} else if (cmd&VM_TIME || cmd&VM_EXEC) {
|
// } else if (cmd&VM_TIME || cmd&VM_EXEC) {
|
||||||
ctx.run(gen, ld, argv, cmd&VM_DETAIL);
|
// ctx.run(gen, ld, argv, cmd&VM_DETAIL);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// get running time
|
// get running time
|
||||||
if (cmd&VM_TIME) {
|
if (cmd&VM_TIME) {
|
||||||
|
@ -132,7 +126,7 @@ i32 main(i32 argc, const char* argv[]) {
|
||||||
|
|
||||||
// run directly or show help
|
// run directly or show help
|
||||||
if (argc==2) {
|
if (argc==2) {
|
||||||
string s(argv[1]);
|
std::string s(argv[1]);
|
||||||
if (s=="-h" || s=="--help") {
|
if (s=="-h" || s=="--help") {
|
||||||
std::clog<<help;
|
std::clog<<help;
|
||||||
} else if (s[0]!='-') {
|
} else if (s[0]!='-') {
|
||||||
|
@ -144,7 +138,7 @@ i32 main(i32 argc, const char* argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// execute with arguments
|
// execute with arguments
|
||||||
const std::unordered_map<string,u32> cmdlst={
|
const std::unordered_map<std::string,u32> cmdlst = {
|
||||||
{"--ast", VM_AST},
|
{"--ast", VM_AST},
|
||||||
{"-a", VM_AST},
|
{"-a", VM_AST},
|
||||||
{"--code", VM_CODE},
|
{"--code", VM_CODE},
|
||||||
|
@ -159,8 +153,8 @@ i32 main(i32 argc, const char* argv[]) {
|
||||||
{"-dbg", VM_DEBUG}
|
{"-dbg", VM_DEBUG}
|
||||||
};
|
};
|
||||||
u32 cmd=0;
|
u32 cmd=0;
|
||||||
string filename="";
|
std::string filename="";
|
||||||
std::vector<string> vm_argv;
|
std::vector<std::string> vm_argv;
|
||||||
for(i32 i=1; i<argc; ++i) {
|
for(i32 i=1; i<argc; ++i) {
|
||||||
if (cmdlst.count(argv[i])) {
|
if (cmdlst.count(argv[i])) {
|
||||||
cmd|=cmdlst.at(argv[i]);
|
cmd|=cmdlst.at(argv[i]);
|
|
@ -0,0 +1,230 @@
|
||||||
|
#include "nasal_new_header.h"
|
||||||
|
|
||||||
|
bool is_windows() {
|
||||||
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_linux() {
|
||||||
|
#if defined __linux__
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_macos() {
|
||||||
|
#if defined __APPLE__
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_x86() {
|
||||||
|
#if defined(__i386__) || defined(_M_IX86)
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_amd64() {
|
||||||
|
#if defined(__amd64__) || defined(_M_X64)
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_x86_64() {
|
||||||
|
return is_amd64();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_arm() {
|
||||||
|
#if defined(__arm__) || defined(_M_ARM)
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_aarch64() {
|
||||||
|
#if defined(__aarch64__) || defined(_M_ARM64)
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_ia64() {
|
||||||
|
#if defined(__ia64__)
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_powerpc() {
|
||||||
|
#if defined(__powerpc__)
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_superh() {
|
||||||
|
#if defined(__sh__)
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
f64 hex2f(const char* str) {
|
||||||
|
f64 ret=0;
|
||||||
|
for(; *str; ++str) {
|
||||||
|
if ('0'<=*str && *str<='9') {
|
||||||
|
ret=ret*16+(*str-'0');
|
||||||
|
} else if ('a'<=*str && *str<='f') {
|
||||||
|
ret=ret*16+(*str-'a'+10);
|
||||||
|
} else if ('A'<=*str && *str<='F') {
|
||||||
|
ret=ret*16+(*str-'A'+10);
|
||||||
|
} else {
|
||||||
|
return nan("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
f64 oct2f(const char* str) {
|
||||||
|
f64 ret=0;
|
||||||
|
while('0'<=*str && *str<'8') {
|
||||||
|
ret=ret*8+(*str++-'0');
|
||||||
|
}
|
||||||
|
if (*str) {
|
||||||
|
return nan("");
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we have the same reason not using atof here
|
||||||
|
// just as andy's interpreter does.
|
||||||
|
// it is not platform independent, and may have strange output.
|
||||||
|
// so we write a new function here to convert str to number manually.
|
||||||
|
// but this also makes 0.1+0.2==0.3,
|
||||||
|
// not another result that you may get in other languages.
|
||||||
|
f64 dec2f(const char* str) {
|
||||||
|
f64 ret=0,negative=1,num_pow=0;
|
||||||
|
while('0'<=*str && *str<='9') {
|
||||||
|
ret=ret*10+(*str++-'0');
|
||||||
|
}
|
||||||
|
if (!*str) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (*str=='.') {
|
||||||
|
if (!*++str) {
|
||||||
|
return nan("");
|
||||||
|
}
|
||||||
|
num_pow=0.1;
|
||||||
|
while('0'<=*str && *str<='9') {
|
||||||
|
ret+=num_pow*(*str++-'0');
|
||||||
|
num_pow*=0.1;
|
||||||
|
}
|
||||||
|
if (!*str) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (*str!='e' && *str!='E') {
|
||||||
|
return nan("");
|
||||||
|
}
|
||||||
|
if (!*++str) {
|
||||||
|
return nan("");
|
||||||
|
}
|
||||||
|
if (*str=='-' || *str=='+') {
|
||||||
|
negative=(*str++=='-'? -1:1);
|
||||||
|
}
|
||||||
|
if (!*str) {
|
||||||
|
return nan("");
|
||||||
|
}
|
||||||
|
num_pow=0;
|
||||||
|
while('0'<=*str && *str<='9') {
|
||||||
|
num_pow=num_pow*10+(*str++-'0');
|
||||||
|
}
|
||||||
|
if (*str) {
|
||||||
|
return nan("");
|
||||||
|
}
|
||||||
|
return ret*std::pow(10,negative*num_pow);
|
||||||
|
}
|
||||||
|
|
||||||
|
f64 str2num(const char* str) {
|
||||||
|
bool negative=false;
|
||||||
|
f64 res=0;
|
||||||
|
if (*str=='-' || *str=='+') {
|
||||||
|
negative=(*str++=='-');
|
||||||
|
}
|
||||||
|
if (!*str) {
|
||||||
|
return nan("");
|
||||||
|
}
|
||||||
|
if (str[0]=='0' && str[1]=='x') {
|
||||||
|
res=hex2f(str+2);
|
||||||
|
} else if (str[0]=='0' && str[1]=='o') {
|
||||||
|
res=oct2f(str+2);
|
||||||
|
} else {
|
||||||
|
res=dec2f(str);
|
||||||
|
}
|
||||||
|
return negative?-res:res;
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 utf8_hdchk(const char head) {
|
||||||
|
// RFC-2279 but now we use RFC-3629 so nbytes is less than 4
|
||||||
|
const u8 c=(u8)head;
|
||||||
|
if ((c>>5)==0x06) { // 110x xxxx (10xx xxxx)^1
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if ((c>>4)==0x0e) { // 1110 xxxx (10xx xxxx)^2
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
if ((c>>3)==0x1e) { // 1111 0xxx (10xx xxxx)^3
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string chrhex(const char c) {
|
||||||
|
const char hextbl[]="0123456789abcdef";
|
||||||
|
return {hextbl[(c&0xf0)>>4],hextbl[c&0x0f]};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string rawstr(const std::string& str, const usize maxlen) {
|
||||||
|
std::string ret("");
|
||||||
|
for(auto i:str) {
|
||||||
|
// windows doesn't output unicode normally, so we output the hex
|
||||||
|
if (is_windows() && i<=0) {
|
||||||
|
ret+="\\x"+chrhex(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
switch(i) {
|
||||||
|
case '\0': ret+="\\0"; break;
|
||||||
|
case '\a': ret+="\\a"; break;
|
||||||
|
case '\b': ret+="\\b"; break;
|
||||||
|
case '\t': ret+="\\t"; break;
|
||||||
|
case '\n': ret+="\\n"; break;
|
||||||
|
case '\v': ret+="\\v"; break;
|
||||||
|
case '\f': ret+="\\f"; break;
|
||||||
|
case '\r': ret+="\\r"; break;
|
||||||
|
case '\033':ret+="\\e"; break;
|
||||||
|
case '\"': ret+="\\\"";break;
|
||||||
|
case '\'': ret+="\\\'";break;
|
||||||
|
case '\\': ret+="\\\\";break;
|
||||||
|
default: ret+=i; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (maxlen && ret.length()>maxlen) {
|
||||||
|
ret=ret.substr(0,maxlen)+"...";
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
|
@ -129,17 +129,10 @@ bool parse::check_func_end(expr* node) {
|
||||||
type==expr_type::ast_hash) {
|
type==expr_type::ast_hash) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (node.child().empty() || (
|
if (type==expr_type::ast_def) {
|
||||||
type!=expr_type::ast_def &&
|
return check_func_end(((definition_expr*)type)->get_value());
|
||||||
type!=expr_type::ast_equal &&
|
} else if (type==expr_type::ast_assign) {
|
||||||
type!=expr_type::ast_addeq &&
|
return check_func_end(((assignment_expr*)type)->get_right());
|
||||||
type!=expr_type::ast_subeq &&
|
|
||||||
type!=expr_type::ast_multeq &&
|
|
||||||
type!=expr_type::ast_diveq &&
|
|
||||||
type!=expr_type::ast_lnkeq)) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return check_func_end(node.child().back());
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -301,7 +294,6 @@ void parse::params(function* func_node) {
|
||||||
auto param = new parameter(toks[ptr].loc);
|
auto param = new parameter(toks[ptr].loc);
|
||||||
param->set_parameter_name(id());
|
param->set_parameter_name(id());
|
||||||
if (lookahead(tok::eq) || lookahead(tok::ellipsis)) {
|
if (lookahead(tok::eq) || lookahead(tok::ellipsis)) {
|
||||||
ast special_arg(toks[ptr].loc, ast_null);
|
|
||||||
if (lookahead(tok::eq)) {
|
if (lookahead(tok::eq)) {
|
||||||
match(tok::eq);
|
match(tok::eq);
|
||||||
param->set_parameter_type(parameter::param_type::default_parameter);
|
param->set_parameter_type(parameter::param_type::default_parameter);
|
||||||
|
@ -417,16 +409,31 @@ expr* parse::calc() {
|
||||||
node = tmp;
|
node = tmp;
|
||||||
} else if (tok::eq<=toks[ptr].type && toks[ptr].type<=tok::lnkeq) {
|
} else if (tok::eq<=toks[ptr].type && toks[ptr].type<=tok::lnkeq) {
|
||||||
// tok::eq~tok::lnkeq is 37 to 42,ast_equal~ast_lnkeq is 21~26
|
// tok::eq~tok::lnkeq is 37 to 42,ast_equal~ast_lnkeq is 21~26
|
||||||
ast tmp(toks[ptr].loc, (u32)toks[ptr].type-(u32)tok::eq+ast_equal);
|
auto tmp = new assignment_expr(toks[ptr].loc);
|
||||||
tmp.add(std::move(node));
|
switch(toks[ptr].type) {
|
||||||
|
case tok::eq: tmp->set_type(assignment_expr::assign_type::equal); break;
|
||||||
|
case tok::addeq: tmp->set_type(assignment_expr::assign_type::add_equal); break;
|
||||||
|
case tok::subeq: tmp->set_type(assignment_expr::assign_type::sub_equal); break;
|
||||||
|
case tok::multeq: tmp->set_type(assignment_expr::assign_type::mult_equal); break;
|
||||||
|
case tok::diveq: tmp->set_type(assignment_expr::assign_type::div_equal); break;
|
||||||
|
case tok::lnkeq: tmp->set_type(assignment_expr::assign_type::concat_equal); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
tmp->set_left(node);
|
||||||
match(toks[ptr].type);
|
match(toks[ptr].type);
|
||||||
tmp.add(calc());
|
tmp->set_right(calc());
|
||||||
node = tmp;
|
node = tmp;
|
||||||
} else if (toks[ptr].type==tok::btandeq || toks[ptr].type==tok::btoreq || toks[ptr].type==tok::btxoreq) {
|
} else if (toks[ptr].type==tok::btandeq || toks[ptr].type==tok::btoreq || toks[ptr].type==tok::btxoreq) {
|
||||||
ast tmp(toks[ptr].loc, (u32)toks[ptr].type-(u32)tok::btandeq+ast_btandeq);
|
auto tmp = new assignment_expr(toks[ptr].loc);
|
||||||
tmp.add(std::move(node));
|
switch(toks[ptr].type) {
|
||||||
|
case tok::btandeq: tmp->set_type(assignment_expr::assign_type::bitwise_and_equal); break;
|
||||||
|
case tok::btoreq: tmp->set_type(assignment_expr::assign_type::bitwise_or_equal); break;
|
||||||
|
case tok::btxoreq: tmp->set_type(assignment_expr::assign_type::bitwise_xor_equal); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
tmp->set_left(node);
|
||||||
match(toks[ptr].type);
|
match(toks[ptr].type);
|
||||||
tmp.add(calc());
|
tmp->set_right(calc());
|
||||||
node = tmp;
|
node = tmp;
|
||||||
}
|
}
|
||||||
update_location(node);
|
update_location(node);
|
||||||
|
|
|
@ -2,11 +2,10 @@
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "nasal.h"
|
#include "nasal_new_header.h"
|
||||||
#include "nasal_new_ast.h"
|
#include "nasal_new_ast.h"
|
||||||
#include "nasal_lexer.h"
|
#include "nasal_new_lexer.h"
|
||||||
#include "nasal_ast.h"
|
#include "nasal_new_err.h"
|
||||||
#include "nasal_err.h"
|
|
||||||
|
|
||||||
class parse {
|
class parse {
|
||||||
|
|
||||||
|
@ -22,7 +21,7 @@ private:
|
||||||
error& err;
|
error& err;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::unordered_map<tok,string> tokname {
|
const std::unordered_map<tok, std::string> tokname {
|
||||||
{tok::rfor ,"for" },
|
{tok::rfor ,"for" },
|
||||||
{tok::forindex,"forindex"},
|
{tok::forindex,"forindex"},
|
||||||
{tok::foreach ,"foreach" },
|
{tok::foreach ,"foreach" },
|
||||||
|
|
53
makefile
53
makefile
|
@ -18,24 +18,12 @@ SRC=\
|
||||||
|
|
||||||
STD=c++14
|
STD=c++14
|
||||||
|
|
||||||
nasal:$(SRC) nasal_new_lexer.o nasal_new_ast.o nasal_new_parse.o ast_visitor.o
|
nasal:$(SRC)
|
||||||
$(CXX) -std=$(STD) -O3 main.cpp -o nasal -fno-exceptions -ldl -Wshadow -Wall
|
$(CXX) -std=$(STD) -O3 main.cpp -o nasal -fno-exceptions -ldl -Wshadow -Wall
|
||||||
|
|
||||||
nasal.exe:$(SRC)
|
nasal.exe:$(SRC)
|
||||||
$(CXX) -std=$(STD) -O3 main.cpp -o nasal.exe -fno-exceptions -Wshadow -Wall -static
|
$(CXX) -std=$(STD) -O3 main.cpp -o nasal.exe -fno-exceptions -Wshadow -Wall -static
|
||||||
|
|
||||||
nasal_new_lexer.o: ast/nasal_new_lexer.h ast/nasal_new_lexer.cpp nasal.h
|
|
||||||
$(CXX) -std=$(STD) -c -O3 ast/nasal_new_lexer.cpp -fno-exceptions -fPIC -o nasal_new_lexer.o -I .
|
|
||||||
|
|
||||||
nasal_new_ast.o: ast/nasal_new_ast.h ast/nasal_new_ast.cpp nasal.h
|
|
||||||
$(CXX) -std=$(STD) -c -O3 ast/nasal_new_ast.cpp -fno-exceptions -fPIC -o nasal_new_ast.o -I .
|
|
||||||
|
|
||||||
nasal_new_parse.o: ast/nasal_new_parse.h ast/nasal_new_parse.cpp nasal.h ast/nasal_new_ast.h
|
|
||||||
# $(CXX) -std=$(STD) -c -O3 ast/nasal_new_parse.cpp -fno-exceptions -fPIC -o nasal_new_parse.o -I .
|
|
||||||
|
|
||||||
ast_visitor.o: ast/nasal_new_ast.h ast/ast_visitor.h ast/ast_visitor.cpp
|
|
||||||
$(CXX) -std=$(STD) -c -O3 ast/ast_visitor.cpp -fno-exceptions -fPIC -o ast_visitor.o -I .
|
|
||||||
|
|
||||||
stable-release:$(SRC)
|
stable-release:$(SRC)
|
||||||
$(CXX) -std=$(STD) -O2 main.cpp -o nasal -fno-exceptions -ldl -Wshadow -Wall
|
$(CXX) -std=$(STD) -O2 main.cpp -o nasal -fno-exceptions -ldl -Wshadow -Wall
|
||||||
|
|
||||||
|
@ -84,3 +72,42 @@ test:nasal
|
||||||
@ ./nasal -d test/wavecollapse.nas
|
@ ./nasal -d test/wavecollapse.nas
|
||||||
@ ./nasal test/word_collector.nas test/md5compare.nas
|
@ ./nasal test/word_collector.nas test/md5compare.nas
|
||||||
@ ./nasal -t -d test/ycombinator.nas
|
@ ./nasal -t -d test/ycombinator.nas
|
||||||
|
|
||||||
|
NASAL_NEW_AST=\
|
||||||
|
nasal_new_misc.o\
|
||||||
|
nasal_new_err.o\
|
||||||
|
nasal_new_lexer.o\
|
||||||
|
nasal_new_ast.o\
|
||||||
|
nasal_new_parse.o\
|
||||||
|
ast_visitor.o\
|
||||||
|
nasal_new_main.o
|
||||||
|
|
||||||
|
# for test
|
||||||
|
nasal_new: $(NASAL_NEW_AST)
|
||||||
|
$(CXX) $(NASAL_NEW_AST) -o nasal_new
|
||||||
|
@ echo "build done"
|
||||||
|
|
||||||
|
nasal_new_main.o: ast/nasal_new_main.cpp
|
||||||
|
$(CXX) -std=$(STD) -c -O3 ast/nasal_new_main.cpp -fno-exceptions -fPIC -o nasal_new_main.o -I .
|
||||||
|
|
||||||
|
nasal_new_misc.o: ast/nasal_new_header.h ast/nasal_new_misc.cpp
|
||||||
|
$(CXX) -std=$(STD) -c -O3 ast/nasal_new_misc.cpp -fno-exceptions -fPIC -o nasal_new_misc.o -I .
|
||||||
|
|
||||||
|
nasal_new_err.o: ast/nasal_new_err.h ast/nasal_new_err.cpp
|
||||||
|
$(CXX) -std=$(STD) -c -O3 ast/nasal_new_err.cpp -fno-exceptions -fPIC -o nasal_new_err.o -I .
|
||||||
|
|
||||||
|
nasal_new_lexer.o: ast/nasal_new_lexer.h ast/nasal_new_lexer.cpp
|
||||||
|
$(CXX) -std=$(STD) -c -O3 ast/nasal_new_lexer.cpp -fno-exceptions -fPIC -o nasal_new_lexer.o -I .
|
||||||
|
|
||||||
|
nasal_new_ast.o: ast/nasal_new_ast.h ast/nasal_new_ast.cpp
|
||||||
|
$(CXX) -std=$(STD) -c -O3 ast/nasal_new_ast.cpp -fno-exceptions -fPIC -o nasal_new_ast.o -I .
|
||||||
|
|
||||||
|
nasal_new_parse.o: ast/nasal_new_parse.h ast/nasal_new_parse.cpp ast/nasal_new_ast.h
|
||||||
|
$(CXX) -std=$(STD) -c -O3 ast/nasal_new_parse.cpp -fno-exceptions -fPIC -o nasal_new_parse.o -I .
|
||||||
|
|
||||||
|
ast_visitor.o: ast/nasal_new_ast.h ast/ast_visitor.h ast/ast_visitor.cpp
|
||||||
|
$(CXX) -std=$(STD) -c -O3 ast/ast_visitor.cpp -fno-exceptions -fPIC -o ast_visitor.o -I .
|
||||||
|
|
||||||
|
.PHONY: nasal_new_clean
|
||||||
|
nasal_new_clean:
|
||||||
|
rm $(NASAL_NEW_AST)
|
Loading…
Reference in New Issue