change ast used in parser

This commit is contained in:
ValKmjolnir 2023-06-24 16:50:43 +08:00
parent 0132ca0870
commit 2ce13e2134
12 changed files with 988 additions and 104 deletions

View File

@ -57,4 +57,302 @@ hash_pair::~hash_pair() {
void hash_pair::accept(ast_visitor* visitor) {
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
}

View File

@ -1,7 +1,7 @@
#pragma once
#include "nasal.h"
#include "nasal_err.h"
#include "nasal_new_header.h"
#include "nasal_new_err.h"
#include <vector>
#include <unordered_map>
@ -51,6 +51,7 @@ enum class expr_type:u32 {
ast_multi_id, // multi identifiers sub-tree
ast_tuple,
ast_def, // definition
ast_assign,
ast_multi_assign,
ast_continue, // continue 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_column = location.end_column;
}
virtual void accept(ast_visitor*);
void accept(ast_visitor*);
};
class null_expr:public expr {
@ -115,6 +116,7 @@ public:
number_literal(const span& location, const f64 num):
expr(location, expr_type::ast_num), number(num) {}
~number_literal() = default;
f64 get_number() const {return number;}
void accept(ast_visitor*) override;
};
@ -126,6 +128,7 @@ public:
string_literal(const span& location, const std::string& str):
expr(location, expr_type::ast_str), content(str) {}
~string_literal() = default;
const std::string get_content() const {return content;}
void accept(ast_visitor*) override;
};
@ -137,6 +140,7 @@ public:
identifier(const span& location, const std::string& str):
expr(location, expr_type::ast_id), name(str) {}
~identifier() = default;
const std::string get_name() const {return name;}
void accept(ast_visitor*) override;
};
@ -346,7 +350,7 @@ public:
call_hash(const span& location, const std::string& name):
expr(location, expr_type::ast_callh),
field(name) {}
~call_hash();
~call_hash() = default;
void accept(ast_visitor*) override;
};
@ -405,6 +409,42 @@ public:
void set_identifier(identifier* node) {variable_name = node;}
void set_multi_define(multi_define* node) {variables = 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;
};

163
ast/nasal_new_err.cpp Normal file
View File

@ -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";
}

73
ast/nasal_new_err.h Normal file
View File

@ -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);
}
}
};

51
ast/nasal_new_header.h Normal file
View File

@ -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);

View File

