✨ add keyword support 'true' and 'false'
true is now number 1.0 false is number 0.0
This commit is contained in:
parent
8df02d25ad
commit
d03273b4e1
|
@ -10,6 +10,7 @@ nil ::= nil;
|
||||||
id ::= identifier;
|
id ::= identifier;
|
||||||
number::= number;
|
number::= number;
|
||||||
string::= string;
|
string::= string;
|
||||||
|
bool ::= true | false;
|
||||||
vector::=
|
vector::=
|
||||||
'[' {calculation ','} ']'
|
'[' {calculation ','} ']'
|
||||||
;
|
;
|
||||||
|
@ -68,6 +69,7 @@ scalar::=
|
||||||
|number
|
|number
|
||||||
|string
|
|string
|
||||||
|nil
|
|nil
|
||||||
|
|bool
|
||||||
|'(' calculation ')' {call_scalar}
|
|'(' calculation ')' {call_scalar}
|
||||||
;
|
;
|
||||||
call_scalar::=
|
call_scalar::=
|
||||||
|
|
28
nasal.h
28
nasal.h
|
@ -11,6 +11,30 @@
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
using i32=std::int32_t;
|
using i32=std::int32_t;
|
||||||
using i64=std::int64_t;
|
using i64=std::int64_t;
|
||||||
using u8=std::uint8_t;
|
using u8=std::uint8_t;
|
||||||
|
@ -139,13 +163,11 @@ string chrhex(const char c) {
|
||||||
string rawstr(const string& str,const usize maxlen=0) {
|
string rawstr(const string& str,const usize maxlen=0) {
|
||||||
string ret("");
|
string ret("");
|
||||||
for(auto i:str) {
|
for(auto i:str) {
|
||||||
#ifdef _WIN32
|
|
||||||
// windows doesn't output unicode normally, so we output the hex
|
// windows doesn't output unicode normally, so we output the hex
|
||||||
if (i<=0) {
|
if (is_windows() && i<=0) {
|
||||||
ret+="\\x"+chrhex(i);
|
ret+="\\x"+chrhex(i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
switch(i) {
|
switch(i) {
|
||||||
case '\0': ret+="\\0"; break;
|
case '\0': ret+="\\0"; break;
|
||||||
case '\a': ret+="\\a"; break;
|
case '\a': ret+="\\a"; break;
|
||||||
|
|
25
nasal_ast.h
25
nasal_ast.h
|
@ -14,6 +14,7 @@ enum ast_node:u32 {
|
||||||
ast_num, // number, basic value type
|
ast_num, // number, basic value type
|
||||||
ast_str, // string, basic value type
|
ast_str, // string, basic value type
|
||||||
ast_id, // identifier
|
ast_id, // identifier
|
||||||
|
ast_bool, // bools
|
||||||
ast_func, // func keyword
|
ast_func, // func keyword
|
||||||
ast_hash, // hash, basic value type
|
ast_hash, // hash, basic value type
|
||||||
ast_vec, // vector, basic value type
|
ast_vec, // vector, basic value type
|
||||||
|
@ -71,10 +72,11 @@ const char* ast_name[]={
|
||||||
"AbstractSyntaxTreeRoot",
|
"AbstractSyntaxTreeRoot",
|
||||||
"CodeBlock",
|
"CodeBlock",
|
||||||
"FileIndex",
|
"FileIndex",
|
||||||
"LiteralNil",
|
"NilLiteral",
|
||||||
"LiteralNumber",
|
"NumberLiteral",
|
||||||
"LiteralString",
|
"StringLiteral",
|
||||||
"Identifier",
|
"Identifier",
|
||||||
|
"BoolLiteral",
|
||||||
"Function",
|
"Function",
|
||||||
"HashMap",
|
"HashMap",
|
||||||
"Vector",
|
"Vector",
|
||||||
|
@ -188,6 +190,7 @@ void ast::print(u32 depth,bool last,std::vector<string>& indent) const{
|
||||||
std::cout<<ast_name[nd_type];
|
std::cout<<ast_name[nd_type];
|
||||||
if (nd_type==ast_str ||
|
if (nd_type==ast_str ||
|
||||||
nd_type==ast_id ||
|
nd_type==ast_id ||
|
||||||
|
nd_type==ast_bool ||
|
||||||
nd_type==ast_default ||
|
nd_type==ast_default ||
|
||||||
nd_type==ast_dynamic ||
|
nd_type==ast_dynamic ||
|
||||||
nd_type==ast_callh) {
|
nd_type==ast_callh) {
|
||||||
|
@ -199,18 +202,14 @@ void ast::print(u32 depth,bool last,std::vector<string>& indent) const{
|
||||||
if (last && depth) {
|
if (last && depth) {
|
||||||
indent.back()=" ";
|
indent.back()=" ";
|
||||||
} else if (!last && depth) {
|
} else if (!last && depth) {
|
||||||
#ifdef _WIN32
|
indent.back()=is_windows()? "| ":"│ ";
|
||||||
indent.back()="| ";
|
|
||||||
#else
|
|
||||||
indent.back()="│ ";
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
for(u32 i=0;i<nd_child.size();++i) {
|
for(u32 i=0;i<nd_child.size();++i) {
|
||||||
#ifdef _WIN32
|
if (is_windows()) {
|
||||||
indent.push_back(i==nd_child.size()-1?"+-":"|-");
|
indent.push_back(i==nd_child.size()-1?"+-":"|-");
|
||||||
#else
|
} else {
|
||||||
indent.push_back(i==nd_child.size()-1?"└─":"├─");
|
indent.push_back(i==nd_child.size()-1?"└─":"├─");
|
||||||
#endif
|
}
|
||||||
nd_child[i].print(depth+1,i==nd_child.size()-1,indent);
|
nd_child[i].print(depth+1,i==nd_child.size()-1,indent);
|
||||||
indent.pop_back();
|
indent.pop_back();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1005,13 +1005,13 @@ var builtin_dlcall(var* local,gc& ngc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var builtin_platform(var* local,gc& ngc) {
|
var builtin_platform(var* local,gc& ngc) {
|
||||||
#if defined _WIN32 || defined _WIN64
|
if (is_windows()) {
|
||||||
return ngc.newstr("windows");
|
return ngc.newstr("windows");
|
||||||
#elif defined __linux__
|
} else if (is_linux()) {
|
||||||
return ngc.newstr("linux");
|
return ngc.newstr("linux");
|
||||||
#elif defined __APPLE__
|
} else if (is_macos()) {
|
||||||
return ngc.newstr("macOS");
|
return ngc.newstr("macOS");
|
||||||
#endif
|
}
|
||||||
return ngc.newstr("unknown");
|
return ngc.newstr("unknown");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -230,6 +230,7 @@ private:
|
||||||
void gen(u8,u32,u32);
|
void gen(u8,u32,u32);
|
||||||
void num_gen(const ast&);
|
void num_gen(const ast&);
|
||||||
void str_gen(const ast&);
|
void str_gen(const ast&);
|
||||||
|
void bool_gen(const ast&);
|
||||||
void vec_gen(const ast&);
|
void vec_gen(const ast&);
|
||||||
void hash_gen(const ast&);
|
void hash_gen(const ast&);
|
||||||
void func_gen(const ast&);
|
void func_gen(const ast&);
|
||||||
|
@ -390,6 +391,12 @@ void codegen::str_gen(const ast& node) {
|
||||||
gen(op_pstr,str_table[node.str()],node.line());
|
gen(op_pstr,str_table[node.str()],node.line());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void codegen::bool_gen(const ast& node) {
|
||||||
|
f64 num=node.str()=="true"?1:0;
|
||||||
|
regist_num(num);
|
||||||
|
gen(op_pnum,num_table[num],node.line());
|
||||||
|
}
|
||||||
|
|
||||||
void codegen::vec_gen(const ast& node) {
|
void codegen::vec_gen(const ast& node) {
|
||||||
for(auto& child:node.child()) {
|
for(auto& child:node.child()) {
|
||||||
calc_gen(child);
|
calc_gen(child);
|
||||||
|
@ -804,7 +811,7 @@ void codegen::for_gen(const ast& node) {
|
||||||
gen(op_pop,0,node[0].line());
|
gen(op_pop,0,node[0].line());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ast_nil:case ast_num:case ast_str:break;
|
case ast_nil:case ast_num:case ast_str:case ast_bool:break;
|
||||||
case ast_vec:case ast_hash:case ast_func:
|
case ast_vec:case ast_hash:case ast_func:
|
||||||
case ast_call:
|
case ast_call:
|
||||||
case ast_neg:case ast_not:
|
case ast_neg:case ast_not:
|
||||||
|
@ -870,7 +877,7 @@ void codegen::for_gen(const ast& node) {
|
||||||
gen(op_pop,0,node[2].line());
|
gen(op_pop,0,node[2].line());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ast_nil:case ast_num:case ast_str:break;
|
case ast_nil:case ast_num:case ast_str:case ast_bool:break;
|
||||||
case ast_vec:case ast_hash:case ast_func:
|
case ast_vec:case ast_hash:case ast_func:
|
||||||
case ast_call:
|
case ast_call:
|
||||||
case ast_neg:case ast_not:
|
case ast_neg:case ast_not:
|
||||||
|
@ -1029,6 +1036,7 @@ void codegen::calc_gen(const ast& node) {
|
||||||
case ast_num: num_gen(node); break;
|
case ast_num: num_gen(node); break;
|
||||||
case ast_str: str_gen(node); break;
|
case ast_str: str_gen(node); break;
|
||||||
case ast_id: call_id(node); break;
|
case ast_id: call_id(node); break;
|
||||||
|
case ast_bool: bool_gen(node); break;
|
||||||
case ast_vec: vec_gen(node); break;
|
case ast_vec: vec_gen(node); break;
|
||||||
case ast_hash: hash_gen(node); break;
|
case ast_hash: hash_gen(node); break;
|
||||||
case ast_func: func_gen(node); break;
|
case ast_func: func_gen(node); break;
|
||||||
|
@ -1122,7 +1130,11 @@ void codegen::calc_gen(const ast& node) {
|
||||||
void codegen::block_gen(const ast& node) {
|
void codegen::block_gen(const ast& node) {
|
||||||
for(auto& tmp:node.child()) {
|
for(auto& tmp:node.child()) {
|
||||||
switch(tmp.type()) {
|
switch(tmp.type()) {
|
||||||
case ast_null:case ast_nil:case ast_num:case ast_str:break;
|
case ast_null:
|
||||||
|
case ast_nil:
|
||||||
|
case ast_num:
|
||||||
|
case ast_str:
|
||||||
|
case ast_bool:break;
|
||||||
case ast_file:fileindex=tmp.num();break; // special node type in main block
|
case ast_file:fileindex=tmp.num();break; // special node type in main block
|
||||||
case ast_def:def_gen(tmp);break;
|
case ast_def:def_gen(tmp);break;
|
||||||
case ast_multi_assign:multi_assign_gen(tmp);break;
|
case ast_multi_assign:multi_assign_gen(tmp);break;
|
||||||
|
|
|
@ -145,7 +145,7 @@ void debugger::interact() {
|
||||||
next=false;
|
next=false;
|
||||||
string cmd;
|
string cmd;
|
||||||
stepinfo();
|
stepinfo();
|
||||||
while(1) {
|
while(true) {
|
||||||
std::cout<<">> ";
|
std::cout<<">> ";
|
||||||
std::getline(std::cin,cmd);
|
std::getline(std::cin,cmd);
|
||||||
auto res=parse(cmd);
|
auto res=parse(cmd);
|
||||||
|
|
|
@ -39,11 +39,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
linker::linker(error& e):show_path(false),lib_loaded(false),err(e) {
|
linker::linker(error& e):show_path(false),lib_loaded(false),err(e) {
|
||||||
#ifdef _WIN32
|
char sep=is_windows()? ';':':';
|
||||||
char sep=';';
|
|
||||||
#else
|
|
||||||
char sep=':';
|
|
||||||
#endif
|
|
||||||
string PATH=getenv("PATH");
|
string PATH=getenv("PATH");
|
||||||
usize last=0,pos=PATH.find(sep,0);
|
usize last=0,pos=PATH.find(sep,0);
|
||||||
while(pos!=string::npos) {
|
while(pos!=string::npos) {
|
||||||
|
@ -77,11 +73,7 @@ string linker::path(const ast& node) {
|
||||||
string linker::findf(const string& fname) {
|
string linker::findf(const string& fname) {
|
||||||
std::vector<string> fpath={fname};
|
std::vector<string> fpath={fname};
|
||||||
for(auto&p:envpath) {
|
for(auto&p:envpath) {
|
||||||
#ifdef _WIN32
|
fpath.push_back(p+(is_windows()? "\\":"/")+fname);
|
||||||
fpath.push_back(p+"\\"+fname);
|
|
||||||
#else
|
|
||||||
fpath.push_back(p+"/"+fname);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
for(auto& i:fpath) {
|
for(auto& i:fpath) {
|
||||||
if (access(i.c_str(),F_OK)!=-1) {
|
if (access(i.c_str(),F_OK)!=-1) {
|
||||||
|
@ -89,11 +81,7 @@ string linker::findf(const string& fname) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fname=="lib.nas") {
|
if (fname=="lib.nas") {
|
||||||
#ifdef _WIN32
|
return is_windows()? findf("stl\\lib.nas"):findf("stl/lib.nas");
|
||||||
return findf("stl\\lib.nas");
|
|
||||||
#else
|
|
||||||
return findf("stl/lib.nas");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
if (!show_path) {
|
if (!show_path) {
|
||||||
err.err("link","cannot find file <"+fname+">");
|
err.err("link","cannot find file <"+fname+">");
|
||||||
|
|
|
@ -18,6 +18,8 @@ enum class tok:u32 {
|
||||||
num, // number literal
|
num, // number literal
|
||||||
str, // string literal
|
str, // string literal
|
||||||
id, // identifier
|
id, // identifier
|
||||||
|
tktrue, // keyword true
|
||||||
|
tkfalse, // keyword false
|
||||||
rfor, // loop keyword for
|
rfor, // loop keyword for
|
||||||
forindex, // loop keyword forindex
|
forindex, // loop keyword forindex
|
||||||
foreach, // loop keyword foreach
|
foreach, // loop keyword foreach
|
||||||
|
@ -88,6 +90,8 @@ private:
|
||||||
error& err;
|
error& err;
|
||||||
std::vector<token> toks;
|
std::vector<token> toks;
|
||||||
std::unordered_map<string,tok> typetbl {
|
std::unordered_map<string,tok> typetbl {
|
||||||
|
{"true" ,tok::tktrue },
|
||||||
|
{"false" ,tok::tkfalse },
|
||||||
{"for" ,tok::rfor },
|
{"for" ,tok::rfor },
|
||||||
{"forindex",tok::forindex},
|
{"forindex",tok::forindex},
|
||||||
{"foreach" ,tok::foreach },
|
{"foreach" ,tok::foreach },
|
||||||
|
|
|
@ -116,6 +116,7 @@ private:
|
||||||
ast num();
|
ast num();
|
||||||
ast str();
|
ast str();
|
||||||
ast id();
|
ast id();
|
||||||
|
ast bools();
|
||||||
ast vec();
|
ast vec();
|
||||||
ast hash();
|
ast hash();
|
||||||
ast pair();
|
ast pair();
|
||||||
|
@ -337,13 +338,24 @@ ast parse::id() {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ast parse::bools() {
|
||||||
|
ast node(toks[ptr].tk_end_line,toks[ptr].tk_end_column,ast_bool,toks[ptr].file);
|
||||||
|
node.set_str(toks[ptr].str);
|
||||||
|
if (lookahead(tok::tktrue)) {
|
||||||
|
match(tok::tktrue);
|
||||||
|
} else {
|
||||||
|
match(tok::tkfalse);
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
ast parse::vec() {
|
ast parse::vec() {
|
||||||
// panic set for this token is not ','
|
// panic set for this token is not ','
|
||||||
// this is the FIRST set of calculation
|
// this is the FIRST set of calculation
|
||||||
// array end with tok::null=0
|
// array end with tok::null=0
|
||||||
const tok panic[]={
|
const tok panic[]={
|
||||||
tok::id,tok::str,tok::num,
|
tok::id,tok::str,tok::num,tok::tktrue,
|
||||||
tok::opnot,tok::sub,tok::tknil,
|
tok::tkfalse,tok::opnot,tok::sub,tok::tknil,
|
||||||
tok::func,tok::var,tok::lcurve,
|
tok::func,tok::var,tok::lcurve,
|
||||||
tok::lbrace,tok::lbracket,tok::null
|
tok::lbrace,tok::lbracket,tok::null
|
||||||
};
|
};
|
||||||
|
@ -460,6 +472,8 @@ ast parse::expr()
|
||||||
case tok::num:
|
case tok::num:
|
||||||
case tok::str:
|
case tok::str:
|
||||||
case tok::id:
|
case tok::id:
|
||||||
|
case tok::tktrue:
|
||||||
|
case tok::tkfalse:
|
||||||
case tok::func:
|
case tok::func:
|
||||||
case tok::lbracket:
|
case tok::lbracket:
|
||||||
case tok::lbrace:
|
case tok::lbrace:
|
||||||
|
@ -621,6 +635,8 @@ ast parse::scalar() {
|
||||||
node=str();
|
node=str();
|
||||||
} else if (lookahead(tok::id)) {
|
} else if (lookahead(tok::id)) {
|
||||||
node=id();
|
node=id();
|
||||||
|
} else if (lookahead(tok::tktrue) || lookahead(tok::tkfalse)) {
|
||||||
|
node=bools();
|
||||||
} else if (lookahead(tok::func)) {
|
} else if (lookahead(tok::func)) {
|
||||||
node=func();
|
node=func();
|
||||||
} else if (lookahead(tok::lbracket)) {
|
} else if (lookahead(tok::lbracket)) {
|
||||||
|
@ -677,8 +693,8 @@ ast parse::callv() {
|
||||||
// this is the FIRST set of subvec
|
// this is the FIRST set of subvec
|
||||||
// array end with tok::null=0
|
// array end with tok::null=0
|
||||||
const tok panic[]={
|
const tok panic[]={
|
||||||
tok::id,tok::str,tok::num,
|
tok::id,tok::str,tok::num,tok::tktrue,
|
||||||
tok::opnot,tok::sub,tok::tknil,
|
tok::tkfalse,tok::opnot,tok::sub,tok::tknil,
|
||||||
tok::func,tok::var,tok::lcurve,
|
tok::func,tok::var,tok::lcurve,
|
||||||
tok::lbrace,tok::lbracket,tok::colon,
|
tok::lbrace,tok::lbracket,tok::colon,
|
||||||
tok::null
|
tok::null
|
||||||
|
@ -707,8 +723,8 @@ ast parse::callf() {
|
||||||
// this is the FIRST set of calculation/hashmember
|
// this is the FIRST set of calculation/hashmember
|
||||||
// array end with tok::null=0
|
// array end with tok::null=0
|
||||||
const tok panic[]={
|
const tok panic[]={
|
||||||
tok::id,tok::str,tok::num,
|
tok::id,tok::str,tok::num,tok::tktrue,
|
||||||
tok::opnot,tok::sub,tok::tknil,
|
tok::tkfalse,tok::opnot,tok::sub,tok::tknil,
|
||||||
tok::func,tok::var,tok::lcurve,
|
tok::func,tok::var,tok::lcurve,
|
||||||
tok::lbrace,tok::lbracket,tok::null
|
tok::lbrace,tok::lbracket,tok::null
|
||||||
};
|
};
|
||||||
|
@ -798,8 +814,8 @@ ast parse::multi_id() {
|
||||||
ast parse::multi_scalar() {
|
ast parse::multi_scalar() {
|
||||||
// if check_call_memory is true,we will check if value called here can reach a memory space
|
// if check_call_memory is true,we will check if value called here can reach a memory space
|
||||||
const tok panic[]={
|
const tok panic[]={
|
||||||
tok::id,tok::str,tok::num,
|
tok::id,tok::str,tok::num,tok::tktrue,
|
||||||
tok::opnot,tok::sub,tok::tknil,
|
tok::tkfalse,tok::opnot,tok::sub,tok::tknil,
|
||||||
tok::func,tok::var,tok::lcurve,
|
tok::func,tok::var,tok::lcurve,
|
||||||
tok::lbrace,tok::lbracket,tok::null
|
tok::lbrace,tok::lbracket,tok::null
|
||||||
};
|
};
|
||||||
|
|
|
@ -51,6 +51,7 @@ z.funcc(); #//f is called
|
||||||
println(z.funcccall); #//func(..){..}
|
println(z.funcccall); #//func(..){..}
|
||||||
z2.listt2[3].hashh.funcc(); #//f is called
|
z2.listt2[3].hashh.funcc(); #//f is called
|
||||||
println(y1[f2()][w]); #//hello
|
println(y1[f2()][w]); #//hello
|
||||||
|
println(true,' ',false); #//1 0
|
||||||
|
|
||||||
|
|
||||||
# ValKmjolnir
|
# ValKmjolnir
|
||||||
|
|
|
@ -203,5 +203,5 @@ foreach(i;a){
|
||||||
}
|
}
|
||||||
println(runtime.argv());
|
println(runtime.argv());
|
||||||
func(a,b,c,d="只有红茶可以吗"){
|
func(a,b,c,d="只有红茶可以吗"){
|
||||||
println(a,' ',b,' ',c,' ',d);
|
println(a,' ',b,' ',c,' ',d,' true: ',true,' false: ',false);
|
||||||
}(c:1919810,b:514,a:114);
|
}(c:1919810,b:514,a:114);
|
Loading…
Reference in New Issue