@ -59,7 +59,7 @@ void lexer::err_char() {
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
struct stat buffer;
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();
}
tok lexer::get_type(const string& str) {
tok lexer::get_type(const std::string& str) {
return typetbl.count(str)?typetbl.at(str):tok::null;
}
string lexer::utf8_gen() {
string str="";
std::string lexer::utf8_gen() {
std::string str="";
while(ptr<res.size() && res[ptr]<0) {
string tmp="";
std::string tmp="";
u32 nbytes=utf8_hdchk(res[ptr]);
if (!nbytes) {
++ptr;
@ -105,7 +105,7 @@ string lexer::utf8_gen() {
// utf8 character's total length is 1+nbytes
if (tmp.length()!=1+nbytes) {
++column;
string utf_info="0x"+chrhex(tmp[0]);
std::string utf_info="0x"+chrhex(tmp[0]);
for(u32 i=1;i<tmp.size();++i) {
utf_info+=" 0x"+chrhex(tmp[i]);
}
@ -121,7 +121,7 @@ string lexer::utf8_gen() {
token lexer::id_gen() {
u32 begin_line=line;
u32 begin_column=column;
string str="";
std::string str="";
while(ptr<res.size() && (is_id(res[ptr])||is_dec(res[ptr]))) {
if (res[ptr]<0) { // utf-8
str+=utf8_gen();
@ -139,7 +139,7 @@ token lexer::num_gen() {
u32 begin_column=column;
// generate hex number
if (ptr+1<res.size() && res[ptr]=='0' && res[ptr+1]=='x') {
string str="0x";
std::string str="0x";
ptr+=2;
while(ptr<res.size() && is_hex(res[ptr])) {
str+=res[ptr++];
@ -150,7 +150,7 @@ token lexer::num_gen() {
}
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
string str="0o";
std::string str="0o";
ptr+=2;
while(ptr<res.size() && is_oct(res[ptr])) {
str+=res[ptr++];
@ -168,7 +168,7 @@ token lexer::num_gen() {
}
// generate dec number
// 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])) {
str+=res[ptr++];
}
@ -206,7 +206,7 @@ token lexer::num_gen() {
token lexer::str_gen() {
u32 begin_line=line;
u32 begin_column=column;
string str="";
std::string str="";
const char begin=res[ptr];
++column;
while(++ptr<res.size() && res[ptr]!=begin) {
@ -257,7 +257,7 @@ token lexer::str_gen() {
token lexer::single_opr() {
u32 begin_line=line;
u32 begin_column=column;
string str(1,res[ptr]);
std::string str(1,res[ptr]);
++column;
tok type=get_type(str);
if (type==tok::null) {
@ -270,7 +270,7 @@ token lexer::single_opr() {
token lexer::dots() {
u32 begin_line=line;
u32 begin_column=column;
string str=".";
std::string str=".";
if (ptr+2<res.size() && res[ptr+1]=='.' && res[ptr+2]=='.') {
str+="..";
}
@ -283,7 +283,7 @@ token lexer::calc_opr() {
u32 begin_line=line;
u32 begin_column=column;
// get calculation operator
string str(1,res[ptr++]);
std::string str(1,res[ptr++]);
if (ptr<res.size() && 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};
}
const error& lexer::scan(const string& file) {
const error& lexer::scan(const std::string& file) {
line=1;
column=0;
ptr=0;

View File

@ -12,8 +12,8 @@
#include <unordered_map>
#include <sys/stat.h>
#include "nasal.h"
#include "nasal_err.h"
#include "nasal_new_header.h"
#include "nasal_new_err.h"
#ifdef _MSC_VER
#define S_ISREG(m) (((m)&0xF000)==0x8000)
@ -81,9 +81,9 @@ enum class tok:u32 {
};
struct token {
span loc; // location
tok type; // token type
string str; // content
span loc; // location
tok type; // token type
std::string str; // content
token() = default;
token(const token&) = default;
};
@ -93,11 +93,11 @@ private:
u32 line;
u32 column;
usize ptr;
string filename;
string res;
std::string filename;
std::string res;
error& err;
std::vector<token> toks;
const std::unordered_map<string,tok> typetbl {
const std::unordered_map<std::string, tok> typetbl {
{"true" ,tok::tktrue },
{"false" ,tok::tkfalse },
{"for" ,tok::rfor },
@ -153,7 +153,7 @@ private:
{">=" ,tok::geq }
};
tok get_type(const string&);
tok get_type(const std::string&);
bool skip(char);
bool is_id(char);
bool is_hex(char);
@ -166,8 +166,8 @@ private:
void skip_note();
void err_char();
void open(const string&);
string utf8_gen();
void open(const std::string&);
std::string utf8_gen();
token id_gen();
token num_gen();
token str_gen();
@ -175,7 +175,9 @@ private:
token dots();
token calc_opr();
public:
lexer(error& e): line(1), column(0), ptr(0), filename(""), res(""), err(e) {}
const error& scan(const string&);
lexer(error& e):
line(1), column(0),
ptr(0), filename(""), res(""), err(e) {}
const error& scan(const std::string&);
const std::vector<token>& result() const {return toks;}
};

View File

@ -1,15 +1,9 @@
#include "nasal.h"
#include "nasal_err.h"
#include "nasal_lexer.h"
#include "nasal_ast.h"
#include "nasal_parse.h"
#include "nasal_import.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 "nasal_new_header.h"
#include "nasal_new_err.h"
#include "nasal_new_lexer.h"
#include "nasal_new_ast.h"
#include "nasal_new_parse.h"
#include "ast_visitor.h"
#include <unordered_map>
#include <thread>
@ -73,8 +67,8 @@ void err() {
}
void execute(
const string& file,
const std::vector<string>& argv,
const std::string& file,
const std::vector<std::string>& argv,
const u32 cmd
) {
using clk=std::chrono::high_resolution_clock;
@ -83,9 +77,9 @@ void execute(
error err;
lexer lex(err);
parse parse(err);
linker ld(err);
codegen gen(err);
vm ctx;
// linker ld(err);
// codegen gen(err);
// vm ctx;
// lexer scans file to get tokens
lex.scan(file).chkerr();
@ -94,27 +88,27 @@ void execute(
parse.compile(lex).chkerr();
// 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
optimize(parse.tree());
if (cmd&VM_AST) {
parse.tree().dump();
}
// optimize(parse.tree());
// if (cmd&VM_AST) {
// parse.tree().dump();
// }
// code generator gets parser's ast and import file list to generate code
gen.compile(parse, ld).chkerr();
if (cmd&VM_CODE) {
gen.print();
}
// gen.compile(parse, ld).chkerr();
// if (cmd&VM_CODE) {
// gen.print();
// }
// run
auto start=clk::now();
if (cmd&VM_DEBUG) {
dbg(err).run(gen, ld, argv);
} else if (cmd&VM_TIME || cmd&VM_EXEC) {
ctx.run(gen, ld, argv, cmd&VM_DETAIL);
}
// if (cmd&VM_DEBUG) {
// dbg(err).run(gen, ld, argv);
// } else if (cmd&VM_TIME || cmd&VM_EXEC) {
// ctx.run(gen, ld, argv, cmd&VM_DETAIL);
// }
// get running time
if (cmd&VM_TIME) {
@ -132,7 +126,7 @@ i32 main(i32 argc, const char* argv[]) {
// run directly or show help
if (argc==2) {
string s(argv[1]);
std::string s(argv[1]);
if (s=="-h" || s=="--help") {
std::clog<<help;
} else if (s[0]!='-') {
@ -144,7 +138,7 @@ i32 main(i32 argc, const char* argv[]) {
}
// execute with arguments
const std::unordered_map<string,u32> cmdlst={
const std::unordered_map<std::string,u32> cmdlst = {
{"--ast", VM_AST},
{"-a", VM_AST},
{"--code", VM_CODE},
@ -159,8 +153,8 @@ i32 main(i32 argc, const char* argv[]) {
{"-dbg", VM_DEBUG}
};
u32 cmd=0;
string filename="";
std::vector<string> vm_argv;
std::string filename="";
std::vector<std::string> vm_argv;
for(i32 i=1; i<argc; ++i) {
if (cmdlst.count(argv[i])) {
cmd|=cmdlst.at(argv[i]);

230
ast/nasal_new_misc.cpp Normal file
View File

@ -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;
}

View File

@ -129,17 +129,10 @@ bool parse::check_func_end(expr* node) {
type==expr_type::ast_hash) {
return false;
}
if (node.child().empty() || (
type!=expr_type::ast_def &&
type!=expr_type::ast_equal &&
type!=expr_type::ast_addeq &&
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());
if (type==expr_type::ast_def) {
return check_func_end(((definition_expr*)type)->get_value());
} else if (type==expr_type::ast_assign) {
return check_func_end(((assignment_expr*)type)->get_right());
}
return false;
}
@ -301,7 +294,6 @@ void parse::params(function* func_node) {
auto param = new parameter(toks[ptr].loc);
param->set_parameter_name(id());
if (lookahead(tok::eq) || lookahead(tok::ellipsis)) {
ast special_arg(toks[ptr].loc, ast_null);
if (lookahead(tok::eq)) {
match(tok::eq);
param->set_parameter_type(parameter::param_type::default_parameter);
@ -417,16 +409,31 @@ expr* parse::calc() {
node = tmp;
} 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
ast tmp(toks[ptr].loc, (u32)toks[ptr].type-(u32)tok::eq+ast_equal);
tmp.add(std::move(node));
auto tmp = new assignment_expr(toks[ptr].loc);
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);
tmp.add(calc());
tmp->set_right(calc());
node = tmp;
} 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);
tmp.add(std::move(node));
auto tmp = new assignment_expr(toks[ptr].loc);
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);
tmp.add(calc());
tmp->set_right(calc());
node = tmp;
}
update_location(node);

View File

@ -2,11 +2,10 @@
#include <unordered_map>
#include "nasal.h"
#include "nasal_new_header.h"
#include "nasal_new_ast.h"
#include "nasal_lexer.h"
#include "nasal_ast.h"
#include "nasal_err.h"
#include "nasal_new_lexer.h"
#include "nasal_new_err.h"
class parse {
@ -22,7 +21,7 @@ private:
error& err;
private:
const std::unordered_map<tok,string> tokname {
const std::unordered_map<tok, std::string> tokname {
{tok::rfor ,"for" },
{tok::forindex,"forindex"},
{tok::foreach ,"foreach" },

View File

@ -18,24 +18,12 @@ SRC=\
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
nasal.exe:$(SRC)
$(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)
$(CXX) -std=$(STD) -O2 main.cpp -o nasal -fno-exceptions -ldl -Wshadow -Wall
@ -83,4 +71,43 @@ test:nasal
@ ./nasal -t -d test/turingmachine.nas
@ ./nasal -d test/wavecollapse.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)