parent
c4a6d94543
commit
e8341c7b06
Binary file not shown.
18
README.md
18
README.md
|
@ -25,24 +25,8 @@ I wrote the lexer, parser and runtime(nasal virtual machine/ast-runtime virtual
|
|||
They found it easier for them to check errors before copying nasal-codes in nasal-console in Flightgear to test.
|
||||
|
||||
# Lexical Analysis
|
||||
|
||||
What do it's outputs look like?
|
||||
|
||||
> ( identifier | start )
|
||||
|
||||
> ( operator | ; )
|
||||
|
||||
> ( reserve word | print )
|
||||
|
||||
> ( operator | ( )
|
||||
|
||||
> ( string | Engine started )
|
||||
|
||||
> ( operator | ) )
|
||||
|
||||
This is what it outputs.
|
||||
|
||||
And the flow chart of lexer is here:
|
||||
The flow chart of lexer is here:
|
||||
|
||||
[](https://github.com/ValKmjolnir/Nasal-Interpreter/blob/master/pic/nasal_lexer.png)
|
||||
|
||||
|
|
|
@ -1,163 +1,163 @@
|
|||
var import=func(filename)
|
||||
{
|
||||
nasal_call_import(filename);
|
||||
return nil;
|
||||
}
|
||||
var print=func(elements...)
|
||||
{
|
||||
nasal_call_builtin_std_cout(elements);
|
||||
return nil;
|
||||
};
|
||||
var append=func(vector,elements...)
|
||||
{
|
||||
nasal_call_builtin_push_back(vector,elements);
|
||||
return nil;
|
||||
}
|
||||
var setsize=func(vector,size)
|
||||
{
|
||||
nasal_call_builtin_set_size(vector,size);
|
||||
return nil;
|
||||
}
|
||||
var system=func(str)
|
||||
{
|
||||
nasal_call_builtin_system(str);
|
||||
return;
|
||||
}
|
||||
var input=func()
|
||||
{
|
||||
return nasal_call_builtin_input();
|
||||
}
|
||||
var sleep=func(duration)
|
||||
{
|
||||
nasal_call_builtin_sleep(duration);
|
||||
return;
|
||||
}
|
||||
var split=func(delimeter,string)
|
||||
{
|
||||
return nasal_call_builtin_split(delimeter,string);
|
||||
}
|
||||
var rand=func(seed=nil)
|
||||
{
|
||||
return nasal_call_builtin_rand(seed);
|
||||
}
|
||||
var id=func(thing)
|
||||
{
|
||||
return nasal_call_builtin_get_id(thing);
|
||||
}
|
||||
var int=func(value)
|
||||
{
|
||||
return nasal_call_builtin_trans_int(value);
|
||||
}
|
||||
var num=func(value)
|
||||
{
|
||||
return nasal_call_builtin_trans_num(value);
|
||||
}
|
||||
var pop=func(vector)
|
||||
{
|
||||
return nasal_call_builtin_pop_back(vector);
|
||||
}
|
||||
var str=func(number)
|
||||
{
|
||||
return nasal_call_builtin_trans_str(number);
|
||||
}
|
||||
var size=func(object)
|
||||
{
|
||||
return nasal_call_builtin_size(object);
|
||||
}
|
||||
var contains=func(hash,key)
|
||||
{
|
||||
return nasal_call_builtin_contains(hash,key);
|
||||
}
|
||||
var delete=func(hash,key)
|
||||
{
|
||||
nasal_call_builtin_delete(hash,key);
|
||||
return;
|
||||
}
|
||||
var keys=func(hash)
|
||||
{
|
||||
return nasal_call_builtin_get_keys(hash);
|
||||
}
|
||||
var time=func(begin_time)
|
||||
{
|
||||
return nasal_call_builtin_time(begin_time);
|
||||
}
|
||||
var die=func(str)
|
||||
{
|
||||
nasal_call_builtin_die(str);
|
||||
return nil;
|
||||
}
|
||||
var type=func(object)
|
||||
{
|
||||
return nasal_call_builtin_type(object);
|
||||
}
|
||||
|
||||
var io=
|
||||
{
|
||||
fin:func(filename)
|
||||
{
|
||||
return nasal_call_builtin_finput(filename);
|
||||
},
|
||||
fout:func(filename,str)
|
||||
{
|
||||
nasal_call_builtin_foutput(filename,str);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
var bits=
|
||||
{
|
||||
bitxor:func(a,b)
|
||||
{
|
||||
return nasal_call_builtin_xor(a,b);
|
||||
},
|
||||
bitand:func(a,b)
|
||||
{
|
||||
return nasal_call_builtin_and(a,b);
|
||||
},
|
||||
bitor:func(a,b)
|
||||
{
|
||||
return nasal_call_builtin_or(a,b);
|
||||
},
|
||||
bitnand:func(a,b)
|
||||
{
|
||||
return nasal_call_builtin_nand(a,b);
|
||||
},
|
||||
bitnot:func(a)
|
||||
{
|
||||
return nasal_call_builtin_not(a);
|
||||
}
|
||||
};
|
||||
|
||||
var math=
|
||||
{
|
||||
e:2.7182818284590452354,
|
||||
pi:3.14159265358979323846,
|
||||
sin:func(x)
|
||||
{
|
||||
return nasal_call_builtin_sin(x);
|
||||
},
|
||||
cos:func(x)
|
||||
{
|
||||
return nasal_call_builtin_cos(x);
|
||||
},
|
||||
tan:func(x)
|
||||
{
|
||||
return nasal_call_builtin_tan(x);
|
||||
},
|
||||
exp:func(x)
|
||||
{
|
||||
return nasal_call_builtin_exp(x);
|
||||
},
|
||||
ln:func(x)
|
||||
{
|
||||
return nasal_call_builtin_cpp_math_ln(x);
|
||||
},
|
||||
sqrt:func(x)
|
||||
{
|
||||
return nasal_call_builtin_cpp_math_sqrt(x);
|
||||
},
|
||||
atan2:func(x,y)
|
||||
{
|
||||
return nasal_call_builtin_cpp_atan2(x,y);
|
||||
},
|
||||
};
|
||||
var import=func(filename)
|
||||
{
|
||||
nasal_call_import(filename);
|
||||
return nil;
|
||||
}
|
||||
var print=func(elements...)
|
||||
{
|
||||
nasal_call_builtin_std_cout(elements);
|
||||
return nil;
|
||||
};
|
||||
var append=func(vector,elements...)
|
||||
{
|
||||
nasal_call_builtin_push_back(vector,elements);
|
||||
return nil;
|
||||
}
|
||||
var setsize=func(vector,size)
|
||||
{
|
||||
nasal_call_builtin_set_size(vector,size);
|
||||
return nil;
|
||||
}
|
||||
var system=func(str)
|
||||
{
|
||||
nasal_call_builtin_system(str);
|
||||
return;
|
||||
}
|
||||
var input=func()
|
||||
{
|
||||
return nasal_call_builtin_input();
|
||||
}
|
||||
var sleep=func(duration)
|
||||
{
|
||||
nasal_call_builtin_sleep(duration);
|
||||
return;
|
||||
}
|
||||
var split=func(delimeter,string)
|
||||
{
|
||||
return nasal_call_builtin_split(delimeter,string);
|
||||
}
|
||||
var rand=func(seed=nil)
|
||||
{
|
||||
return nasal_call_builtin_rand(seed);
|
||||
}
|
||||
var id=func(thing)
|
||||
{
|
||||
return nasal_call_builtin_get_id(thing);
|
||||
}
|
||||
var int=func(value)
|
||||
{
|
||||
return nasal_call_builtin_trans_int(value);
|
||||
}
|
||||
var num=func(value)
|
||||
{
|
||||
return nasal_call_builtin_trans_num(value);
|
||||
}
|
||||
var pop=func(vector)
|
||||
{
|
||||
return nasal_call_builtin_pop_back(vector);
|
||||
}
|
||||
var str=func(number)
|
||||
{
|
||||
return nasal_call_builtin_trans_str(number);
|
||||
}
|
||||
var size=func(object)
|
||||
{
|
||||
return nasal_call_builtin_size(object);
|
||||
}
|
||||
var contains=func(hash,key)
|
||||
{
|
||||
return nasal_call_builtin_contains(hash,key);
|
||||
}
|
||||
var delete=func(hash,key)
|
||||
{
|
||||
nasal_call_builtin_delete(hash,key);
|
||||
return;
|
||||
}
|
||||
var keys=func(hash)
|
||||
{
|
||||
return nasal_call_builtin_get_keys(hash);
|
||||
}
|
||||
var time=func(begin_time)
|
||||
{
|
||||
return nasal_call_builtin_time(begin_time);
|
||||
}
|
||||
var die=func(str)
|
||||
{
|
||||
nasal_call_builtin_die(str);
|
||||
return nil;
|
||||
}
|
||||
var type=func(object)
|
||||
{
|
||||
return nasal_call_builtin_type(object);
|
||||
}
|
||||
|
||||
var io=
|
||||
{
|
||||
fin:func(filename)
|
||||
{
|
||||
return nasal_call_builtin_finput(filename);
|
||||
},
|
||||
fout:func(filename,str)
|
||||
{
|
||||
nasal_call_builtin_foutput(filename,str);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
var bits=
|
||||
{
|
||||
bitxor:func(a,b)
|
||||
{
|
||||
return nasal_call_builtin_xor(a,b);
|
||||
},
|
||||
bitand:func(a,b)
|
||||
{
|
||||
return nasal_call_builtin_and(a,b);
|
||||
},
|
||||
bitor:func(a,b)
|
||||
{
|
||||
return nasal_call_builtin_or(a,b);
|
||||
},
|
||||
bitnand:func(a,b)
|
||||
{
|
||||
return nasal_call_builtin_nand(a,b);
|
||||
},
|
||||
bitnot:func(a)
|
||||
{
|
||||
return nasal_call_builtin_not(a);
|
||||
}
|
||||
};
|
||||
|
||||
var math=
|
||||
{
|
||||
e:2.7182818284590452354,
|
||||
pi:3.14159265358979323846,
|
||||
sin:func(x)
|
||||
{
|
||||
return nasal_call_builtin_sin(x);
|
||||
},
|
||||
cos:func(x)
|
||||
{
|
||||
return nasal_call_builtin_cos(x);
|
||||
},
|
||||
tan:func(x)
|
||||
{
|
||||
return nasal_call_builtin_tan(x);
|
||||
},
|
||||
exp:func(x)
|
||||
{
|
||||
return nasal_call_builtin_exp(x);
|
||||
},
|
||||
ln:func(x)
|
||||
{
|
||||
return nasal_call_builtin_cpp_math_ln(x);
|
||||
},
|
||||
sqrt:func(x)
|
||||
{
|
||||
return nasal_call_builtin_cpp_math_sqrt(x);
|
||||
},
|
||||
atan2:func(x,y)
|
||||
{
|
||||
return nasal_call_builtin_cpp_atan2(x,y);
|
||||
},
|
||||
};
|
|
@ -1,248 +1,248 @@
|
|||
#include "nasal.h"
|
||||
|
||||
nasal_resource resource;
|
||||
nasal_lexer lexer;
|
||||
nasal_parse parse;
|
||||
nasal_import preprocessor;
|
||||
nasal_codegen code_generator;
|
||||
std::string command;
|
||||
std::string inputfile="null";
|
||||
nasal_runtime runtime;
|
||||
|
||||
void help()
|
||||
{
|
||||
std::cout<<">> [\"file\"] input a file name.\n";
|
||||
std::cout<<">> [clear ] clear the screen.\n";
|
||||
std::cout<<">> [del ] clear the input filename.\n";
|
||||
std::cout<<">> [rs ] print source code.\n";
|
||||
std::cout<<">> [lex ] use lexer to turn code into tokens.\n";
|
||||
std::cout<<">> [ast ] do parsing and check the abstract syntax tree.\n";
|
||||
std::cout<<">> [run ] run abstract syntax tree.\n";
|
||||
std::cout<<">> [exec ] generate byte code.\n";
|
||||
std::cout<<">> [erun ] run byte code.\n";
|
||||
std::cout<<">> [logo ] print logo of nasal .\n";
|
||||
std::cout<<">> [exit ] quit nasal interpreter.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
void logo()
|
||||
{
|
||||
std::cout<<" __ _ \n";
|
||||
std::cout<<" /\\ \\ \\__ _ ___ __ _| | \n";
|
||||
std::cout<<" / \\/ / _` / __|/ _` | | \n";
|
||||
std::cout<<" / /\\ / (_| \\__ \\ (_| | | \n";
|
||||
std::cout<<" \\_\\ \\/ \\__,_|___/\\__,_|_|\n";
|
||||
return;
|
||||
}
|
||||
|
||||
void del_func()
|
||||
{
|
||||
resource.clear();
|
||||
lexer.clear();
|
||||
parse.clear();
|
||||
inputfile="null";
|
||||
std::cout<<">> [Delete] complete.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
void die(std::string stage,std::string filename)
|
||||
{
|
||||
std::cout<<">> ["<<stage<<"] in <\""<<filename<<"\">: error(s) occurred,stop.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
void lex_func()
|
||||
{
|
||||
if(!resource.input_file(inputfile))
|
||||
{
|
||||
die("resource",inputfile);
|
||||
return;
|
||||
}
|
||||
lexer.scanner(resource.get_file());
|
||||
if(lexer.get_error())
|
||||
{
|
||||
die("lexer",inputfile);
|
||||
return;
|
||||
}
|
||||
lexer.print_token();
|
||||
return;
|
||||
}
|
||||
|
||||
void ast_print()
|
||||
{
|
||||
if(!resource.input_file(inputfile))
|
||||
{
|
||||
die("resource",inputfile);
|
||||
return;
|
||||
}
|
||||
lexer.scanner(resource.get_file());
|
||||
if(lexer.get_error())
|
||||
{
|
||||
die("lexer",inputfile);
|
||||
return;
|
||||
}
|
||||
parse.set_toklist(lexer.get_token_list());
|
||||
parse.main_process();
|
||||
if(parse.get_error())
|
||||
{
|
||||
die("parse",inputfile);
|
||||
return;
|
||||
}
|
||||
parse.get_root().print_ast(0);
|
||||
return;
|
||||
}
|
||||
void runtime_start()
|
||||
{
|
||||
if(!resource.input_file(inputfile))
|
||||
{
|
||||
die("resource",inputfile);
|
||||
return;
|
||||
}
|
||||
lexer.scanner(resource.get_file());
|
||||
if(lexer.get_error())
|
||||
{
|
||||
die("lexer",inputfile);
|
||||
return;
|
||||
}
|
||||
parse.set_toklist(lexer.get_token_list());
|
||||
parse.main_process();
|
||||
if(parse.get_error())
|
||||
{
|
||||
die("parse",inputfile);
|
||||
return;
|
||||
}
|
||||
preprocessor.preprocessing(parse.get_root());
|
||||
if(preprocessor.get_error())
|
||||
{
|
||||
die("import",inputfile);
|
||||
return;
|
||||
}
|
||||
runtime.set_root(preprocessor.get_root());
|
||||
runtime.run();
|
||||
return;
|
||||
}
|
||||
|
||||
void codegen_start()
|
||||
{
|
||||
if(!resource.input_file(inputfile))
|
||||
{
|
||||
die("resource",inputfile);
|
||||
return;
|
||||
}
|
||||
lexer.scanner(resource.get_file());
|
||||
if(lexer.get_error())
|
||||
{
|
||||
die("lexer",inputfile);
|
||||
return;
|
||||
}
|
||||
parse.set_toklist(lexer.get_token_list());
|
||||
parse.main_process();
|
||||
if(parse.get_error())
|
||||
{
|
||||
die("parse",inputfile);
|
||||
return;
|
||||
}
|
||||
preprocessor.preprocessing(parse.get_root());
|
||||
if(preprocessor.get_error())
|
||||
{
|
||||
die("import",inputfile);
|
||||
return;
|
||||
}
|
||||
runtime.set_root(preprocessor.get_root());
|
||||
code_generator.output_exec(inputfile+".naexec",preprocessor.get_root());
|
||||
if(code_generator.get_error())
|
||||
{
|
||||
die("code",inputfile);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void execution_start()
|
||||
{
|
||||
code_generator.load_exec(inputfile,preprocessor.get_root());
|
||||
if(code_generator.get_error())
|
||||
{
|
||||
die("code",inputfile);
|
||||
return;
|
||||
}
|
||||
runtime.set_root(preprocessor.get_root());
|
||||
runtime.run();
|
||||
return;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// use chcp 65001 to use unicode io
|
||||
system("chcp 65001");
|
||||
system("cls");
|
||||
#endif
|
||||
logo();
|
||||
#ifdef _WIN32
|
||||
std::cout<<">> [system] Windows system.\n";
|
||||
#endif
|
||||
#ifdef _linux_
|
||||
std::cout<<">> [system] Linux system.\n";
|
||||
#endif
|
||||
#ifdef TARGET_OS_MAC
|
||||
std::cout<<">> [system] MacOS system.\n";
|
||||
#endif
|
||||
|
||||
std::cout<<">> Nasal interpreter ver 3.0 .\n";
|
||||
std::cout<<">> Code: https://github.com/ValKmjolnir/Nasal-Interpreter\n";
|
||||
std::cout<<">> Info: http://wiki.flightgear.org/Nasal_scripting_language\n";
|
||||
std::cout<<">> Input \"help\" to get help .\n";
|
||||
while(1)
|
||||
{
|
||||
std::cout<<">> ";
|
||||
std::cin>>command;
|
||||
if(command=="help")
|
||||
help();
|
||||
else if(command=="clear")
|
||||
{
|
||||
#ifdef _WIN32
|
||||
system("cls");
|
||||
#endif
|
||||
#ifdef _linux_
|
||||
system("clear");
|
||||
#endif
|
||||
#ifdef TARGET_OS_MAC
|
||||
system("clear");
|
||||
#endif
|
||||
}
|
||||
else if(command=="del")
|
||||
del_func();
|
||||
else if(command=="rs")
|
||||
{
|
||||
if(resource.input_file(inputfile))
|
||||
resource.print_file();
|
||||
}
|
||||
else if(command=="lex")
|
||||
lex_func();
|
||||
else if(command=="ast")
|
||||
ast_print();
|
||||
else if(command=="run")
|
||||
runtime_start();
|
||||
else if(command=="exec")
|
||||
codegen_start();
|
||||
else if(command=="erun")
|
||||
execution_start();
|
||||
else if(command=="logo")
|
||||
logo();
|
||||
else if(command=="exit")
|
||||
break;
|
||||
else
|
||||
{
|
||||
inputfile=command;
|
||||
std::ifstream fin(command);
|
||||
if(fin.fail())
|
||||
{
|
||||
std::cout<<">> [file] cannot open file \""<<command<<"\".\n";
|
||||
inputfile="null";
|
||||
}
|
||||
fin.close();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
#include "nasal.h"
|
||||
|
||||
nasal_resource resource;
|
||||
nasal_lexer lexer;
|
||||
nasal_parse parse;
|
||||
nasal_import preprocessor;
|
||||
nasal_codegen code_generator;
|
||||
std::string command;
|
||||
std::string inputfile="null";
|
||||
nasal_runtime runtime;
|
||||
|
||||
void help()
|
||||
{
|
||||
std::cout<<">> [\"file\"] input a file name.\n";
|
||||
std::cout<<">> [clear ] clear the screen.\n";
|
||||
std::cout<<">> [del ] clear the input filename.\n";
|
||||
std::cout<<">> [rs ] print source code.\n";
|
||||
std::cout<<">> [lex ] use lexer to turn code into tokens.\n";
|
||||
std::cout<<">> [ast ] do parsing and check the abstract syntax tree.\n";
|
||||
std::cout<<">> [run ] run abstract syntax tree.\n";
|
||||
std::cout<<">> [exec ] generate byte code.\n";
|
||||
std::cout<<">> [erun ] run byte code.\n";
|
||||
std::cout<<">> [logo ] print logo of nasal .\n";
|
||||
std::cout<<">> [exit ] quit nasal interpreter.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
void logo()
|
||||
{
|
||||
std::cout<<" __ _ \n";
|
||||
std::cout<<" /\\ \\ \\__ _ ___ __ _| | \n";
|
||||
std::cout<<" / \\/ / _` / __|/ _` | | \n";
|
||||
std::cout<<" / /\\ / (_| \\__ \\ (_| | | \n";
|
||||
std::cout<<" \\_\\ \\/ \\__,_|___/\\__,_|_|\n";
|
||||
return;
|
||||
}
|
||||
|
||||
void del_func()
|
||||
{
|
||||
resource.clear();
|
||||
lexer.clear();
|
||||
parse.clear();
|
||||
inputfile="null";
|
||||
std::cout<<">> [Delete] complete.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
void die(std::string stage,std::string filename)
|
||||
{
|
||||
std::cout<<">> ["<<stage<<"] in <\""<<filename<<"\">: error(s) occurred,stop.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
void lex_func()
|
||||
{
|
||||
if(!resource.input_file(inputfile))
|
||||
{
|
||||
die("resource",inputfile);
|
||||
return;
|
||||
}
|
||||
lexer.scanner(resource.get_file());
|
||||
if(lexer.get_error())
|
||||
{
|
||||
die("lexer",inputfile);
|
||||
return;
|
||||
}
|
||||
lexer.print_token();
|
||||
return;
|
||||
}
|
||||
|
||||
void ast_print()
|
||||
{
|
||||
if(!resource.input_file(inputfile))
|
||||
{
|
||||
die("resource",inputfile);
|
||||
return;
|
||||
}
|
||||
lexer.scanner(resource.get_file());
|
||||
if(lexer.get_error())
|
||||
{
|
||||
die("lexer",inputfile);
|
||||
return;
|
||||
}
|
||||
parse.set_toklist(lexer.get_token_list());
|
||||
parse.main_process();
|
||||
if(parse.get_error())
|
||||
{
|
||||
die("parse",inputfile);
|
||||
return;
|
||||
}
|
||||
parse.get_root().print_ast(0);
|
||||
return;
|
||||
}
|
||||
void runtime_start()
|
||||
{
|
||||
if(!resource.input_file(inputfile))
|
||||
{
|
||||
die("resource",inputfile);
|
||||
return;
|
||||
}
|
||||
lexer.scanner(resource.get_file());
|
||||
if(lexer.get_error())
|
||||
{
|
||||
die("lexer",inputfile);
|
||||
return;
|
||||
}
|
||||
parse.set_toklist(lexer.get_token_list());
|
||||
parse.main_process();
|
||||
if(parse.get_error())
|
||||
{
|
||||
die("parse",inputfile);
|
||||
return;
|
||||
}
|
||||
preprocessor.preprocessing(parse.get_root());
|
||||
if(preprocessor.get_error())
|
||||
{
|
||||
die("import",inputfile);
|
||||
return;
|
||||
}
|
||||
runtime.set_root(preprocessor.get_root());
|
||||
runtime.run();
|
||||
return;
|
||||
}
|
||||
|
||||
void codegen_start()
|
||||
{
|
||||
if(!resource.input_file(inputfile))
|
||||
{
|
||||
die("resource",inputfile);
|
||||
return;
|
||||
}
|
||||
lexer.scanner(resource.get_file());
|
||||
if(lexer.get_error())
|
||||
{
|
||||
die("lexer",inputfile);
|
||||
return;
|
||||
}
|
||||
parse.set_toklist(lexer.get_token_list());
|
||||
parse.main_process();
|
||||
if(parse.get_error())
|
||||
{
|
||||
die("parse",inputfile);
|
||||
return;
|
||||
}
|
||||
preprocessor.preprocessing(parse.get_root());
|
||||
if(preprocessor.get_error())
|
||||
{
|
||||
die("import",inputfile);
|
||||
return;
|
||||
}
|
||||
runtime.set_root(preprocessor.get_root());
|
||||
code_generator.output_exec(inputfile+".naexec",preprocessor.get_root());
|
||||
if(code_generator.get_error())
|
||||
{
|
||||
die("code",inputfile);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void execution_start()
|
||||
{
|
||||
code_generator.load_exec(inputfile,preprocessor.get_root());
|
||||
if(code_generator.get_error())
|
||||
{
|
||||
die("code",inputfile);
|
||||
return;
|
||||
}
|
||||
runtime.set_root(preprocessor.get_root());
|
||||
runtime.run();
|
||||
return;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// use chcp 65001 to use unicode io
|
||||
system("chcp 65001");
|
||||
system("cls");
|
||||
#endif
|
||||
logo();
|
||||
#ifdef _WIN32
|
||||
std::cout<<">> [system] Windows system.\n";
|
||||
#endif
|
||||
#ifdef _linux_
|
||||
std::cout<<">> [system] Linux system.\n";
|
||||
#endif
|
||||
#ifdef TARGET_OS_MAC
|
||||
std::cout<<">> [system] MacOS system.\n";
|
||||
#endif
|
||||
|
||||
std::cout<<">> Nasal interpreter ver 3.0 .\n";
|
||||
std::cout<<">> Code: https://github.com/ValKmjolnir/Nasal-Interpreter\n";
|
||||
std::cout<<">> Info: http://wiki.flightgear.org/Nasal_scripting_language\n";
|
||||
std::cout<<">> Input \"help\" to get help .\n";
|
||||
while(1)
|
||||
{
|
||||
std::cout<<">> ";
|
||||
std::cin>>command;
|
||||
if(command=="help")
|
||||
help();
|
||||
else if(command=="clear")
|
||||
{
|
||||
#ifdef _WIN32
|
||||
system("cls");
|
||||
#endif
|
||||
#ifdef _linux_
|
||||
system("clear");
|
||||
#endif
|
||||
#ifdef TARGET_OS_MAC
|
||||
system("clear");
|
||||
#endif
|
||||
}
|
||||
else if(command=="del")
|
||||
del_func();
|
||||
else if(command=="rs")
|
||||
{
|
||||
if(resource.input_file(inputfile))
|
||||
resource.print_file();
|
||||
}
|
||||
else if(command=="lex")
|
||||
lex_func();
|
||||
else if(command=="ast")
|
||||
ast_print();
|
||||
else if(command=="run")
|
||||
runtime_start();
|
||||
else if(command=="exec")
|
||||
codegen_start();
|
||||
else if(command=="erun")
|
||||
execution_start();
|
||||
else if(command=="logo")
|
||||
logo();
|
||||
else if(command=="exit")
|
||||
break;
|
||||
else
|
||||
{
|
||||
inputfile=command;
|
||||
std::ifstream fin(command);
|
||||
if(fin.fail())
|
||||
{
|
||||
std::cout<<">> [file] cannot open file \""<<command<<"\".\n";
|
||||
inputfile="null";
|
||||
}
|
||||
fin.close();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
167
misc/ast.cpp
167
misc/ast.cpp
|
@ -1,167 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <list>
|
||||
|
||||
class abstract_syntax_tree
|
||||
{
|
||||
private:
|
||||
int ast_node_type;
|
||||
double var_number;
|
||||
std::string var_string;
|
||||
std::string var_name;
|
||||
std::list<abstract_syntax_tree> children;
|
||||
public:
|
||||
abstract_syntax_tree()
|
||||
{
|
||||
ast_node_type=0;
|
||||
var_number=0;
|
||||
var_string="";
|
||||
var_name="";
|
||||
children.clear();
|
||||
return;
|
||||
}
|
||||
abstract_syntax_tree(const abstract_syntax_tree& p)
|
||||
{
|
||||
ast_node_type=p.ast_node_type;
|
||||
var_number=p.var_number;
|
||||
var_string=p.var_string;
|
||||
var_name=p.var_name;
|
||||
children=p.children;
|
||||
return;
|
||||
}
|
||||
abstract_syntax_tree& operator=(const abstract_syntax_tree& p)
|
||||
{
|
||||
ast_node_type=p.ast_node_type;
|
||||
var_number=p.var_number;
|
||||
var_string=p.var_string;
|
||||
var_name=p.var_name;
|
||||
children=p.children;
|
||||
return *this;
|
||||
}
|
||||
void print_tree(const int n)
|
||||
{
|
||||
std::cout<<n<<" ";
|
||||
if(!children.empty())
|
||||
{
|
||||
for(auto i=children.begin();i!=children.end();++i)
|
||||
i->print_tree(n+1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
void set_node_type(const int type)
|
||||
{
|
||||
ast_node_type=type;
|
||||
return;
|
||||
}
|
||||
void set_var_string(std::string& str)
|
||||
{
|
||||
var_string=str;
|
||||
return;
|
||||
}
|
||||
void set_var_number(std::string& str)
|
||||
{
|
||||
if(str=="nil")
|
||||
{
|
||||
var_number=0;
|
||||
return;
|
||||
}
|
||||
if((int)str.length()>2 && (str[1]=='x' || str[1]=='o'))
|
||||
{
|
||||
if(str[1]=='x')
|
||||
{
|
||||
int num=0;
|
||||
int pw=1;
|
||||
for(int i=(int)str.length()-1;i>1;--i)
|
||||
{
|
||||
if('0'<=str[i] && str[i]<='9')
|
||||
num+=(str[i]-'0')*pw;
|
||||
else if('a'<=str[i] && str[i]<='f')
|
||||
num+=(10+str[i]-'a')*pw;
|
||||
else if('A'<=str[i] && str[i]<='F')
|
||||
num+=(10+str[i]-'A')*pw;
|
||||
pw<<=4;
|
||||
}
|
||||
var_number=(double)num;
|
||||
}
|
||||
else
|
||||
{
|
||||
int num=0;
|
||||
int pw=1;
|
||||
for(int i=(int)str.length()-1;i>1;--i)
|
||||
{
|
||||
num+=(str[i]-'0')*pw;
|
||||
pw<<=3;
|
||||
}
|
||||
var_number=(double)num;
|
||||
}
|
||||
return;
|
||||
}
|
||||
int dot_place=-1;
|
||||
for(int i=0;i<(int)str.length();++i)
|
||||
if(str[i]=='.')
|
||||
{
|
||||
dot_place=i;
|
||||
break;
|
||||
}
|
||||
if(dot_place==-1)
|
||||
{
|
||||
var_number=0;
|
||||
double pw=1;
|
||||
for(int i=(int)str.length()-1;i>=0;--i)
|
||||
{
|
||||
var_number+=(str[i]-'0')*pw;
|
||||
pw*=10;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var_number=0;
|
||||
double pw=0.1;
|
||||
for(int i=dot_place+1;i<(int)str.length();++i)
|
||||
{
|
||||
var_number+=(str[i]-'0')*pw;
|
||||
pw/=10;
|
||||
}
|
||||
pw=1;
|
||||
for(int i=dot_place-1;i>=0;--i)
|
||||
{
|
||||
var_number+=(str[i]-'0')*pw;
|
||||
pw*=10;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
void set_var_name(std::string& str)
|
||||
{
|
||||
var_name=str;
|
||||
return;
|
||||
}
|
||||
void add_child(abstract_syntax_tree& p)
|
||||
{
|
||||
children.push_back(p);
|
||||
return;
|
||||
}
|
||||
double return_var_number()
|
||||
{
|
||||
return var_number;
|
||||
}
|
||||
std::string return_var_string()
|
||||
{
|
||||
return var_string;
|
||||
}
|
||||
std::string return_var_name()
|
||||
{
|
||||
return var_name;
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
abstract_syntax_tree a,b;
|
||||
a.add_child(a);
|
||||
a.add_child(a);
|
||||
a.add_child(a);
|
||||
b=a;
|
||||
b.print_tree(1);
|
||||
return 0;
|
||||
}
|
|
@ -1,183 +0,0 @@
|
|||
#ifndef __LEXER_H__
|
||||
#define __LEXER_H__
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
#include "nasal.h"
|
||||
#include "process_stack.h"
|
||||
|
||||
using namespace nasal;
|
||||
|
||||
std::string text;
|
||||
process_stack _test;
|
||||
process_stack_unit _unit;
|
||||
|
||||
void PrintProcess(std::string content)
|
||||
{
|
||||
std::string Sentence="";
|
||||
int len=(int)content.length();
|
||||
for(int i=0;i<len;++i)
|
||||
{
|
||||
if(content[i]==',')
|
||||
Sentence="";
|
||||
else if(content[i]=='\"')//string mode
|
||||
{
|
||||
Sentence="";
|
||||
for(int j=i+1;j<len;++j)
|
||||
{
|
||||
if(content[j]=='\\' && j+1<len)
|
||||
{
|
||||
Sentence+=content[j];
|
||||
Sentence+=content[j+1];
|
||||
++j;
|
||||
}
|
||||
else if(content[j]=='\"')
|
||||
{
|
||||
i=j;
|
||||
break;
|
||||
}
|
||||
else
|
||||
Sentence+=content[j];
|
||||
}
|
||||
PrintString(Sentence);
|
||||
}
|
||||
else if(content[i]!=' ' && content[i]!='\"' && content[i]!=',')//check var
|
||||
{
|
||||
Sentence="";
|
||||
for(int j=i;j<len;++j)
|
||||
{
|
||||
if(content[j]!=' ' && content[j]!='\"' && content[j]!=',')
|
||||
Sentence+=content[j];
|
||||
if(content[j]==',' || content[j]==' ' || j==len-1)
|
||||
{
|
||||
i=j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(_test.check_stack(Sentence))
|
||||
{
|
||||
_test.stack_content_print(Sentence);
|
||||
}
|
||||
else
|
||||
std::cout<<std::endl<<"[Error] "<<Sentence<<" is not declared in this scope."<<std::endl;
|
||||
}
|
||||
}
|
||||
std::cout<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
void FileProcess(const char *FileName)
|
||||
{
|
||||
std::ifstream fin(FileName);
|
||||
|
||||
fin.close();
|
||||
return;
|
||||
}
|
||||
|
||||
void CommandProcess()
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
std::cout<<">> ";
|
||||
std::getline(std::cin,text);
|
||||
int len=(int)text.length();
|
||||
|
||||
int sharpDetected=0;
|
||||
for(int i=len-1;i>=0;--i)
|
||||
{
|
||||
if(text[i]=='#')
|
||||
{
|
||||
//ignore sharp
|
||||
len=i;
|
||||
sharpDetected=i;
|
||||
}
|
||||
if(text[i]==';')
|
||||
{
|
||||
len=i+1;
|
||||
//find the real end of the sentence
|
||||
if(sharpDetected)
|
||||
{
|
||||
for(int j=sharpDetected-1;j>=len;--j)
|
||||
if(text[j]!=' ')
|
||||
{
|
||||
len=j+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int j=(int)text.length()-1;j>=len;--j)
|
||||
if(text[j]!=' ')
|
||||
{
|
||||
len=j+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(text[len-1]==';')
|
||||
{
|
||||
for(int i=0;i<len;++i)
|
||||
{
|
||||
if(text[i]=='p' && i+1<len && text[i+1]=='r' && i+2<len && text[i+2]=='i' && i+3<len && text[i+3]=='n' && i+4<len && text[i+4]=='t')
|
||||
{
|
||||
//In this part every error leads to an error information and breaks the loop!
|
||||
|
||||
//check the first char after print is '(' or not
|
||||
int string_beg=len-1;
|
||||
for(int j=i+5;j<len;++j)
|
||||
if(text[j]!=' ')
|
||||
{
|
||||
string_beg=j;
|
||||
break;
|
||||
}
|
||||
|
||||
if(text[string_beg]!='(')
|
||||
{
|
||||
std::cout<<std::endl<<"[Error] Missing \'(\' ."<<std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
//check the ')' and the place
|
||||
int string_end=len-1;
|
||||
for(int j=len-2;j>=0;--j)
|
||||
if(text[j]!=' ')
|
||||
{
|
||||
string_end=j;
|
||||
break;
|
||||
}
|
||||
if(text[string_end]!=')')
|
||||
{
|
||||
std::cout<<std::endl<<"[Error] Missing \')\' ."<<std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
std::string content="";
|
||||
for(int j=string_beg+1;j<string_end;++j)
|
||||
content+=text[j];
|
||||
|
||||
std::cout<<std::endl<<"Target string: "<<content<<std::endl;
|
||||
PrintProcess(content);
|
||||
break;
|
||||
}
|
||||
else if(text[i]=='v' && i+1<len && text[i+1]=='a' && i+2<len && text[i+2]=='r')
|
||||
{
|
||||
;
|
||||
}
|
||||
else if(i==len-1)
|
||||
std::cout<<std::endl<<"[Error] Incorrect command."<<std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout<<std::endl<<"[Error] Expected \';\' after this line."<<std::endl;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,291 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
|
||||
#define IDENTIFIER -1 //自定义标识符
|
||||
#define OPERATOR -2 //界符 or 运算符
|
||||
#define NUMBER -3 //数字
|
||||
#define RESERVEWORD -4 //关键字
|
||||
#define STRING -5 //字符串类型
|
||||
#define FAIL -6 //失败
|
||||
#define SCANEND -7 //扫描完成
|
||||
#define ERRORFOUND -8 //异常错误
|
||||
|
||||
// \n 换行
|
||||
// \t tab
|
||||
// \r 回车
|
||||
// \\ 反斜线
|
||||
// \' 单引号
|
||||
// \" 双引号
|
||||
std::string ReserveWord[26]=
|
||||
{
|
||||
"for","foreach","forindex","while",
|
||||
"var","func","break","continue","return",
|
||||
"if","else","elsif","nil","and","or",
|
||||
"print","cmp","append","setsize","subvec","pop",
|
||||
"sort","contains","delete","keys","typeof"
|
||||
};
|
||||
|
||||
std::string OperatorOrDelimiter[40]=
|
||||
{
|
||||
"+","-","*","/","=","+=","-=","*=","/=",
|
||||
"\n","\t","\r","\\","\'","\"",".",
|
||||
"<","<=",">",">=","==","!=","~=","!","~",
|
||||
",",";","(",")","[","]","{","}","#","?",":",
|
||||
"&","|","%","^"
|
||||
};
|
||||
|
||||
std::string IdentifierTable[1000]={""};
|
||||
char ResourcePrograme[16777216];
|
||||
|
||||
int isReserveWord(std::string &p)
|
||||
{
|
||||
for(int i=0;i<26;++i)
|
||||
if(ReserveWord[i]==p)
|
||||
return i+1;
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
int isOperatorOrDelimiter(std::string &p)
|
||||
{
|
||||
for(int i=0;i<40;++i)
|
||||
if(OperatorOrDelimiter[i]==p)
|
||||
return i+1;
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
bool isLetter(char t)
|
||||
{
|
||||
return (('a'<=t) && (t<='z') || ('A'<=t) && (t<='Z'));
|
||||
}
|
||||
|
||||
bool isNumber(char t)
|
||||
{
|
||||
return (('0'<=t) && (t<='9'));
|
||||
}
|
||||
|
||||
void InputFile(std::string &FileName)
|
||||
{
|
||||
std::ifstream fin(FileName);
|
||||
if(fin.fail())
|
||||
{
|
||||
std::cout<<"[Error] Failed to load file: "<<FileName<<std::endl;
|
||||
ResourcePrograme[0]='@';
|
||||
fin.close();
|
||||
return;
|
||||
}
|
||||
int i=0;
|
||||
bool FindNote=false;
|
||||
while(!fin.eof())
|
||||
{
|
||||
ResourcePrograme[i]=fin.get();
|
||||
if(ResourcePrograme[i]=='\n')
|
||||
FindNote=false;
|
||||
if(ResourcePrograme[i]!='#' && !FindNote)
|
||||
++i;
|
||||
else if(ResourcePrograme[i]=='#')
|
||||
{
|
||||
FindNote=true;
|
||||
}
|
||||
if(fin.eof())
|
||||
break;
|
||||
}
|
||||
ResourcePrograme[i]='@';
|
||||
++i;
|
||||
for(int j=0;j<i;++j)
|
||||
std::cout<<ResourcePrograme[j];
|
||||
std::cout<<std::endl;
|
||||
fin.close();
|
||||
return;
|
||||
}
|
||||
|
||||
void Scanner(int &Syn,const char Source[],std::string &token,int &ptr)
|
||||
{
|
||||
char temp;
|
||||
temp=Source[ptr];
|
||||
while(temp==' ' || temp=='\n' || temp=='\t' || temp=='\r' || temp<0 || temp>127)
|
||||
{
|
||||
++ptr;
|
||||
temp=Source[ptr];
|
||||
}
|
||||
|
||||
token="";
|
||||
if(isLetter(temp) || temp=='_')
|
||||
{
|
||||
token+=temp;
|
||||
++ptr;
|
||||
temp=Source[ptr];
|
||||
while(isLetter(temp) || isNumber(temp) || temp=='_')
|
||||
{
|
||||
token+=temp;
|
||||
++ptr;
|
||||
temp=Source[ptr];
|
||||
}
|
||||
Syn=isReserveWord(token);
|
||||
if(Syn==FAIL)
|
||||
Syn=IDENTIFIER;
|
||||
else
|
||||
Syn=RESERVEWORD;
|
||||
}
|
||||
else if(isNumber(temp))
|
||||
{
|
||||
int PointCnt=0;
|
||||
while(isNumber(temp))
|
||||
{
|
||||
token+=temp;
|
||||
++ptr;
|
||||
temp=Source[ptr];
|
||||
if(temp=='.' && !PointCnt)
|
||||
{
|
||||
++PointCnt;
|
||||
token+=temp;
|
||||
++ptr;
|
||||
temp=Source[ptr];
|
||||
}
|
||||
}
|
||||
Syn=NUMBER;
|
||||
}
|
||||
else if(temp=='(' || temp==')' || temp=='[' || temp==']' || temp=='{' ||
|
||||
temp=='}' || temp==',' || temp==';' || temp=='|' || temp==':' ||
|
||||
temp=='?' || temp=='.' || temp=='`' || temp=='\'' || temp=='&'||
|
||||
temp=='%' || temp=='$' || temp=='^')
|
||||
{
|
||||
token+=temp;
|
||||
++ptr;
|
||||
Syn=OPERATOR;
|
||||
}
|
||||
else if(temp=='=' || temp=='+' || temp=='-' || temp=='*' || temp=='!' || temp=='/' || temp=='<' || temp=='>' || temp=='~')
|
||||
{
|
||||
Syn=OPERATOR;
|
||||
token+=temp;
|
||||
++ptr;
|
||||
temp=Source[ptr];
|
||||
if(temp=='=')
|
||||
{
|
||||
token+=temp;
|
||||
++ptr;
|
||||
}
|
||||
}
|
||||
else if(temp=='\\')
|
||||
{
|
||||
Syn=OPERATOR;
|
||||
token+=temp;
|
||||
++ptr;
|
||||
temp=Source[ptr];
|
||||
if(temp=='=' || temp=='n' || temp=='t' || temp=='r' || temp=='\\' || temp=='\'' || temp=='\"')
|
||||
{
|
||||
token+=temp;
|
||||
++ptr;
|
||||
}
|
||||
}
|
||||
else if(temp=='\"')
|
||||
{
|
||||
Syn=STRING;
|
||||
token+=temp;
|
||||
++ptr;
|
||||
temp=Source[ptr];
|
||||
while(temp!='\"')
|
||||
{
|
||||
if(temp=='\\')
|
||||
{
|
||||
token+=temp;
|
||||
|
||||
++ptr;
|
||||
temp=Source[ptr];
|
||||
token+=temp;
|
||||
|
||||
++ptr;
|
||||
temp=Source[ptr];
|
||||
}
|
||||
else
|
||||
{
|
||||
token+=temp;
|
||||
++ptr;
|
||||
temp=Source[ptr];
|
||||
}
|
||||
if(temp=='@' || temp=='\n')
|
||||
break;
|
||||
}
|
||||
//add the last char \"
|
||||
if(temp=='\"')
|
||||
{
|
||||
token+=temp;
|
||||
++ptr;
|
||||
}
|
||||
else
|
||||
token+=" __missing_end_of_string";
|
||||
}
|
||||
else if(temp=='@')
|
||||
{
|
||||
Syn=SCANEND;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
Syn=FAIL;
|
||||
std::cout<<"[Error] Unexpected error occurred: "<<temp<<std::endl;
|
||||
system("pause");
|
||||
++ptr;
|
||||
return;
|
||||
}
|
||||
if(token=="")
|
||||
{
|
||||
Syn=ERRORFOUND;
|
||||
std::cout<<"[Error] Cannot identify "<<std::endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void help()
|
||||
{
|
||||
std::cout<<">> exit: exit the programe."<<std::endl;
|
||||
std::cout<<">> clear: clean the screen."<<std::endl;
|
||||
std::cout<<">> help: find help."<<std::endl;
|
||||
std::cout<<">> input the file name to scan."<<std::endl;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
help();
|
||||
while(1)
|
||||
{
|
||||
int Syn=0;//token type
|
||||
int Ptr=0;//pointer to one char in ResourcePrograme
|
||||
std::string token;
|
||||
std::string FileNameOrCommand;
|
||||
std::cout<<">> ";
|
||||
std::cin>>FileNameOrCommand;
|
||||
|
||||
if(FileNameOrCommand=="exit")
|
||||
break;
|
||||
else if(FileNameOrCommand=="clear")
|
||||
{
|
||||
system("cls");
|
||||
continue;
|
||||
}
|
||||
else if(FileNameOrCommand=="help")
|
||||
{
|
||||
help();
|
||||
continue;
|
||||
}
|
||||
//std::ofstream fout("Data.txt");
|
||||
InputFile(FileNameOrCommand);
|
||||
while(Syn!=SCANEND && Syn!=ERRORFOUND)
|
||||
{
|
||||
Scanner(Syn,ResourcePrograme,token,Ptr);
|
||||
if(Syn==OPERATOR)
|
||||
std::cout<<"( Operator | "<<token<<" )"<<std::endl;
|
||||
else if(Syn==IDENTIFIER)
|
||||
std::cout<<"( Identifier | "<<token<<" )"<<std::endl;
|
||||
else if(Syn==NUMBER)
|
||||
std::cout<<"( Number | "<<token<<" )"<<std::endl;
|
||||
else if(Syn==RESERVEWORD)
|
||||
std::cout<<"( ReserveWord | "<<token<<" )"<<std::endl;
|
||||
else if(Syn==STRING)
|
||||
std::cout<<"( String | "<<token<<" )"<<std::endl;
|
||||
}
|
||||
std::cout<<">> Complete scanning \""<<FileNameOrCommand<<"\"."<<std::endl;
|
||||
//fout.close();
|
||||
}
|
||||
return 0;
|
||||
}
|
1473
misc/nasal_parser.h
1473
misc/nasal_parser.h
File diff suppressed because it is too large
Load Diff
|
@ -1,159 +0,0 @@
|
|||
#ifndef __PROCESS_STACK_H__
|
||||
#define __PROCESS_STACK_H__
|
||||
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include "nasal.h"
|
||||
namespace nasal
|
||||
{
|
||||
|
||||
|
||||
struct process_stack_unit
|
||||
{
|
||||
int line; //place the unit first appear
|
||||
std::string name; //content of the unit or name of the var/class/function
|
||||
std::string format_type; //var class function string info
|
||||
var unitdata;
|
||||
bool global;
|
||||
process_stack_unit *next;
|
||||
process_stack_unit *last;
|
||||
};
|
||||
|
||||
class process_stack
|
||||
{
|
||||
private:
|
||||
process_stack_unit *head;
|
||||
process_stack_unit *ptr;
|
||||
public:
|
||||
process_stack()
|
||||
{
|
||||
head=new process_stack_unit;
|
||||
head->line=0;
|
||||
head->name="InterpreterInfo";
|
||||
head->format_type="Info";
|
||||
head->global=false;
|
||||
head->unitdata.Type="string";
|
||||
head->unitdata.data=new std::string;
|
||||
*((std::string *)head->unitdata.data)="# Nasal language for FlightGear.";
|
||||
|
||||
head->last=NULL;
|
||||
head->next=NULL;
|
||||
ptr=NULL;
|
||||
}
|
||||
~process_stack()
|
||||
{
|
||||
process_stack_unit *temp=head;
|
||||
while(temp->next)
|
||||
{
|
||||
temp=temp->next;
|
||||
delete head;
|
||||
head=temp;
|
||||
}
|
||||
delete head;
|
||||
}
|
||||
void stack_append(process_stack_unit &p)
|
||||
{
|
||||
process_stack_unit *temp=head;
|
||||
process_stack_unit *last_node;
|
||||
while(temp->next)
|
||||
{
|
||||
temp=temp->next;
|
||||
}
|
||||
temp->next=new process_stack_unit;
|
||||
|
||||
last_node=temp;
|
||||
temp=temp->next;
|
||||
|
||||
temp->last=last_node;
|
||||
last_node->next=temp;
|
||||
temp->next=NULL;
|
||||
|
||||
temp->name=p.name;
|
||||
temp->line=p.line;
|
||||
temp->format_type=p.format_type;
|
||||
temp->global=p.global;
|
||||
temp->unitdata=p.unitdata;
|
||||
|
||||
return;
|
||||
}
|
||||
void stack_print(bool reverse_mode_used)
|
||||
{
|
||||
process_stack_unit *temp=head;
|
||||
std::cout<<"In stack: "<<std::endl;
|
||||
if(reverse_mode_used)
|
||||
{
|
||||
while(temp->next)
|
||||
temp=temp->next;
|
||||
while(temp->last)
|
||||
{
|
||||
std::cout<<"line "<<temp->line<<": |"<<temp->format_type<<"|"<<temp->name<<"|\n\t|";
|
||||
temp->unitdata.Print();
|
||||
std::cout<<std::endl;
|
||||
temp=temp->last;
|
||||
}
|
||||
std::cout<<"line "<<temp->line<<": |"<<temp->format_type<<"|"<<temp->name<<"|\n\t|";
|
||||
temp->unitdata.Print();
|
||||
std::cout<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout<<"line "<<temp->line<<": |"<<temp->format_type<<"|"<<temp->name<<"|\n\t|";
|
||||
temp->unitdata.Print();
|
||||
std::cout<<std::endl;
|
||||
while(temp->next)
|
||||
{
|
||||
temp=temp->next;
|
||||
std::cout<<"line "<<temp->line<<": |"<<temp->format_type<<"|"<<temp->name<<"|\n\t|";
|
||||
temp->unitdata.Print();
|
||||
std::cout<<std::endl;
|
||||
}
|
||||
}
|
||||
std::cout<<"End."<<std::endl;
|
||||
return;
|
||||
}
|
||||
void pop()
|
||||
{
|
||||
process_stack_unit *temp=head;
|
||||
process_stack_unit *last_node;
|
||||
while(temp->next)
|
||||
{
|
||||
last_node=temp;
|
||||
temp=temp->next;
|
||||
}
|
||||
last_node->next=NULL;
|
||||
delete temp;
|
||||
return;
|
||||
}
|
||||
bool check_stack(std::string &ElementName)
|
||||
{
|
||||
process_stack_unit *temp=head;
|
||||
while(temp->next)
|
||||
{
|
||||
temp=temp->next;
|
||||
if(temp->name==ElementName)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void stack_content_print(std::string &ElementName)
|
||||
{
|
||||
process_stack_unit *temp=head;
|
||||
while(temp->next)
|
||||
{
|
||||
temp=temp->next;
|
||||
if(temp->name==ElementName)
|
||||
{
|
||||
temp->unitdata.Print();
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,60 +0,0 @@
|
|||
#ifndef __STR2NUM_H__
|
||||
#define __STR2NUM_H__
|
||||
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
|
||||
namespace nasal
|
||||
{
|
||||
|
||||
void Str2Num(std::string &str)
|
||||
{
|
||||
for(int i=0;i<(int)str.length();++i)
|
||||
if(!(('0'<=str[i]) && (str[i]<='9') || (str[i]=='.')))
|
||||
{
|
||||
std::cout<<"[Error] Non-numeric string."<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
bool isFloat=false;
|
||||
int DotPlace=0;
|
||||
for(int i=0;i<(int)str.length();++i)
|
||||
if(str[i]=='.')
|
||||
{
|
||||
isFloat=true;
|
||||
DotPlace=i;
|
||||
break;
|
||||
}
|
||||
if(!isFloat)
|
||||
{
|
||||
long long int num=0;
|
||||
long long int acc=1;
|
||||
for(int i=(int)str.length()-1;i>=0;--i)
|
||||
{
|
||||
num+=acc*((long long int)(str[i]-'0'));
|
||||
acc*=10;
|
||||
}
|
||||
std::cout<<num<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
double num=0;
|
||||
double acc=1;
|
||||
double aff=0.1;
|
||||
for(int i=DotPlace+1;i<(int)str.length();++i)
|
||||
{
|
||||
num+=aff*((double)(str[i]-'0'));
|
||||
aff*=0.1;
|
||||
}
|
||||
for(int i=DotPlace-1;i>=0;--i)
|
||||
{
|
||||
num+=acc*((double)(str[i]-'0'));
|
||||
acc*=10;
|
||||
}
|
||||
std::cout<<num<<std::endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
|
@ -1,132 +1,132 @@
|
|||
(*
|
||||
<> must choose
|
||||
[] can choose
|
||||
{} can repeat 0 to infinite time(s)
|
||||
| or
|
||||
::= is defined as
|
||||
*)
|
||||
|
||||
nil ::= nil;
|
||||
id ::= identifier;
|
||||
number::= number;
|
||||
string::= string;
|
||||
vector::=
|
||||
'[' {calculation ','} ']'
|
||||
;
|
||||
hash ::=
|
||||
'{' {hashmember ','} '}'
|
||||
;
|
||||
hashmember::=
|
||||
id|string ':' calculation
|
||||
;
|
||||
function::=
|
||||
func argument_list expressions
|
||||
;
|
||||
argument_list::=
|
||||
'(' [{id ','} ([id '...']|{id '=' scalar ','})] ')'
|
||||
;
|
||||
expr::=
|
||||
definition
|
||||
|multi_assignment
|
||||
|calculation
|
||||
|loop
|
||||
|conditional
|
||||
|return_expr
|
||||
|continue_expr
|
||||
|break_expr
|
||||
;
|
||||
expressions::=
|
||||
'{' {expr} '}'
|
||||
;
|
||||
calculation::=
|
||||
calculation '?' calculation ':' calculation
|
||||
|or_expr
|
||||
|calculation ('=' | '+=' | '-=' | '*=' | '/=' | '~=') calculation
|
||||
;
|
||||
or_expr::=
|
||||
and_expr or and_expr
|
||||
;
|
||||
and_expr::=
|
||||
cmp_expr and cmp_expr
|
||||
;
|
||||
cmp_expr::=
|
||||
additive_expr ('==' | '!=' | '>' | '<' | '>=' | '<=') additive_expr
|
||||
;
|
||||
additive_expr::=
|
||||
multive_expr ('+' | '-' | '~') multive_expr
|
||||
;
|
||||
multive_expr::=
|
||||
(unary|scalar) ('*' | '/') (unary|scalar)
|
||||
;
|
||||
unary::=
|
||||
('-'|'!') scalar
|
||||
;
|
||||
scalar::=
|
||||
function {call_scalar}
|
||||
|identifier {call_scalar}
|
||||
|vector {call_scalar}
|
||||
|hash {call_scalar}
|
||||
|number
|
||||
|string
|
||||
|'(' calculation ')' {call_scalar}
|
||||
;
|
||||
call_scalar::=
|
||||
call_hash
|
||||
|call_vector
|
||||
|call_func
|
||||
;
|
||||
call_hash::=
|
||||
'.' id
|
||||
;
|
||||
call_vector::=
|
||||
'[' {(subvec) ','} ']'
|
||||
;
|
||||
call_func::=
|
||||
'(' {calculation ','} ')'
|
||||
|'(' {hashmember ','} ')'
|
||||
;
|
||||
subvec::=
|
||||
[calculation] ':' [calculation]
|
||||
;
|
||||
definition::=
|
||||
var id '=' calculation
|
||||
|var '(' multi_id ')' '=' (calculation | multi_scalar)
|
||||
|'(' var multi_id ')' '=' (calculation | multi_scalar)
|
||||
;
|
||||
multi_id::=
|
||||
<id> {',' id}
|
||||
;
|
||||
multi_scalar::=
|
||||
'(' <calculation> {',' calculation} ')'
|
||||
;
|
||||
multi_assignment::=
|
||||
multi_scalar '=' (multi_scalar|calculation)
|
||||
;
|
||||
loop::=
|
||||
while_loop
|
||||
|for_loop
|
||||
|forei_loop
|
||||
;
|
||||
while_loop::=
|
||||
while '(' calculation ')' expressions
|
||||
;
|
||||
for_loop::=
|
||||
for '(' [definition|calculation] ';' [calculation] ';' [calculation] ')' expressions
|
||||
;
|
||||
forei_loop::=
|
||||
(forindex | foreach) '(' (definition | calculation) ';' calculation ')' expressions
|
||||
;
|
||||
conditional::=
|
||||
if '(' calculation ')' expressions
|
||||
{elsif '(' calculation ')' expressions}
|
||||
[else expressions]
|
||||
;
|
||||
continue_expr::=
|
||||
continue
|
||||
;
|
||||
break_expr::=
|
||||
break
|
||||
;
|
||||
return_expr::=
|
||||
return [calculation]
|
||||
(*
|
||||
<> must choose
|
||||
[] can choose
|
||||
{} can repeat 0 to infinite time(s)
|
||||
| or
|
||||
::= is defined as
|
||||
*)
|
||||
|
||||
nil ::= nil;
|
||||
id ::= identifier;
|
||||
number::= number;
|
||||
string::= string;
|
||||
vector::=
|
||||
'[' {calculation ','} ']'
|
||||
;
|
||||
hash ::=
|
||||
'{' {hashmember ','} '}'
|
||||
;
|
||||
hashmember::=
|
||||
id|string ':' calculation
|
||||
;
|
||||
function::=
|
||||
func argument_list expressions
|
||||
;
|
||||
argument_list::=
|
||||
'(' [{id ','} ([id '...']|{id '=' scalar ','})] ')'
|
||||
;
|
||||
expr::=
|
||||
definition
|
||||
|multi_assignment
|
||||
|calculation
|
||||
|loop
|
||||
|conditional
|
||||
|return_expr
|
||||
|continue_expr
|
||||
|break_expr
|
||||
;
|
||||
expressions::=
|
||||
'{' {expr} '}'
|
||||
;
|
||||
calculation::=
|
||||
calculation '?' calculation ':' calculation
|
||||
|or_expr
|
||||
|calculation ('=' | '+=' | '-=' | '*=' | '/=' | '~=') calculation
|
||||
;
|
||||
or_expr::=
|
||||
and_expr or and_expr
|
||||
;
|
||||
and_expr::=
|
||||
cmp_expr and cmp_expr
|
||||
;
|
||||
cmp_expr::=
|
||||
additive_expr ('==' | '!=' | '>' | '<' | '>=' | '<=') additive_expr
|
||||
;
|
||||
additive_expr::=
|
||||
multive_expr ('+' | '-' | '~') multive_expr
|
||||
;
|
||||
multive_expr::=
|
||||
(unary|scalar) ('*' | '/') (unary|scalar)
|
||||
;
|
||||
unary::=
|
||||
('-'|'!') scalar
|
||||
;
|
||||
scalar::=
|
||||
function {call_scalar}
|
||||
|identifier {call_scalar}
|
||||
|vector {call_scalar}
|
||||
|hash {call_scalar}
|
||||
|number
|
||||
|string
|
||||
|'(' calculation ')' {call_scalar}
|
||||
;
|
||||
call_scalar::=
|
||||
call_hash
|
||||
|call_vector
|
||||
|call_func
|
||||
;
|
||||
call_hash::=
|
||||
'.' id
|
||||
;
|
||||
call_vector::=
|
||||
'[' {(subvec) ','} ']'
|
||||
;
|
||||
call_func::=
|
||||
'(' {calculation ','} ')'
|
||||
|'(' {hashmember ','} ')'
|
||||
;
|
||||
subvec::=
|
||||
[calculation] ':' [calculation]
|
||||
;
|
||||
definition::=
|
||||
var id '=' calculation
|
||||
|var '(' multi_id ')' '=' (calculation | multi_scalar)
|
||||
|'(' var multi_id ')' '=' (calculation | multi_scalar)
|
||||
;
|
||||
multi_id::=
|
||||
<id> {',' id}
|
||||
;
|
||||
multi_scalar::=
|
||||
'(' <calculation> {',' calculation} ')'
|
||||
;
|
||||
multi_assignment::=
|
||||
multi_scalar '=' (multi_scalar|calculation)
|
||||
;
|
||||
loop::=
|
||||
while_loop
|
||||
|for_loop
|
||||
|forei_loop
|
||||
;
|
||||
while_loop::=
|
||||
while '(' calculation ')' expressions
|
||||
;
|
||||
for_loop::=
|
||||
for '(' [definition|calculation] ';' [calculation] ';' [calculation] ')' expressions
|
||||
;
|
||||
forei_loop::=
|
||||
(forindex | foreach) '(' (definition | calculation) ';' calculation ')' expressions
|
||||
;
|
||||
conditional::=
|
||||
if '(' calculation ')' expressions
|
||||
{elsif '(' calculation ')' expressions}
|
||||
[else expressions]
|
||||
;
|
||||
continue_expr::=
|
||||
continue
|
||||
;
|
||||
break_expr::=
|
||||
break
|
||||
;
|
||||
return_expr::=
|
||||
return [calculation]
|
||||
;
|
|
@ -1,34 +1,34 @@
|
|||
#ifndef __NASAL_H__
|
||||
#define __NASAL_H__
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <cmath>
|
||||
/* if thread is used, don't forget to add -std=c++11 or higher standard before executing */
|
||||
// #include <thread>
|
||||
#include <list>
|
||||
#include <stack>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "nasal_enum.h"
|
||||
#include "nasal_misc.h"
|
||||
#include "nasal_resource.h"
|
||||
#include "nasal_lexer.h"
|
||||
#include "nasal_ast.h"
|
||||
#include "nasal_parse.h"
|
||||
#include "nasal_import.h"
|
||||
#include "nasal_codegen.h"
|
||||
#include "nasal_gc.h"
|
||||
#include "nasal_runtime.h"
|
||||
#include "nasal_builtin.h"
|
||||
|
||||
#endif
|
||||
#ifndef __NASAL_H__
|
||||
#define __NASAL_H__
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <cmath>
|
||||
/* if thread is used, don't forget to add -std=c++11 or higher standard before executing */
|
||||
// #include <thread>
|
||||
#include <list>
|
||||
#include <stack>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "nasal_enum.h"
|
||||
#include "nasal_misc.h"
|
||||
#include "nasal_resource.h"
|
||||
#include "nasal_lexer.h"
|
||||
#include "nasal_ast.h"
|
||||
#include "nasal_parse.h"
|
||||
#include "nasal_import.h"
|
||||
#include "nasal_codegen.h"
|
||||
#include "nasal_gc.h"
|
||||
#include "nasal_runtime.h"
|
||||
#include "nasal_builtin.h"
|
||||
|
||||
#endif
|
|
@ -1,129 +1,129 @@
|
|||
#ifndef __NASAL_AST_H__
|
||||
#define __NASAL_AST_H__
|
||||
|
||||
class nasal_ast
|
||||
{
|
||||
private:
|
||||
int line;
|
||||
int type;
|
||||
std::string str;
|
||||
std::vector<nasal_ast> children;
|
||||
public:
|
||||
nasal_ast();
|
||||
nasal_ast(const nasal_ast&);
|
||||
~nasal_ast();
|
||||
nasal_ast& operator=(const nasal_ast&);
|
||||
void clear();
|
||||
void set_line(int);
|
||||
void set_type(int);
|
||||
void set_str(std::string&);
|
||||
void add_child(nasal_ast);
|
||||
int get_line();
|
||||
int get_type();
|
||||
std::string get_str();
|
||||
std::vector<nasal_ast>& get_children();
|
||||
void print_ast(int);
|
||||
};
|
||||
|
||||
nasal_ast::nasal_ast()
|
||||
{
|
||||
this->line=0;
|
||||
this->type=ast_null;
|
||||
this->str="";
|
||||
return;
|
||||
}
|
||||
|
||||
nasal_ast::nasal_ast(const nasal_ast& tmp)
|
||||
{
|
||||
this->line=tmp.line;
|
||||
this->type=tmp.type;
|
||||
this->str=tmp.str;
|
||||
this->children=tmp.children;
|
||||
return;
|
||||
}
|
||||
|
||||
nasal_ast::~nasal_ast()
|
||||
{
|
||||
this->str.clear();
|
||||
this->children.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
nasal_ast& nasal_ast::operator=(const nasal_ast& tmp)
|
||||
{
|
||||
this->line=tmp.line;
|
||||
this->type=tmp.type;
|
||||
this->str=tmp.str;
|
||||
this->children=tmp.children;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void nasal_ast::clear()
|
||||
{
|
||||
this->line=0;
|
||||
this->type=ast_null;
|
||||
this->str="";
|
||||
this->children.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_ast::set_line(int l)
|
||||
{
|
||||
this->line=l;
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_ast::set_type(int t)
|
||||
{
|
||||
this->type=t;
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_ast::set_str(std::string& s)
|
||||
{
|
||||
this->str=s;
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_ast::add_child(nasal_ast ast)
|
||||
{
|
||||
children.push_back(ast);
|
||||
return;
|
||||
}
|
||||
|
||||
int nasal_ast::get_line()
|
||||
{
|
||||
return this->line;
|
||||
}
|
||||
|
||||
int nasal_ast::get_type()
|
||||
{
|
||||
return this->type;
|
||||
}
|
||||
|
||||
std::string nasal_ast::get_str()
|
||||
{
|
||||
return this->str;
|
||||
}
|
||||
|
||||
std::vector<nasal_ast>& nasal_ast::get_children()
|
||||
{
|
||||
return this->children;
|
||||
}
|
||||
|
||||
void nasal_ast::print_ast(int depth)
|
||||
{
|
||||
std::string indentation="";
|
||||
for(int i=0;i<depth;++i) indentation+="| ";
|
||||
indentation+=ast_str(this->type);
|
||||
std::cout<<indentation;
|
||||
if(this->type==ast_number || this->type==ast_string || this->type==ast_identifier || this->type==ast_dynamic_id || this->type==ast_call_hash)
|
||||
std::cout<<":"<<this->str;
|
||||
std::cout<<std::endl;
|
||||
int child_size=this->children.size();
|
||||
for(int i=0;i<child_size;++i)
|
||||
this->children[i].print_ast(depth+1);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef __NASAL_AST_H__
|
||||
#define __NASAL_AST_H__
|
||||
|
||||
class nasal_ast
|
||||
{
|
||||
private:
|
||||
int line;
|
||||
int type;
|
||||
std::string str;
|
||||
std::vector<nasal_ast> children;
|
||||
public:
|
||||
nasal_ast();
|
||||
nasal_ast(const nasal_ast&);
|
||||
~nasal_ast();
|
||||
nasal_ast& operator=(const nasal_ast&);
|
||||
void clear();
|
||||
void set_line(int);
|
||||
void set_type(int);
|
||||
void set_str(std::string&);
|
||||
void add_child(nasal_ast);
|
||||
int get_line();
|
||||
int get_type();
|
||||
std::string get_str();
|
||||
std::vector<nasal_ast>& get_children();
|
||||
void print_ast(int);
|
||||
};
|
||||
|
||||
nasal_ast::nasal_ast()
|
||||
{
|
||||
this->line=0;
|
||||
this->type=ast_null;
|
||||
this->str="";
|
||||
return;
|
||||
}
|
||||
|
||||
nasal_ast::nasal_ast(const nasal_ast& tmp)
|
||||
{
|
||||
this->line=tmp.line;
|
||||
this->type=tmp.type;
|
||||
this->str=tmp.str;
|
||||
this->children=tmp.children;
|
||||
return;
|
||||
}
|
||||
|
||||
nasal_ast::~nasal_ast()
|
||||
{
|
||||
this->str.clear();
|
||||
this->children.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
nasal_ast& nasal_ast::operator=(const nasal_ast& tmp)
|
||||
{
|
||||
this->line=tmp.line;
|
||||
this->type=tmp.type;
|
||||
this->str=tmp.str;
|
||||
this->children=tmp.children;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void nasal_ast::clear()
|
||||
{
|
||||
this->line=0;
|
||||
this->type=ast_null;
|
||||
this->str="";
|
||||
this->children.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_ast::set_line(int l)
|
||||
{
|
||||
this->line=l;
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_ast::set_type(int t)
|
||||
{
|
||||
this->type=t;
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_ast::set_str(std::string& s)
|
||||
{
|
||||
this->str=s;
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_ast::add_child(nasal_ast ast)
|
||||
{
|
||||
children.push_back(ast);
|
||||
return;
|
||||
}
|
||||
|
||||
int nasal_ast::get_line()
|
||||
{
|
||||
return this->line;
|
||||
}
|
||||
|
||||
int nasal_ast::get_type()
|
||||
{
|
||||
return this->type;
|
||||
}
|
||||
|
||||
std::string nasal_ast::get_str()
|
||||
{
|
||||
return this->str;
|
||||
}
|
||||
|
||||
std::vector<nasal_ast>& nasal_ast::get_children()
|
||||
{
|
||||
return this->children;
|
||||
}
|
||||
|
||||
void nasal_ast::print_ast(int depth)
|
||||
{
|
||||
std::string indentation="";
|
||||
for(int i=0;i<depth;++i) indentation+="| ";
|
||||
indentation+=ast_str(this->type);
|
||||
std::cout<<indentation;
|
||||
if(this->type==ast_number || this->type==ast_string || this->type==ast_identifier || this->type==ast_dynamic_id || this->type==ast_call_hash)
|
||||
std::cout<<":"<<this->str;
|
||||
std::cout<<std::endl;
|
||||
int child_size=this->children.size();
|
||||
for(int i=0;i<child_size;++i)
|
||||
this->children[i].print_ast(depth+1);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -1,225 +1,225 @@
|
|||
#ifndef __NASAL_CODEGEN_H__
|
||||
#define __NASAL_CODEGEN_H__
|
||||
|
||||
// unfinished
|
||||
// now it can output ast but it is not byte code yet
|
||||
// please wait...
|
||||
class nasal_codegen
|
||||
{
|
||||
private:
|
||||
std::vector<unsigned char> file_header;
|
||||
std::vector<unsigned char> output_file;
|
||||
std::vector<std::string> string_table;
|
||||
int error;
|
||||
void init();
|
||||
void output_int(unsigned int,std::vector<unsigned char>&);
|
||||
void output_short(unsigned short,std::vector<unsigned char>&);
|
||||
void output_root(nasal_ast&);
|
||||
unsigned int input_int(std::ifstream&);
|
||||
unsigned short input_short(std::ifstream&);
|
||||
void input_root(nasal_ast&,std::ifstream&);
|
||||
public:
|
||||
nasal_codegen();
|
||||
int get_error();
|
||||
void output_exec(std::string,nasal_ast&);
|
||||
void load_exec(std::string,nasal_ast&);
|
||||
};
|
||||
|
||||
nasal_codegen::nasal_codegen()
|
||||
{
|
||||
error=0;
|
||||
string_table.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
int nasal_codegen::get_error()
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
void nasal_codegen::init()
|
||||
{
|
||||
error=0;
|
||||
string_table.clear();
|
||||
file_header.clear();
|
||||
output_file.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_codegen::output_int(unsigned int num,std::vector<unsigned char>& vec)
|
||||
{
|
||||
unsigned int tmp=0xff000000;
|
||||
unsigned int offset=24;
|
||||
for(int i=0;i<4;++i)
|
||||
{
|
||||
vec.push_back((unsigned char)((tmp&num)>>offset));
|
||||
offset-=8;
|
||||
tmp>>=8;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_codegen::output_short(unsigned short num,std::vector<unsigned char>& vec)
|
||||
{
|
||||
vec.push_back((unsigned char)((num&0xff00)>>8));
|
||||
vec.push_back((unsigned char)(num&0x00ff));
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_codegen::output_root(nasal_ast& root)
|
||||
{
|
||||
unsigned char type=(unsigned char)root.get_type();
|
||||
output_file.push_back(type);
|
||||
std::vector<nasal_ast>& ref_vec=root.get_children();
|
||||
unsigned short root_children_size=ref_vec.size();
|
||||
output_short(root_children_size,output_file);
|
||||
if(type==ast_number || type==ast_string || type==ast_identifier || type==ast_dynamic_id || type==ast_call_hash)
|
||||
{
|
||||
std::string tmp=root.get_str();
|
||||
if(std::find(string_table.begin(),string_table.end(),tmp)==string_table.end())
|
||||
{
|
||||
string_table.push_back(tmp);
|
||||
output_short(string_table.size()-1,output_file);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i=0;i<string_table.size();++i)
|
||||
if(string_table[i]==tmp)
|
||||
{
|
||||
output_short(i,output_file);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(unsigned short i=0;i<root_children_size;++i)
|
||||
output_root(ref_vec[i]);
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_codegen::output_exec(std::string filename,nasal_ast& root)
|
||||
{
|
||||
// initializing
|
||||
this->init();
|
||||
|
||||
// put header input file_header
|
||||
unsigned char header[4]={0x40,0x56,0x4b,0x21};
|
||||
for(int i=0;i<4;++i)
|
||||
file_header.push_back(header[i]);
|
||||
|
||||
// main progress,put codes into output_file
|
||||
output_root(root);
|
||||
|
||||
// put string table into file_header
|
||||
output_short(string_table.size(),file_header);
|
||||
for(int i=0;i<string_table.size();++i)
|
||||
{
|
||||
int len=string_table[i].length();
|
||||
for(int j=0;j<len;++j)
|
||||
file_header.push_back((unsigned char)string_table[i][j]);
|
||||
file_header.push_back(0);
|
||||
}
|
||||
|
||||
// output to file
|
||||
std::ofstream fout(filename,std::ios::binary);
|
||||
if(fout.fail())
|
||||
{
|
||||
++error;
|
||||
std::cout<<">> [code] cannot generate file \""<<filename<<"\"."<<std::endl;
|
||||
fout.close();
|
||||
return;
|
||||
}
|
||||
int size=file_header.size();
|
||||
for(int i=0;i<size;++i)
|
||||
fout<<file_header[i];
|
||||
size=output_file.size();
|
||||
for(int i=0;i<size;++i)
|
||||
fout<<output_file[i];
|
||||
fout.close();
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int nasal_codegen::input_int(std::ifstream& fin)
|
||||
{
|
||||
unsigned int number=0;
|
||||
for(int i=0;i<4;++i)
|
||||
{
|
||||
number<<=8;
|
||||
number+=(unsigned char)fin.get();
|
||||
}
|
||||
return number;
|
||||
}
|
||||
|
||||
unsigned short nasal_codegen::input_short(std::ifstream& fin)
|
||||
{
|
||||
unsigned short number=(unsigned char)fin.get();
|
||||
number=(number<<8)+(unsigned char)fin.get();
|
||||
return number;
|
||||
}
|
||||
|
||||
void nasal_codegen::input_root(nasal_ast& root,std::ifstream& fin)
|
||||
{
|
||||
unsigned char type=(unsigned char)fin.get();
|
||||
unsigned short size=input_short(fin);
|
||||
root.set_type(type);
|
||||
if(type==ast_number || type==ast_string || type==ast_identifier || type==ast_dynamic_id || type==ast_call_hash)
|
||||
{
|
||||
std::string tmp=string_table[input_short(fin)];
|
||||
root.set_str(tmp);
|
||||
}
|
||||
for(unsigned short i=0;i<size;++i)
|
||||
{
|
||||
nasal_ast new_ast;
|
||||
root.add_child(new_ast);
|
||||
input_root(root.get_children().back(),fin);
|
||||
if(error)
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_codegen::load_exec(std::string filename,nasal_ast& root)
|
||||
{
|
||||
// initializing
|
||||
string_table.clear();
|
||||
root.clear();
|
||||
|
||||
// start input
|
||||
std::ifstream fin(filename,std::ios::binary);
|
||||
if(fin.fail())
|
||||
{
|
||||
++error;
|
||||
std::cout<<">> [code] cannot open file\""<<filename<<"\"."<<std::endl;
|
||||
fin.close();
|
||||
return;
|
||||
}
|
||||
|
||||
// check header
|
||||
unsigned char header[4]={0x40,0x56,0x4b,0x21};
|
||||
for(int i=0;i<4;++i)
|
||||
if((unsigned char)fin.get()!=header[i])
|
||||
{
|
||||
++error;
|
||||
std::cout<<">> [code] \""<<filename<<"\" is not an executable file."<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// input string table
|
||||
unsigned short string_num=input_short(fin);
|
||||
for(int i=0;i<string_num;++i)
|
||||
{
|
||||
std::string tmp="";
|
||||
while(1)
|
||||
{
|
||||
unsigned char c=(unsigned char)fin.get();
|
||||
if(!c || fin.eof()) break;
|
||||
tmp+=c;
|
||||
}
|
||||
string_table.push_back(tmp);
|
||||
}
|
||||
|
||||
// generate root
|
||||
input_root(root,fin);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef __NASAL_CODEGEN_H__
|
||||
#define __NASAL_CODEGEN_H__
|
||||
|
||||
// unfinished
|
||||
// now it can output ast but it is not byte code yet
|
||||
// please wait...
|
||||
class nasal_codegen
|
||||
{
|
||||
private:
|
||||
std::vector<unsigned char> file_header;
|
||||
std::vector<unsigned char> output_file;
|
||||
std::vector<std::string> string_table;
|
||||
int error;
|
||||
void init();
|
||||
void output_int(unsigned int,std::vector<unsigned char>&);
|
||||
void output_short(unsigned short,std::vector<unsigned char>&);
|
||||
void output_root(nasal_ast&);
|
||||
unsigned int input_int(std::ifstream&);
|
||||
unsigned short input_short(std::ifstream&);
|
||||
void input_root(nasal_ast&,std::ifstream&);
|
||||
public:
|
||||
nasal_codegen();
|
||||
int get_error();
|
||||
void output_exec(std::string,nasal_ast&);
|
||||
void load_exec(std::string,nasal_ast&);
|
||||
};
|
||||
|
||||
nasal_codegen::nasal_codegen()
|
||||
{
|
||||
error=0;
|
||||
string_table.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
int nasal_codegen::get_error()
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
void nasal_codegen::init()
|
||||
{
|
||||
error=0;
|
||||
string_table.clear();
|
||||
file_header.clear();
|
||||
output_file.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_codegen::output_int(unsigned int num,std::vector<unsigned char>& vec)
|
||||
{
|
||||
unsigned int tmp=0xff000000;
|
||||
unsigned int offset=24;
|
||||
for(int i=0;i<4;++i)
|
||||
{
|
||||
vec.push_back((unsigned char)((tmp&num)>>offset));
|
||||
offset-=8;
|
||||
tmp>>=8;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_codegen::output_short(unsigned short num,std::vector<unsigned char>& vec)
|
||||
{
|
||||
vec.push_back((unsigned char)((num&0xff00)>>8));
|
||||
vec.push_back((unsigned char)(num&0x00ff));
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_codegen::output_root(nasal_ast& root)
|
||||
{
|
||||
unsigned char type=(unsigned char)root.get_type();
|
||||
output_file.push_back(type);
|
||||
std::vector<nasal_ast>& ref_vec=root.get_children();
|
||||
unsigned short root_children_size=ref_vec.size();
|
||||
output_short(root_children_size,output_file);
|
||||
if(type==ast_number || type==ast_string || type==ast_identifier || type==ast_dynamic_id || type==ast_call_hash)
|
||||
{
|
||||
std::string tmp=root.get_str();
|
||||
if(std::find(string_table.begin(),string_table.end(),tmp)==string_table.end())
|
||||
{
|
||||
string_table.push_back(tmp);
|
||||
output_short(string_table.size()-1,output_file);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i=0;i<string_table.size();++i)
|
||||
if(string_table[i]==tmp)
|
||||
{
|
||||
output_short(i,output_file);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(unsigned short i=0;i<root_children_size;++i)
|
||||
output_root(ref_vec[i]);
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_codegen::output_exec(std::string filename,nasal_ast& root)
|
||||
{
|
||||
// initializing
|
||||
this->init();
|
||||
|
||||
// put header input file_header
|
||||
unsigned char header[4]={0x40,0x56,0x4b,0x21};
|
||||
for(int i=0;i<4;++i)
|
||||
file_header.push_back(header[i]);
|
||||
|
||||
// main progress,put codes into output_file
|
||||
output_root(root);
|
||||
|
||||
// put string table into file_header
|
||||
output_short(string_table.size(),file_header);
|
||||
for(int i=0;i<string_table.size();++i)
|
||||
{
|
||||
int len=string_table[i].length();
|
||||
for(int j=0;j<len;++j)
|
||||
file_header.push_back((unsigned char)string_table[i][j]);
|
||||
file_header.push_back(0);
|
||||
}
|
||||
|
||||
// output to file
|
||||
std::ofstream fout(filename,std::ios::binary);
|
||||
if(fout.fail())
|
||||
{
|
||||
++error;
|
||||
std::cout<<">> [code] cannot generate file \""<<filename<<"\"."<<std::endl;
|
||||
fout.close();
|
||||
return;
|
||||
}
|
||||
int size=file_header.size();
|
||||
for(int i=0;i<size;++i)
|
||||
fout<<file_header[i];
|
||||
size=output_file.size();
|
||||
for(int i=0;i<size;++i)
|
||||
fout<<output_file[i];
|
||||
fout.close();
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int nasal_codegen::input_int(std::ifstream& fin)
|
||||
{
|
||||
unsigned int number=0;
|
||||
for(int i=0;i<4;++i)
|
||||
{
|
||||
number<<=8;
|
||||
number+=(unsigned char)fin.get();
|
||||
}
|
||||
return number;
|
||||
}
|
||||
|
||||
unsigned short nasal_codegen::input_short(std::ifstream& fin)
|
||||
{
|
||||
unsigned short number=(unsigned char)fin.get();
|
||||
number=(number<<8)+(unsigned char)fin.get();
|
||||
return number;
|
||||
}
|
||||
|
||||
void nasal_codegen::input_root(nasal_ast& root,std::ifstream& fin)
|
||||
{
|
||||
unsigned char type=(unsigned char)fin.get();
|
||||
unsigned short size=input_short(fin);
|
||||
root.set_type(type);
|
||||
if(type==ast_number || type==ast_string || type==ast_identifier || type==ast_dynamic_id || type==ast_call_hash)
|
||||
{
|
||||
std::string tmp=string_table[input_short(fin)];
|
||||
root.set_str(tmp);
|
||||
}
|
||||
for(unsigned short i=0;i<size;++i)
|
||||
{
|
||||
nasal_ast new_ast;
|
||||
root.add_child(new_ast);
|
||||
input_root(root.get_children().back(),fin);
|
||||
if(error)
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_codegen::load_exec(std::string filename,nasal_ast& root)
|
||||
{
|
||||
// initializing
|
||||
string_table.clear();
|
||||
root.clear();
|
||||
|
||||
// start input
|
||||
std::ifstream fin(filename,std::ios::binary);
|
||||
if(fin.fail())
|
||||
{
|
||||
++error;
|
||||
std::cout<<">> [code] cannot open file\""<<filename<<"\"."<<std::endl;
|
||||
fin.close();
|
||||
return;
|
||||
}
|
||||
|
||||
// check header
|
||||
unsigned char header[4]={0x40,0x56,0x4b,0x21};
|
||||
for(int i=0;i<4;++i)
|
||||
if((unsigned char)fin.get()!=header[i])
|
||||
{
|
||||
++error;
|
||||
std::cout<<">> [code] \""<<filename<<"\" is not an executable file."<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// input string table
|
||||
unsigned short string_num=input_short(fin);
|
||||
for(int i=0;i<string_num;++i)
|
||||
{
|
||||
std::string tmp="";
|
||||
while(1)
|
||||
{
|
||||
unsigned char c=(unsigned char)fin.get();
|
||||
if(!c || fin.eof()) break;
|
||||
tmp+=c;
|
||||
}
|
||||
string_table.push_back(tmp);
|
||||
}
|
||||
|
||||
// generate root
|
||||
input_root(root,fin);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,190 +1,190 @@
|
|||
#ifndef __NASAL_ENUM_H__
|
||||
#define __NASAL_ENUM_H__
|
||||
|
||||
/* token_type is used in lexer */
|
||||
enum token_type
|
||||
{
|
||||
tok_null=0,
|
||||
tok_number,tok_string,tok_identifier,
|
||||
tok_for,tok_forindex,tok_foreach,tok_while,
|
||||
tok_var,tok_func,tok_break,tok_continue,
|
||||
tok_return,tok_if,tok_elsif,tok_else,tok_nil,
|
||||
tok_left_curve,tok_right_curve,
|
||||
tok_left_bracket,tok_right_bracket,
|
||||
tok_left_brace,tok_right_brace,
|
||||
tok_semi,tok_and,tok_or,tok_comma,tok_dot,tok_ellipsis,tok_quesmark,
|
||||
tok_colon,tok_add,tok_sub,tok_mult,tok_div,tok_link,tok_not,
|
||||
tok_equal,
|
||||
tok_add_equal,tok_sub_equal,tok_mult_equal,tok_div_equal,tok_link_equal,
|
||||
tok_cmp_equal,tok_cmp_not_equal,tok_less_than,tok_greater_than,tok_less_equal,tok_greater_equal
|
||||
};
|
||||
|
||||
enum ast_node
|
||||
{
|
||||
ast_null=0,ast_root,ast_block,
|
||||
ast_nil,ast_number,ast_string,ast_identifier,ast_function,ast_hash,ast_vector,
|
||||
ast_hashmember,ast_call,ast_call_hash,ast_call_vec,ast_call_func,ast_subvec,
|
||||
ast_args,ast_default_arg,ast_dynamic_id,
|
||||
ast_and,ast_or,
|
||||
ast_equal,ast_add_equal,ast_sub_equal,ast_mult_equal,ast_div_equal,ast_link_equal,
|
||||
ast_cmp_equal,ast_cmp_not_equal,ast_less_than,ast_less_equal,ast_greater_than,ast_greater_equal,
|
||||
ast_add,ast_sub,ast_mult,ast_div,ast_link,
|
||||
ast_unary_sub,ast_unary_not,
|
||||
ast_trinocular,
|
||||
ast_for,ast_forindex,ast_foreach,ast_while,ast_new_iter,
|
||||
ast_conditional,ast_if,ast_elsif,ast_else,
|
||||
ast_multi_id,ast_multi_scalar,
|
||||
ast_definition,ast_multi_assign,
|
||||
ast_continue,ast_break,ast_return
|
||||
};
|
||||
|
||||
std::string ast_str(int type)
|
||||
{
|
||||
std::string str;
|
||||
switch(type)
|
||||
{
|
||||
case ast_null: str="null";break;
|
||||
case ast_root: str="root";break;
|
||||
case ast_block: str="block";break;
|
||||
case ast_nil: str="nil";break;
|
||||
case ast_number: str="number";break;
|
||||
case ast_string: str="string";break;
|
||||
case ast_identifier: str="id";break;
|
||||
case ast_function: str="function";break;
|
||||
case ast_hash: str="hash";break;
|
||||
case ast_vector: str="vector";break;
|
||||
case ast_hashmember: str="hashmember";break;
|
||||
case ast_call: str="call";break;
|
||||
case ast_call_hash: str="call_hash";break;
|
||||
case ast_call_vec: str="call_vector";break;
|
||||
case ast_call_func: str="call_func";break;
|
||||
case ast_subvec: str="subvec";break;
|
||||
case ast_args: str="arguments";break;
|
||||
case ast_default_arg: str="default_arg";break;
|
||||
case ast_dynamic_id: str="dynamic_id";break;
|
||||
case ast_and: str="and";break;
|
||||
case ast_or: str="or";break;
|
||||
case ast_equal: str="=";break;
|
||||
case ast_add_equal: str="+=";break;
|
||||
case ast_sub_equal: str="-=";break;
|
||||
case ast_mult_equal: str="*=";break;
|
||||
case ast_div_equal: str="/=";break;
|
||||
case ast_link_equal: str="~=";break;
|
||||
case ast_cmp_equal: str="==";break;
|
||||
case ast_cmp_not_equal:str="!=";break;
|
||||
case ast_less_than: str="<";break;
|
||||
case ast_less_equal: str="<=";break;
|
||||
case ast_greater_than: str=">";break;
|
||||
case ast_greater_equal:str=">=";break;
|
||||
case ast_add: str="+";break;
|
||||
case ast_sub: str="-";break;
|
||||
case ast_mult: str="*";break;
|
||||
case ast_div: str="/";break;
|
||||
case ast_link: str="~";break;
|
||||
case ast_unary_sub: str="unary-";break;
|
||||
case ast_unary_not: str="unary!";break;
|
||||
case ast_trinocular: str="trinocular";break;
|
||||
case ast_for: str="for";break;
|
||||
case ast_forindex: str="forindex";break;
|
||||
case ast_foreach: str="foreach";break;
|
||||
case ast_while: str="while";break;
|
||||
case ast_new_iter: str="new_iterator";break;
|
||||
case ast_conditional: str="conditional";break;
|
||||
case ast_if: str="if";break;
|
||||
case ast_elsif: str="elsif";break;
|
||||
case ast_else: str="else";break;
|
||||
case ast_multi_id: str="multi_id";break;
|
||||
case ast_multi_scalar: str="multi_scalar";break;
|
||||
case ast_definition: str="definition";break;
|
||||
case ast_multi_assign: str="multi_assignment";break;
|
||||
case ast_continue: str="continue";break;
|
||||
case ast_break: str="break";break;
|
||||
case ast_return: str="return";break;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
enum parse_error
|
||||
{
|
||||
unknown,
|
||||
error_token,
|
||||
error_expr,
|
||||
lack_left_curve,
|
||||
lack_right_curve,
|
||||
lack_left_bracket,
|
||||
lack_right_bracket,
|
||||
lack_left_brace,
|
||||
lack_right_brace,
|
||||
exprs_lack_rbrace,
|
||||
lack_semi,
|
||||
lack_comma,
|
||||
lack_colon,
|
||||
lack_equal,
|
||||
lack_scalar,
|
||||
lack_identifier,
|
||||
lack_calculation,
|
||||
lack_exprs,
|
||||
lack_token,
|
||||
lack_args,
|
||||
default_arg_not_end,
|
||||
dynamic_id_not_end,
|
||||
name_repetition,
|
||||
definition_use_call,
|
||||
multi_id_use_call,
|
||||
multi_assign_lack_val,
|
||||
lack_definition,
|
||||
lack_loop_iter,
|
||||
lack_func_content
|
||||
};
|
||||
|
||||
void error_info(int line,int error_type,std::string error_str="")
|
||||
{
|
||||
std::string detail;
|
||||
std::cout<<">> [parse] error_info: [line "<<line<<"] ";
|
||||
switch(error_type)
|
||||
{
|
||||
case unknown: std::cout<<"unknown error.\n"; break;
|
||||
case error_token: std::cout<<"error token \""+error_str+"\".\n"; break;
|
||||
case error_expr: std::cout<<"error expression \""+error_str+"\".\n"; break;
|
||||
case lack_left_curve: std::cout<<"expected \"(\".\n"; break;
|
||||
case lack_right_curve: std::cout<<"expected \")\".\n"; break;
|
||||
case lack_left_bracket: std::cout<<"expected \"[\".\n"; break;
|
||||
case lack_right_bracket: std::cout<<"expected \"]\".\n"; break;
|
||||
case lack_left_brace: std::cout<<"expected \"{\".\n"; break;
|
||||
case lack_right_brace: std::cout<<"expected \"}\".\n"; break;
|
||||
case exprs_lack_rbrace: std::cout<<"expected \"}\" with this line\'s \"{\".\n";break;
|
||||
case lack_semi: std::cout<<"expected \";\".\n"; break;
|
||||
case lack_comma: std::cout<<"expected \",\".\n"; break;
|
||||
case lack_colon: std::cout<<"expected \":\".\n"; break;
|
||||
case lack_equal: std::cout<<"expected \"=\".\n"; break;
|
||||
case lack_scalar: std::cout<<"expected scalar here.\n"; break;
|
||||
case lack_identifier: std::cout<<"expected identifier here.\n"; break;
|
||||
case lack_calculation: std::cout<<"expected arithmetic-expression here.\n"; break;
|
||||
case lack_exprs: std::cout<<"expected expression block here.\n"; break;
|
||||
case lack_token: std::cout<<"expected \""+error_str+"\" here.\n"; break;
|
||||
case lack_args: std::cout<<"expected arguments here.\n"; break;
|
||||
case default_arg_not_end: std::cout<<"default argument missing for parameter of "+error_str+".\n";break;
|
||||
case dynamic_id_not_end: std::cout<<"dynamic id must be the end of "+error_str+".\n";break;
|
||||
case name_repetition: std::cout<<"this identifier name has existed.\n";break;
|
||||
case definition_use_call: std::cout<<"should not use call_scalar in definition progress.\n";break;
|
||||
case multi_id_use_call: std::cout<<"should not use call_scalar in multi_id progress.\n";break;
|
||||
case multi_assign_lack_val:std::cout<<"multi-assignment lacks value list.\n";break;
|
||||
case lack_definition: std::cout<<"expected a definition expression here.\n";break;
|
||||
case lack_loop_iter: std::cout<<"expected an iterator to loop through.\n";break;
|
||||
case lack_func_content: std::cout<<"expected arguments or expression block here.\n";break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
enum runtime_scalar_type
|
||||
{
|
||||
vm_nil=0,
|
||||
vm_number,
|
||||
vm_string,
|
||||
vm_closure,
|
||||
vm_function,
|
||||
vm_vector,
|
||||
vm_hash
|
||||
};
|
||||
|
||||
#ifndef __NASAL_ENUM_H__
|
||||
#define __NASAL_ENUM_H__
|
||||
|
||||
/* token_type is used in lexer */
|
||||
enum token_type
|
||||
{
|
||||
tok_null=0,
|
||||
tok_number,tok_string,tok_identifier,
|
||||
tok_for,tok_forindex,tok_foreach,tok_while,
|
||||
tok_var,tok_func,tok_break,tok_continue,
|
||||
tok_return,tok_if,tok_elsif,tok_else,tok_nil,
|
||||
tok_left_curve,tok_right_curve,
|
||||
tok_left_bracket,tok_right_bracket,
|
||||
tok_left_brace,tok_right_brace,
|
||||
tok_semi,tok_and,tok_or,tok_comma,tok_dot,tok_ellipsis,tok_quesmark,
|
||||
tok_colon,tok_add,tok_sub,tok_mult,tok_div,tok_link,tok_not,
|
||||
tok_equal,
|
||||
tok_add_equal,tok_sub_equal,tok_mult_equal,tok_div_equal,tok_link_equal,
|
||||
tok_cmp_equal,tok_cmp_not_equal,tok_less_than,tok_greater_than,tok_less_equal,tok_greater_equal
|
||||
};
|
||||
|
||||
enum ast_node
|
||||
{
|
||||
ast_null=0,ast_root,ast_block,
|
||||
ast_nil,ast_number,ast_string,ast_identifier,ast_function,ast_hash,ast_vector,
|
||||
ast_hashmember,ast_call,ast_call_hash,ast_call_vec,ast_call_func,ast_subvec,
|
||||
ast_args,ast_default_arg,ast_dynamic_id,
|
||||
ast_and,ast_or,
|
||||
ast_equal,ast_add_equal,ast_sub_equal,ast_mult_equal,ast_div_equal,ast_link_equal,
|
||||
ast_cmp_equal,ast_cmp_not_equal,ast_less_than,ast_less_equal,ast_greater_than,ast_greater_equal,
|
||||
ast_add,ast_sub,ast_mult,ast_div,ast_link,
|
||||
ast_unary_sub,ast_unary_not,
|
||||
ast_trinocular,
|
||||
ast_for,ast_forindex,ast_foreach,ast_while,ast_new_iter,
|
||||
ast_conditional,ast_if,ast_elsif,ast_else,
|
||||
ast_multi_id,ast_multi_scalar,
|
||||
ast_definition,ast_multi_assign,
|
||||
ast_continue,ast_break,ast_return
|
||||
};
|
||||
|
||||
std::string ast_str(int type)
|
||||
{
|
||||
std::string str;
|
||||
switch(type)
|
||||
{
|
||||
case ast_null: str="null";break;
|
||||
case ast_root: str="root";break;
|
||||
case ast_block: str="block";break;
|
||||
case ast_nil: str="nil";break;
|
||||
case ast_number: str="number";break;
|
||||
case ast_string: str="string";break;
|
||||
case ast_identifier: str="id";break;
|
||||
case ast_function: str="function";break;
|
||||
case ast_hash: str="hash";break;
|
||||
case ast_vector: str="vector";break;
|
||||
case ast_hashmember: str="hashmember";break;
|
||||
case ast_call: str="call";break;
|
||||
case ast_call_hash: str="call_hash";break;
|
||||
case ast_call_vec: str="call_vector";break;
|
||||
case ast_call_func: str="call_func";break;
|
||||
case ast_subvec: str="subvec";break;
|
||||
case ast_args: str="arguments";break;
|
||||
case ast_default_arg: str="default_arg";break;
|
||||
case ast_dynamic_id: str="dynamic_id";break;
|
||||
case ast_and: str="and";break;
|
||||
case ast_or: str="or";break;
|
||||
case ast_equal: str="=";break;
|
||||
case ast_add_equal: str="+=";break;
|
||||
case ast_sub_equal: str="-=";break;
|
||||
case ast_mult_equal: str="*=";break;
|
||||
case ast_div_equal: str="/=";break;
|
||||
case ast_link_equal: str="~=";break;
|
||||
case ast_cmp_equal: str="==";break;
|
||||
case ast_cmp_not_equal:str="!=";break;
|
||||
case ast_less_than: str="<";break;
|
||||
case ast_less_equal: str="<=";break;
|
||||
case ast_greater_than: str=">";break;
|
||||
case ast_greater_equal:str=">=";break;
|
||||
case ast_add: str="+";break;
|
||||
case ast_sub: str="-";break;
|
||||
case ast_mult: str="*";break;
|
||||
case ast_div: str="/";break;
|
||||
case ast_link: str="~";break;
|
||||
case ast_unary_sub: str="unary-";break;
|
||||
case ast_unary_not: str="unary!";break;
|
||||
case ast_trinocular: str="trinocular";break;
|
||||
case ast_for: str="for";break;
|
||||
case ast_forindex: str="forindex";break;
|
||||
case ast_foreach: str="foreach";break;
|
||||
case ast_while: str="while";break;
|
||||
case ast_new_iter: str="new_iterator";break;
|
||||
case ast_conditional: str="conditional";break;
|
||||
case ast_if: str="if";break;
|
||||
case ast_elsif: str="elsif";break;
|
||||
case ast_else: str="else";break;
|
||||
case ast_multi_id: str="multi_id";break;
|
||||
case ast_multi_scalar: str="multi_scalar";break;
|
||||
case ast_definition: str="definition";break;
|
||||
case ast_multi_assign: str="multi_assignment";break;
|
||||
case ast_continue: str="continue";break;
|
||||
case ast_break: str="break";break;
|
||||
case ast_return: str="return";break;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
enum parse_error
|
||||
{
|
||||
unknown,
|
||||
error_token,
|
||||
error_expr,
|
||||
lack_left_curve,
|
||||
lack_right_curve,
|
||||
lack_left_bracket,
|
||||
lack_right_bracket,
|
||||
lack_left_brace,
|
||||
lack_right_brace,
|
||||
exprs_lack_rbrace,
|
||||
lack_semi,
|
||||
lack_comma,
|
||||
lack_colon,
|
||||
lack_equal,
|
||||
lack_scalar,
|
||||
lack_identifier,
|
||||
lack_calculation,
|
||||
lack_exprs,
|
||||
lack_token,
|
||||
lack_args,
|
||||
default_arg_not_end,
|
||||
dynamic_id_not_end,
|
||||
name_repetition,
|
||||
definition_use_call,
|
||||
multi_id_use_call,
|
||||
multi_assign_lack_val,
|
||||
lack_definition,
|
||||
lack_loop_iter,
|
||||
lack_func_content
|
||||
};
|
||||
|
||||
void error_info(int line,int error_type,std::string error_str="")
|
||||
{
|
||||
std::string detail;
|
||||
std::cout<<">> [parse] error_info: [line "<<line<<"] ";
|
||||
switch(error_type)
|
||||
{
|
||||
case unknown: std::cout<<"unknown error.\n"; break;
|
||||
case error_token: std::cout<<"error token \""+error_str+"\".\n"; break;
|
||||
case error_expr: std::cout<<"error expression \""+error_str+"\".\n"; break;
|
||||
case lack_left_curve: std::cout<<"expected \"(\".\n"; break;
|
||||
case lack_right_curve: std::cout<<"expected \")\".\n"; break;
|
||||
case lack_left_bracket: std::cout<<"expected \"[\".\n"; break;
|
||||
case lack_right_bracket: std::cout<<"expected \"]\".\n"; break;
|
||||
case lack_left_brace: std::cout<<"expected \"{\".\n"; break;
|
||||
case lack_right_brace: std::cout<<"expected \"}\".\n"; break;
|
||||
case exprs_lack_rbrace: std::cout<<"expected \"}\" with this line\'s \"{\".\n";break;
|
||||
case lack_semi: std::cout<<"expected \";\".\n"; break;
|
||||
case lack_comma: std::cout<<"expected \",\".\n"; break;
|
||||
case lack_colon: std::cout<<"expected \":\".\n"; break;
|
||||
case lack_equal: std::cout<<"expected \"=\".\n"; break;
|
||||
case lack_scalar: std::cout<<"expected scalar here.\n"; break;
|
||||
case lack_identifier: std::cout<<"expected identifier here.\n"; break;
|
||||
case lack_calculation: std::cout<<"expected arithmetic-expression here.\n"; break;
|
||||
case lack_exprs: std::cout<<"expected expression block here.\n"; break;
|
||||
case lack_token: std::cout<<"expected \""+error_str+"\" here.\n"; break;
|
||||
case lack_args: std::cout<<"expected arguments here.\n"; break;
|
||||
case default_arg_not_end: std::cout<<"default argument missing for parameter of "+error_str+".\n";break;
|
||||
case dynamic_id_not_end: std::cout<<"dynamic id must be the end of "+error_str+".\n";break;
|
||||
case name_repetition: std::cout<<"this identifier name has existed.\n";break;
|
||||
case definition_use_call: std::cout<<"should not use call_scalar in definition progress.\n";break;
|
||||
case multi_id_use_call: std::cout<<"should not use call_scalar in multi_id progress.\n";break;
|
||||
case multi_assign_lack_val:std::cout<<"multi-assignment lacks value list.\n";break;
|
||||
case lack_definition: std::cout<<"expected a definition expression here.\n";break;
|
||||
case lack_loop_iter: std::cout<<"expected an iterator to loop through.\n";break;
|
||||
case lack_func_content: std::cout<<"expected arguments or expression block here.\n";break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
enum runtime_scalar_type
|
||||
{
|
||||
vm_nil=0,
|
||||
vm_number,
|
||||
vm_string,
|
||||
vm_closure,
|
||||
vm_function,
|
||||
vm_vector,
|
||||
vm_hash
|
||||
};
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -1,184 +1,184 @@
|
|||
#ifndef __NASAL_IMPORT_H__
|
||||
#define __NASAL_IMPORT_H__
|
||||
|
||||
class nasal_import
|
||||
{
|
||||
private:
|
||||
nasal_resource import_src;
|
||||
nasal_lexer import_lex;
|
||||
nasal_parse import_par;
|
||||
nasal_ast import_ast;
|
||||
std::vector<std::string> filename_table;
|
||||
int error;
|
||||
void die(std::string,std::string);
|
||||
void init();
|
||||
bool check_import(nasal_ast&);
|
||||
bool check_exist(std::string);
|
||||
void linker(nasal_ast&,nasal_ast&);
|
||||
nasal_ast file_import(nasal_ast&);
|
||||
nasal_ast load(nasal_ast&);
|
||||
public:
|
||||
nasal_import();
|
||||
int get_error();
|
||||
void preprocessing(nasal_ast&);
|
||||
nasal_ast& get_root();
|
||||
};
|
||||
|
||||
nasal_import::nasal_import()
|
||||
{
|
||||
import_src.clear();
|
||||
import_lex.clear();
|
||||
import_par.clear();
|
||||
import_ast.clear();
|
||||
filename_table.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_import::die(std::string filename,std::string error_stage)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">> [import] in <\""<<filename<<"\">: error(s) occurred in "<<error_stage<<"."<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_import::init()
|
||||
{
|
||||
import_src.clear();
|
||||
import_lex.clear();
|
||||
import_par.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
bool nasal_import::check_import(nasal_ast& node)
|
||||
{
|
||||
/*
|
||||
only this kind of node can be recognized as 'import':
|
||||
|
||||
call
|
||||
id:import
|
||||
call_func
|
||||
string:'filename'
|
||||
*/
|
||||
if(node.get_type()!=ast_call)
|
||||
return false;
|
||||
std::vector<nasal_ast>& ref_vec=node.get_children();
|
||||
if(ref_vec.size()!=2)
|
||||
return false;
|
||||
if(ref_vec[0].get_str()!="import")
|
||||
return false;
|
||||
if(ref_vec[1].get_type()!=ast_call_func)
|
||||
return false;
|
||||
if(ref_vec[1].get_children().size()!=1 || ref_vec[1].get_children()[0].get_type()!=ast_string)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nasal_import::check_exist(std::string filename)
|
||||
{
|
||||
// avoid importing the same file
|
||||
int size=filename_table.size();
|
||||
for(int i=0;i<size;++i)
|
||||
if(filename==filename_table[i])
|
||||
return true;
|
||||
filename_table.push_back(filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
void nasal_import::linker(nasal_ast& root,nasal_ast& add_root)
|
||||
{
|
||||
// add children of add_root to the back of root
|
||||
std::vector<nasal_ast>& ref_vec=add_root.get_children();
|
||||
int size=ref_vec.size();
|
||||
for(int i=0;i<size;++i)
|
||||
root.add_child(ref_vec[i]);
|
||||
return;
|
||||
}
|
||||
|
||||
nasal_ast nasal_import::file_import(nasal_ast& node)
|
||||
{
|
||||
// initializing
|
||||
nasal_ast tmp;
|
||||
tmp.set_line(0);
|
||||
tmp.set_type(ast_root);
|
||||
init();
|
||||
|
||||
// get filename and set node to ast_null
|
||||
std::string filename=node.get_children()[1].get_children()[0].get_str();
|
||||
node.clear();
|
||||
node.set_type(ast_null);
|
||||
|
||||
// avoid infinite loading loop
|
||||
if(check_exist(filename))
|
||||
return tmp;
|
||||
|
||||
// start importing...
|
||||
if(!import_src.input_file(filename))
|
||||
{
|
||||
this->die(filename,"resource");
|
||||
return tmp;
|
||||
}
|
||||
import_lex.scanner(import_src.get_file());
|
||||
if(import_lex.get_error())
|
||||
{
|
||||
this->die(filename,"lexer");
|
||||
return tmp;
|
||||
}
|
||||
import_par.set_toklist(import_lex.get_token_list());
|
||||
import_par.main_process();
|
||||
if(import_par.get_error())
|
||||
{
|
||||
this->die(filename,"parser");
|
||||
return tmp;
|
||||
}
|
||||
tmp=import_par.get_root();
|
||||
|
||||
// check if tmp has 'import'
|
||||
return load(tmp);
|
||||
}
|
||||
|
||||
nasal_ast nasal_import::load(nasal_ast& root)
|
||||
{
|
||||
nasal_ast new_root;
|
||||
new_root.set_line(0);
|
||||
new_root.set_type(ast_root);
|
||||
|
||||
std::vector<nasal_ast>& ref_vec=root.get_children();
|
||||
int size=ref_vec.size();
|
||||
for(int i=0;i<size;++i)
|
||||
{
|
||||
if(check_import(ref_vec[i]))
|
||||
{
|
||||
nasal_ast tmp=file_import(ref_vec[i]);
|
||||
// add tmp to the back of new_root
|
||||
linker(new_root,tmp);
|
||||
}
|
||||
}
|
||||
// add root to the back of new_root
|
||||
linker(new_root,root);
|
||||
|
||||
// oops,i think it is not efficient if the root is too ... large?
|
||||
return new_root;
|
||||
}
|
||||
|
||||
void nasal_import::preprocessing(nasal_ast& root)
|
||||
{
|
||||
// initializing
|
||||
error=0;
|
||||
filename_table.clear();
|
||||
import_ast.clear();
|
||||
// scan root and import files,then generate a new ast and return to import_ast
|
||||
import_ast=load(root);
|
||||
return;
|
||||
}
|
||||
|
||||
nasal_ast& nasal_import::get_root()
|
||||
{
|
||||
return import_ast;
|
||||
}
|
||||
|
||||
int nasal_import::get_error()
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
#ifndef __NASAL_IMPORT_H__
|
||||
#define __NASAL_IMPORT_H__
|
||||
|
||||
class nasal_import
|
||||
{
|
||||
private:
|
||||
nasal_resource import_src;
|
||||
nasal_lexer import_lex;
|
||||
nasal_parse import_par;
|
||||
nasal_ast import_ast;
|
||||
std::vector<std::string> filename_table;
|
||||
int error;
|
||||
void die(std::string,std::string);
|
||||
void init();
|
||||
bool check_import(nasal_ast&);
|
||||
bool check_exist(std::string);
|
||||
void linker(nasal_ast&,nasal_ast&);
|
||||
nasal_ast file_import(nasal_ast&);
|
||||
nasal_ast load(nasal_ast&);
|
||||
public:
|
||||
nasal_import();
|
||||
int get_error();
|
||||
void preprocessing(nasal_ast&);
|
||||
nasal_ast& get_root();
|
||||
};
|
||||
|
||||
nasal_import::nasal_import()
|
||||
{
|
||||
import_src.clear();
|
||||
import_lex.clear();
|
||||
import_par.clear();
|
||||
import_ast.clear();
|
||||
filename_table.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_import::die(std::string filename,std::string error_stage)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">> [import] in <\""<<filename<<"\">: error(s) occurred in "<<error_stage<<"."<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_import::init()
|
||||
{
|
||||
import_src.clear();
|
||||
import_lex.clear();
|
||||
import_par.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
bool nasal_import::check_import(nasal_ast& node)
|
||||
{
|
||||
/*
|
||||
only this kind of node can be recognized as 'import':
|
||||
|
||||
call
|
||||
id:import
|
||||
call_func
|
||||
string:'filename'
|
||||
*/
|
||||
if(node.get_type()!=ast_call)
|
||||
return false;
|
||||
std::vector<nasal_ast>& ref_vec=node.get_children();
|
||||
if(ref_vec.size()!=2)
|
||||
return false;
|
||||
if(ref_vec[0].get_str()!="import")
|
||||
return false;
|
||||
if(ref_vec[1].get_type()!=ast_call_func)
|
||||
return false;
|
||||
if(ref_vec[1].get_children().size()!=1 || ref_vec[1].get_children()[0].get_type()!=ast_string)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nasal_import::check_exist(std::string filename)
|
||||
{
|
||||
// avoid importing the same file
|
||||
int size=filename_table.size();
|
||||
for(int i=0;i<size;++i)
|
||||
if(filename==filename_table[i])
|
||||
return true;
|
||||
filename_table.push_back(filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
void nasal_import::linker(nasal_ast& root,nasal_ast& add_root)
|
||||
{
|
||||
// add children of add_root to the back of root
|
||||
std::vector<nasal_ast>& ref_vec=add_root.get_children();
|
||||
int size=ref_vec.size();
|
||||
for(int i=0;i<size;++i)
|
||||
root.add_child(ref_vec[i]);
|
||||
return;
|
||||
}
|
||||
|
||||
nasal_ast nasal_import::file_import(nasal_ast& node)
|
||||
{
|
||||
// initializing
|
||||
nasal_ast tmp;
|
||||
tmp.set_line(0);
|
||||
tmp.set_type(ast_root);
|
||||
init();
|
||||
|
||||
// get filename and set node to ast_null
|
||||
std::string filename=node.get_children()[1].get_children()[0].get_str();
|
||||
node.clear();
|
||||
node.set_type(ast_null);
|
||||
|
||||
// avoid infinite loading loop
|
||||
if(check_exist(filename))
|
||||
return tmp;
|
||||
|
||||
// start importing...
|
||||
if(!import_src.input_file(filename))
|
||||
{
|
||||
this->die(filename,"resource");
|
||||
return tmp;
|
||||
}
|
||||
import_lex.scanner(import_src.get_file());
|
||||
if(import_lex.get_error())
|
||||
{
|
||||
this->die(filename,"lexer");
|
||||
return tmp;
|
||||
}
|
||||
import_par.set_toklist(import_lex.get_token_list());
|
||||
import_par.main_process();
|
||||
if(import_par.get_error())
|
||||
{
|
||||
this->die(filename,"parser");
|
||||
return tmp;
|
||||
}
|
||||
tmp=import_par.get_root();
|
||||
|
||||
// check if tmp has 'import'
|
||||
return load(tmp);
|
||||
}
|
||||
|
||||
nasal_ast nasal_import::load(nasal_ast& root)
|
||||
{
|
||||
nasal_ast new_root;
|
||||
new_root.set_line(0);
|
||||
new_root.set_type(ast_root);
|
||||
|
||||
std::vector<nasal_ast>& ref_vec=root.get_children();
|
||||
int size=ref_vec.size();
|
||||
for(int i=0;i<size;++i)
|
||||
{
|
||||
if(check_import(ref_vec[i]))
|
||||
{
|
||||
nasal_ast tmp=file_import(ref_vec[i]);
|
||||
// add tmp to the back of new_root
|
||||
linker(new_root,tmp);
|
||||
}
|
||||
}
|
||||
// add root to the back of new_root
|
||||
linker(new_root,root);
|
||||
|
||||
// oops,i think it is not efficient if the root is too ... large?
|
||||
return new_root;
|
||||
}
|
||||
|
||||
void nasal_import::preprocessing(nasal_ast& root)
|
||||
{
|
||||
// initializing
|
||||
error=0;
|
||||
filename_table.clear();
|
||||
import_ast.clear();
|
||||
// scan root and import files,then generate a new ast and return to import_ast
|
||||
import_ast=load(root);
|
||||
return;
|
||||
}
|
||||
|
||||
nasal_ast& nasal_import::get_root()
|
||||
{
|
||||
return import_ast;
|
||||
}
|
||||
|
||||
int nasal_import::get_error()
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,394 +1,394 @@
|
|||
#ifndef __NASAL_LEXER_H__
|
||||
#define __NASAL_LEXER_H__
|
||||
|
||||
#define IS_IDENTIFIER_HEAD(c) ((c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z'))
|
||||
#define IS_IDENTIFIER_BODY(c) ((c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z')||('0'<=c&&c<='9'))
|
||||
#define IS_HEX_NUMBER(c) (('0'<=c&&c<='9')||('a'<=c&&c<='f')||('A'<=c && c<='F'))
|
||||
#define IS_OCT_NUMEBR(c) ('0'<=c&&c<='7')
|
||||
#define IS_DIGIT(c) ('0'<=c&&c<='9')
|
||||
#define IS_STRING_HEAD(c) (c=='\''||c=='\"')
|
||||
// single operators have only one character
|
||||
#define IS_SINGLE_OPRATOR(c) (c=='('||c==')'||c=='['||c==']'||c=='{'||c=='}'||c==','||c==';'||c=='|'||c==':'||\
|
||||
c=='?'||c=='`'||c=='&'||c=='@'||c=='%'||c=='$'||c=='^'||c=='\\')
|
||||
// calculation operators may have two chars, for example: += -= *= /= ~= != == >= <=
|
||||
#define IS_CALC_OPERATOR(c) (c=='='||c=='+'||c=='-'||c=='*'||c=='!'||c=='/'||c=='<'||c=='>'||c=='~')
|
||||
#define IS_NOTE_HEAD(c) (c=='#')
|
||||
|
||||
#ifndef TOKEN_TABLE_SIZE
|
||||
#define TOKEN_TABLE_SIZE 45
|
||||
struct token_table
|
||||
{
|
||||
std::string str;
|
||||
int tok_type;
|
||||
}tok_tbl[TOKEN_TABLE_SIZE]=
|
||||
{
|
||||
{"for" ,tok_for },
|
||||
{"forindex",tok_forindex },
|
||||
{"foreach" ,tok_foreach },
|
||||
{"while" ,tok_while },
|
||||
{"var" ,tok_var },
|
||||
{"func" ,tok_func },
|
||||
{"break" ,tok_break },
|
||||
{"continue",tok_continue },
|
||||
{"return" ,tok_return },
|
||||
{"if" ,tok_if },
|
||||
{"elsif" ,tok_elsif },
|
||||
{"else" ,tok_else },
|
||||
{"nil" ,tok_nil },
|
||||
{"(" ,tok_left_curve },
|
||||
{")" ,tok_right_curve },
|
||||
{"[" ,tok_left_bracket },
|
||||
{"]" ,tok_right_bracket},
|
||||
{"{" ,tok_left_brace },
|
||||
{"}" ,tok_right_brace },
|
||||
{";" ,tok_semi },
|
||||
{"and" ,tok_and },
|
||||
{"or" ,tok_or },
|
||||
{"," ,tok_comma },
|
||||
{"." ,tok_dot },
|
||||
{"..." ,tok_ellipsis },
|
||||
{"?" ,tok_quesmark },
|
||||
{":" ,tok_colon },
|
||||
{"+" ,tok_add },
|
||||
{"-" ,tok_sub },
|
||||
{"*" ,tok_mult },
|
||||
{"/" ,tok_div },
|
||||
{"~" ,tok_link },
|
||||
{"!" ,tok_not },
|
||||
{"=" ,tok_equal },
|
||||
{"+=" ,tok_add_equal },
|
||||
{"-=" ,tok_sub_equal },
|
||||
{"*=" ,tok_mult_equal },
|
||||
{"/=" ,tok_div_equal },
|
||||
{"~=" ,tok_link_equal },
|
||||
{"==" ,tok_cmp_equal },
|
||||
{"!=" ,tok_cmp_not_equal},
|
||||
{"<" ,tok_less_than },
|
||||
{">" ,tok_greater_than },
|
||||
{"<=" ,tok_less_equal },
|
||||
{">=" ,tok_greater_equal},
|
||||
};
|
||||
#endif
|
||||
|
||||
struct token
|
||||
{
|
||||
int line;
|
||||
int type;
|
||||
std::string str;
|
||||
};
|
||||
|
||||
class nasal_lexer
|
||||
{
|
||||
private:
|
||||
int error;
|
||||
std::vector<token> token_list;
|
||||
std::string identifier_gen(std::vector<char>&,int&,int&);
|
||||
void generate_number_error(int,std::string);
|
||||
std::string number_gen(std::vector<char>&,int&,int&);
|
||||
std::string string_gen(std::vector<char>&,int&,int&);
|
||||
public:
|
||||
void clear();
|
||||
void scanner(std::vector<char>&);
|
||||
void print_token();
|
||||
int get_error();
|
||||
std::vector<token>& get_token_list();
|
||||
};
|
||||
|
||||
void nasal_lexer::clear()
|
||||
{
|
||||
token_list.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
std::string nasal_lexer::identifier_gen(std::vector<char>& res,int& ptr,int& line)
|
||||
{
|
||||
int res_size=res.size();
|
||||
std::string token_str="";
|
||||
while(ptr<res_size && IS_IDENTIFIER_BODY(res[ptr]))
|
||||
token_str+=res[ptr++];
|
||||
return token_str;
|
||||
// after running this process, ptr will point to the next token's beginning character
|
||||
}
|
||||
|
||||
void nasal_lexer::generate_number_error(int line,std::string token_str)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">> [lexer] line "<<line<<": \""<<token_str<<"\" is not a correct number.\n";
|
||||
return;
|
||||
}
|
||||
std::string nasal_lexer::number_gen(std::vector<char>& res,int& ptr,int& line)
|
||||
{
|
||||
int res_size=res.size();
|
||||
bool scientific_notation=false;// numbers like 1e8 are scientific_notation
|
||||
std::string token_str="";
|
||||
// generate hex number
|
||||
if(res[ptr]=='0' && ptr+1<res_size && res[ptr+1]=='x')
|
||||
{
|
||||
token_str="0x";
|
||||
ptr+=2;
|
||||
while(ptr<res_size && IS_HEX_NUMBER(res[ptr]))
|
||||
token_str+=res[ptr++];
|
||||
if(token_str=="0x")
|
||||
{
|
||||
generate_number_error(line,token_str);
|
||||
return "0";
|
||||
}
|
||||
return token_str;
|
||||
}
|
||||
// generate oct number
|
||||
else if(res[ptr]=='0' && ptr+1<res_size && res[ptr+1]=='o')
|
||||
{
|
||||
token_str="0o";
|
||||
ptr+=2;
|
||||
while(ptr<res_size && IS_OCT_NUMEBR(res[ptr]))
|
||||
token_str+=res[ptr++];
|
||||
if(token_str=="0o")
|
||||
{
|
||||
generate_number_error(line,token_str);
|
||||
return "0";
|
||||
}
|
||||
return token_str;
|
||||
}
|
||||
// generate dec number
|
||||
// dec number -> 0|[1~9][0~9]*(.[0~9]*)(e|E(+|-)0|[1~9][0~9]*)
|
||||
if(ptr<res_size && res[ptr]=='0')
|
||||
token_str+=res[ptr++];
|
||||
while(ptr<res_size && IS_DIGIT(res[ptr]))
|
||||
token_str+=res[ptr++];
|
||||
if(ptr<res_size && res[ptr]=='.')
|
||||
{
|
||||
token_str+=res[ptr++];
|
||||
// "xxxx." is not a correct number
|
||||
if(ptr>=res_size)
|
||||
{
|
||||
generate_number_error(line,token_str);
|
||||
return "0";
|
||||
}
|
||||
while(ptr<res_size && IS_DIGIT(res[ptr]))
|
||||
token_str+=res[ptr++];
|
||||
// "xxxx." is not a correct number
|
||||
if(token_str.back()=='.')
|
||||
{
|
||||
generate_number_error(line,token_str);
|
||||
return "0";
|
||||
}
|
||||
}
|
||||
if(ptr<res_size && (res[ptr]=='e' || res[ptr]=='E'))
|
||||
{
|
||||
token_str+=res[ptr++];
|
||||
// "xxxe" is not a correct number
|
||||
if(ptr>=res_size)
|
||||
{
|
||||
generate_number_error(line,token_str);
|
||||
return "0";
|
||||
}
|
||||
if(ptr<res_size && (res[ptr]=='-' || res[ptr]=='+'))
|
||||
token_str+=res[ptr++];
|
||||
if(ptr>=res_size)
|
||||
{
|
||||
generate_number_error(line,token_str);
|
||||
return "0";
|
||||
}
|
||||
if(ptr<res_size && res[ptr]=='0')
|
||||
token_str+=res[ptr++];
|
||||
while(ptr<res_size && IS_DIGIT(res[ptr]))
|
||||
token_str+=res[ptr++];
|
||||
// "xxxe(-|+)" is not a correct number
|
||||
if(token_str.back()=='e' || token_str.back()=='E' || token_str.back()=='-' || token_str.back()=='+')
|
||||
{
|
||||
generate_number_error(line,token_str);
|
||||
return "0";
|
||||
}
|
||||
}
|
||||
return token_str;
|
||||
}
|
||||
|
||||
std::string nasal_lexer::string_gen(std::vector<char>& res,int& ptr,int& line)
|
||||
{
|
||||
int res_size=res.size();
|
||||
std::string token_str="";
|
||||
char str_begin=res[ptr++];
|
||||
if(ptr>=res_size) return token_str;
|
||||
while(ptr<res_size && res[ptr]!=str_begin)
|
||||
{
|
||||
if(res[ptr]=='\n') ++line;
|
||||
if(res[ptr]=='\\' && ptr+1<res.size())
|
||||
{
|
||||
++ptr;
|
||||
switch(res[ptr])
|
||||
{
|
||||
case 'a':token_str.push_back('\a');break;
|
||||
case 'b':token_str.push_back('\b');break;
|
||||
case 'f':token_str.push_back('\f');break;
|
||||
case 'n':token_str.push_back('\n');break;
|
||||
case 'r':token_str.push_back('\r');break;
|
||||
case 't':token_str.push_back('\t');break;
|
||||
case 'v':token_str.push_back('\v');break;
|
||||
case '?':token_str.push_back('\?');break;
|
||||
case '0':token_str.push_back('\0');break;
|
||||
case '\\':token_str.push_back('\\');break;
|
||||
case '\'':token_str.push_back('\'');break;
|
||||
case '\"':token_str.push_back('\"');break;
|
||||
default: token_str.push_back(res[ptr]);break;
|
||||
}
|
||||
}
|
||||
else
|
||||
token_str+=res[ptr];
|
||||
++ptr;
|
||||
}
|
||||
// check if this string ends with a " or '
|
||||
if(ptr>=res_size)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">> [lexer] line "<<line<<": get EOF when generating string.\n";
|
||||
}
|
||||
++ptr;
|
||||
return token_str;
|
||||
}
|
||||
|
||||
void nasal_lexer::scanner(std::vector<char>& res)
|
||||
{
|
||||
error=0;
|
||||
token_list.clear();
|
||||
int line=1,ptr=0,res_size=res.size();
|
||||
std::string token_str;
|
||||
while(ptr<res_size)
|
||||
{
|
||||
while(ptr<res_size && (res[ptr]==' ' || res[ptr]=='\n' || res[ptr]=='\t' || res[ptr]=='\r' || res[ptr]<0))
|
||||
{
|
||||
// these characters will be ignored, and '\n' will cause ++line
|
||||
if(res[ptr]=='\n') ++line;
|
||||
++ptr;
|
||||
}
|
||||
if(ptr>=res_size) break;
|
||||
if(IS_IDENTIFIER_HEAD(res[ptr]))
|
||||
{
|
||||
token_str=identifier_gen(res,ptr,line);
|
||||
token new_token;
|
||||
new_token.line=line;
|
||||
new_token.str=token_str;
|
||||
new_token.type=0;
|
||||
for(int i=0;i<TOKEN_TABLE_SIZE;++i)
|
||||
if(token_str==tok_tbl[i].str)
|
||||
{
|
||||
new_token.type=tok_tbl[i].tok_type;
|
||||
break;
|
||||
}
|
||||
if(!new_token.type)
|
||||
new_token.type=tok_identifier;
|
||||
token_list.push_back(new_token);
|
||||
}
|
||||
else if(IS_DIGIT(res[ptr]))
|
||||
{
|
||||
token_str=number_gen(res,ptr,line);
|
||||
token new_token;
|
||||
new_token.line=line;
|
||||
new_token.str=token_str;
|
||||
new_token.type=tok_number;
|
||||
token_list.push_back(new_token);
|
||||
}
|
||||
else if(IS_STRING_HEAD(res[ptr]))
|
||||
{
|
||||
token_str=string_gen(res,ptr,line);
|
||||
token new_token;
|
||||
new_token.line=line;
|
||||
new_token.type=tok_string;
|
||||
new_token.str=token_str;
|
||||
token_list.push_back(new_token);
|
||||
}
|
||||
else if(IS_SINGLE_OPRATOR(res[ptr]))
|
||||
{
|
||||
token_str="";
|
||||
token_str+=res[ptr];
|
||||
token new_token;
|
||||
new_token.line=line;
|
||||
new_token.str=token_str;
|
||||
for(int i=0;i<TOKEN_TABLE_SIZE;++i)
|
||||
if(token_str==tok_tbl[i].str)
|
||||
{
|
||||
new_token.type=tok_tbl[i].tok_type;
|
||||
break;
|
||||
}
|
||||
token_list.push_back(new_token);
|
||||
++ptr;
|
||||
}
|
||||
else if(res[ptr]=='.')
|
||||
{
|
||||
if(ptr+2<res_size && res[ptr+1]=='.' && res[ptr+2]=='.')
|
||||
{
|
||||
token_str="...";
|
||||
ptr+=3;
|
||||
}
|
||||
else
|
||||
{
|
||||
token_str=".";
|
||||
++ptr;
|
||||
}
|
||||
token new_token;
|
||||
new_token.line=line;
|
||||
new_token.str=token_str;
|
||||
for(int i=0;i<TOKEN_TABLE_SIZE;++i)
|
||||
if(token_str==tok_tbl[i].str)
|
||||
{
|
||||
new_token.type=tok_tbl[i].tok_type;
|
||||
break;
|
||||
}
|
||||
token_list.push_back(new_token);
|
||||
}
|
||||
else if(IS_CALC_OPERATOR(res[ptr]))
|
||||
{
|
||||
// get calculation operator
|
||||
token_str="";
|
||||
token_str+=res[ptr];
|
||||
++ptr;
|
||||
if(ptr<res.size() && res[ptr]=='=')
|
||||
{
|
||||
token_str+=res[ptr];
|
||||
++ptr;
|
||||
}
|
||||
token new_token;
|
||||
new_token.line=line;
|
||||
new_token.str=token_str;
|
||||
for(int i=0;i<TOKEN_TABLE_SIZE;++i)
|
||||
if(token_str==tok_tbl[i].str)
|
||||
{
|
||||
new_token.type=tok_tbl[i].tok_type;
|
||||
break;
|
||||
}
|
||||
token_list.push_back(new_token);
|
||||
}
|
||||
else if(IS_NOTE_HEAD(res[ptr]))
|
||||
{
|
||||
// avoid note
|
||||
while(ptr<res_size && res[ptr]!='\n') ++ptr;
|
||||
// after this process ptr will point to a '\n'
|
||||
// don't ++ptr then the counter for line can work correctly
|
||||
}
|
||||
else
|
||||
{
|
||||
++error;
|
||||
std::cout<<">> [lexer] line "<<line<<": unknown char "<<(int)res[ptr]<<'.'<<std::endl;
|
||||
++ptr;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_lexer::print_token()
|
||||
{
|
||||
int size=token_list.size();
|
||||
for(int i=0;i<size;++i)
|
||||
std::cout<<"("<<token_list[i].line<<" | "<<token_list[i].str<<")\n";
|
||||
return;
|
||||
}
|
||||
|
||||
int nasal_lexer::get_error()
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
std::vector<token>& nasal_lexer::get_token_list()
|
||||
{
|
||||
return token_list;
|
||||
}
|
||||
#ifndef __NASAL_LEXER_H__
|
||||
#define __NASAL_LEXER_H__
|
||||
|
||||
#define IS_IDENTIFIER_HEAD(c) ((c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z'))
|
||||
#define IS_IDENTIFIER_BODY(c) ((c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z')||('0'<=c&&c<='9'))
|
||||
#define IS_HEX_NUMBER(c) (('0'<=c&&c<='9')||('a'<=c&&c<='f')||('A'<=c && c<='F'))
|
||||
#define IS_OCT_NUMEBR(c) ('0'<=c&&c<='7')
|
||||
#define IS_DIGIT(c) ('0'<=c&&c<='9')
|
||||
#define IS_STRING_HEAD(c) (c=='\''||c=='\"')
|
||||
// single operators have only one character
|
||||
#define IS_SINGLE_OPRATOR(c) (c=='('||c==')'||c=='['||c==']'||c=='{'||c=='}'||c==','||c==';'||c=='|'||c==':'||\
|
||||
c=='?'||c=='`'||c=='&'||c=='@'||c=='%'||c=='$'||c=='^'||c=='\\')
|
||||
// calculation operators may have two chars, for example: += -= *= /= ~= != == >= <=
|
||||
#define IS_CALC_OPERATOR(c) (c=='='||c=='+'||c=='-'||c=='*'||c=='!'||c=='/'||c=='<'||c=='>'||c=='~')
|
||||
#define IS_NOTE_HEAD(c) (c=='#')
|
||||
|
||||
#ifndef TOKEN_TABLE_SIZE
|
||||
#define TOKEN_TABLE_SIZE 45
|
||||
struct token_table
|
||||
{
|
||||
std::string str;
|
||||
int tok_type;
|
||||
}tok_tbl[TOKEN_TABLE_SIZE]=
|
||||
{
|
||||
{"for" ,tok_for },
|
||||
{"forindex",tok_forindex },
|
||||
{"foreach" ,tok_foreach },
|
||||
{"while" ,tok_while },
|
||||
{"var" ,tok_var },
|
||||
{"func" ,tok_func },
|
||||
{"break" ,tok_break },
|
||||
{"continue",tok_continue },
|
||||
{"return" ,tok_return },
|
||||
{"if" ,tok_if },
|
||||
{"elsif" ,tok_elsif },
|
||||
{"else" ,tok_else },
|
||||
{"nil" ,tok_nil },
|
||||
{"(" ,tok_left_curve },
|
||||
{")" ,tok_right_curve },
|
||||
{"[" ,tok_left_bracket },
|
||||
{"]" ,tok_right_bracket},
|
||||
{"{" ,tok_left_brace },
|
||||
{"}" ,tok_right_brace },
|
||||
{";" ,tok_semi },
|
||||
{"and" ,tok_and },
|
||||
{"or" ,tok_or },
|
||||
{"," ,tok_comma },
|
||||
{"." ,tok_dot },
|
||||
{"..." ,tok_ellipsis },
|
||||
{"?" ,tok_quesmark },
|
||||
{":" ,tok_colon },
|
||||
{"+" ,tok_add },
|
||||
{"-" ,tok_sub },
|
||||
{"*" ,tok_mult },
|
||||
{"/" ,tok_div },
|
||||
{"~" ,tok_link },
|
||||
{"!" ,tok_not },
|
||||
{"=" ,tok_equal },
|
||||
{"+=" ,tok_add_equal },
|
||||
{"-=" ,tok_sub_equal },
|
||||
{"*=" ,tok_mult_equal },
|
||||
{"/=" ,tok_div_equal },
|
||||
{"~=" ,tok_link_equal },
|
||||
{"==" ,tok_cmp_equal },
|
||||
{"!=" ,tok_cmp_not_equal},
|
||||
{"<" ,tok_less_than },
|
||||
{">" ,tok_greater_than },
|
||||
{"<=" ,tok_less_equal },
|
||||
{">=" ,tok_greater_equal},
|
||||
};
|
||||
#endif
|
||||
|
||||
struct token
|
||||
{
|
||||
int line;
|
||||
int type;
|
||||
std::string str;
|
||||
};
|
||||
|
||||
class nasal_lexer
|
||||
{
|
||||
private:
|
||||
int error;
|
||||
std::vector<token> token_list;
|
||||
std::string identifier_gen(std::vector<char>&,int&,int&);
|
||||
void generate_number_error(int,std::string);
|
||||
std::string number_gen(std::vector<char>&,int&,int&);
|
||||
std::string string_gen(std::vector<char>&,int&,int&);
|
||||
public:
|
||||
void clear();
|
||||
void scanner(std::vector<char>&);
|
||||
void print_token();
|
||||
int get_error();
|
||||
std::vector<token>& get_token_list();
|
||||
};
|
||||
|
||||
void nasal_lexer::clear()
|
||||
{
|
||||
token_list.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
std::string nasal_lexer::identifier_gen(std::vector<char>& res,int& ptr,int& line)
|
||||
{
|
||||
int res_size=res.size();
|
||||
std::string token_str="";
|
||||
while(ptr<res_size && IS_IDENTIFIER_BODY(res[ptr]))
|
||||
token_str+=res[ptr++];
|
||||
return token_str;
|
||||
// after running this process, ptr will point to the next token's beginning character
|
||||
}
|
||||
|
||||
void nasal_lexer::generate_number_error(int line,std::string token_str)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">> [lexer] line "<<line<<": \""<<token_str<<"\" is not a correct number.\n";
|
||||
return;
|
||||
}
|
||||
std::string nasal_lexer::number_gen(std::vector<char>& res,int& ptr,int& line)
|
||||
{
|
||||
int res_size=res.size();
|
||||
bool scientific_notation=false;// numbers like 1e8 are scientific_notation
|
||||
std::string token_str="";
|
||||
// generate hex number
|
||||
if(res[ptr]=='0' && ptr+1<res_size && res[ptr+1]=='x')
|
||||
{
|
||||
token_str="0x";
|
||||
ptr+=2;
|
||||
while(ptr<res_size && IS_HEX_NUMBER(res[ptr]))
|
||||
token_str+=res[ptr++];
|
||||
if(token_str=="0x")
|
||||
{
|
||||
generate_number_error(line,token_str);
|
||||
return "0";
|
||||
}
|
||||
return token_str;
|
||||
}
|
||||
// generate oct number
|
||||
else if(res[ptr]=='0' && ptr+1<res_size && res[ptr+1]=='o')
|
||||
{
|
||||
token_str="0o";
|
||||
ptr+=2;
|
||||
while(ptr<res_size && IS_OCT_NUMEBR(res[ptr]))
|
||||
token_str+=res[ptr++];
|
||||
if(token_str=="0o")
|
||||
{
|
||||
generate_number_error(line,token_str);
|
||||
return "0";
|
||||
}
|
||||
return token_str;
|
||||
}
|
||||
// generate dec number
|
||||
// dec number -> 0|[1~9][0~9]*(.[0~9]*)(e|E(+|-)0|[1~9][0~9]*)
|
||||
if(ptr<res_size && res[ptr]=='0')
|
||||
token_str+=res[ptr++];
|
||||
while(ptr<res_size && IS_DIGIT(res[ptr]))
|
||||
token_str+=res[ptr++];
|
||||
if(ptr<res_size && res[ptr]=='.')
|
||||
{
|
||||
token_str+=res[ptr++];
|
||||
// "xxxx." is not a correct number
|
||||
if(ptr>=res_size)
|
||||
{
|
||||
generate_number_error(line,token_str);
|
||||
return "0";
|
||||
}
|
||||
while(ptr<res_size && IS_DIGIT(res[ptr]))
|
||||
token_str+=res[ptr++];
|
||||
// "xxxx." is not a correct number
|
||||
if(token_str.back()=='.')
|
||||
{
|
||||
generate_number_error(line,token_str);
|
||||
return "0";
|
||||
}
|
||||
}
|
||||
if(ptr<res_size && (res[ptr]=='e' || res[ptr]=='E'))
|
||||
{
|
||||
token_str+=res[ptr++];
|
||||
// "xxxe" is not a correct number
|
||||
if(ptr>=res_size)
|
||||
{
|
||||
generate_number_error(line,token_str);
|
||||
return "0";
|
||||
}
|
||||
if(ptr<res_size && (res[ptr]=='-' || res[ptr]=='+'))
|
||||
token_str+=res[ptr++];
|
||||
if(ptr>=res_size)
|
||||
{
|
||||
generate_number_error(line,token_str);
|
||||
return "0";
|
||||
}
|
||||
if(ptr<res_size && res[ptr]=='0')
|
||||
token_str+=res[ptr++];
|
||||
while(ptr<res_size && IS_DIGIT(res[ptr]))
|
||||
token_str+=res[ptr++];
|
||||
// "xxxe(-|+)" is not a correct number
|
||||
if(token_str.back()=='e' || token_str.back()=='E' || token_str.back()=='-' || token_str.back()=='+')
|
||||
{
|
||||
generate_number_error(line,token_str);
|
||||
return "0";
|
||||
}
|
||||
}
|
||||
return token_str;
|
||||
}
|
||||
|
||||
std::string nasal_lexer::string_gen(std::vector<char>& res,int& ptr,int& line)
|
||||
{
|
||||
int res_size=res.size();
|
||||
std::string token_str="";
|
||||
char str_begin=res[ptr++];
|
||||
if(ptr>=res_size) return token_str;
|
||||
while(ptr<res_size && res[ptr]!=str_begin)
|
||||
{
|
||||
if(res[ptr]=='\n') ++line;
|
||||
if(res[ptr]=='\\' && ptr+1<res.size())
|
||||
{
|
||||
++ptr;
|
||||
switch(res[ptr])
|
||||
{
|
||||
case 'a':token_str.push_back('\a');break;
|
||||
case 'b':token_str.push_back('\b');break;
|
||||
case 'f':token_str.push_back('\f');break;
|
||||
case 'n':token_str.push_back('\n');break;
|
||||
case 'r':token_str.push_back('\r');break;
|
||||
case 't':token_str.push_back('\t');break;
|
||||
case 'v':token_str.push_back('\v');break;
|
||||
case '?':token_str.push_back('\?');break;
|
||||
case '0':token_str.push_back('\0');break;
|
||||
case '\\':token_str.push_back('\\');break;
|
||||
case '\'':token_str.push_back('\'');break;
|
||||
case '\"':token_str.push_back('\"');break;
|
||||
default: token_str.push_back(res[ptr]);break;
|
||||
}
|
||||
}
|
||||
else
|
||||
token_str+=res[ptr];
|
||||
++ptr;
|
||||
}
|
||||
// check if this string ends with a " or '
|
||||
if(ptr>=res_size)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">> [lexer] line "<<line<<": get EOF when generating string.\n";
|
||||
}
|
||||
++ptr;
|
||||
return token_str;
|
||||
}
|
||||
|
||||
void nasal_lexer::scanner(std::vector<char>& res)
|
||||
{
|
||||
error=0;
|
||||
token_list.clear();
|
||||
int line=1,ptr=0,res_size=res.size();
|
||||
std::string token_str;
|
||||
while(ptr<res_size)
|
||||
{
|
||||
while(ptr<res_size && (res[ptr]==' ' || res[ptr]=='\n' || res[ptr]=='\t' || res[ptr]=='\r' || res[ptr]<0))
|
||||
{
|
||||
// these characters will be ignored, and '\n' will cause ++line
|
||||
if(res[ptr]=='\n') ++line;
|
||||
++ptr;
|
||||
}
|
||||
if(ptr>=res_size) break;
|
||||
if(IS_IDENTIFIER_HEAD(res[ptr]))
|
||||
{
|
||||
token_str=identifier_gen(res,ptr,line);
|
||||
token new_token;
|
||||
new_token.line=line;
|
||||
new_token.str=token_str;
|
||||
new_token.type=0;
|
||||
for(int i=0;i<TOKEN_TABLE_SIZE;++i)
|
||||
if(token_str==tok_tbl[i].str)
|
||||
{
|
||||
new_token.type=tok_tbl[i].tok_type;
|
||||
break;
|
||||
}
|
||||
if(!new_token.type)
|
||||
new_token.type=tok_identifier;
|
||||
token_list.push_back(new_token);
|
||||
}
|
||||
else if(IS_DIGIT(res[ptr]))
|
||||
{
|
||||
token_str=number_gen(res,ptr,line);
|
||||
token new_token;
|
||||
new_token.line=line;
|
||||
new_token.str=token_str;
|
||||
new_token.type=tok_number;
|
||||
token_list.push_back(new_token);
|
||||
}
|
||||
else if(IS_STRING_HEAD(res[ptr]))
|
||||
{
|
||||
token_str=string_gen(res,ptr,line);
|
||||
token new_token;
|
||||
new_token.line=line;
|
||||
new_token.type=tok_string;
|
||||
new_token.str=token_str;
|
||||
token_list.push_back(new_token);
|
||||
}
|
||||
else if(IS_SINGLE_OPRATOR(res[ptr]))
|
||||
{
|
||||
token_str="";
|
||||
token_str+=res[ptr];
|
||||
token new_token;
|
||||
new_token.line=line;
|
||||
new_token.str=token_str;
|
||||
for(int i=0;i<TOKEN_TABLE_SIZE;++i)
|
||||
if(token_str==tok_tbl[i].str)
|
||||
{
|
||||
new_token.type=tok_tbl[i].tok_type;
|
||||
break;
|
||||
}
|
||||
token_list.push_back(new_token);
|
||||
++ptr;
|
||||
}
|
||||
else if(res[ptr]=='.')
|
||||
{
|
||||
if(ptr+2<res_size && res[ptr+1]=='.' && res[ptr+2]=='.')
|
||||
{
|
||||
token_str="...";
|
||||
ptr+=3;
|
||||
}
|
||||
else
|
||||
{
|
||||
token_str=".";
|
||||
++ptr;
|
||||
}
|
||||
token new_token;
|
||||
new_token.line=line;
|
||||
new_token.str=token_str;
|
||||
for(int i=0;i<TOKEN_TABLE_SIZE;++i)
|
||||
if(token_str==tok_tbl[i].str)
|
||||
{
|
||||
new_token.type=tok_tbl[i].tok_type;
|
||||
break;
|
||||
}
|
||||
token_list.push_back(new_token);
|
||||
}
|
||||
else if(IS_CALC_OPERATOR(res[ptr]))
|
||||
{
|
||||
// get calculation operator
|
||||
token_str="";
|
||||
token_str+=res[ptr];
|
||||
++ptr;
|
||||
if(ptr<res.size() && res[ptr]=='=')
|
||||
{
|
||||
token_str+=res[ptr];
|
||||
++ptr;
|
||||
}
|
||||
token new_token;
|
||||
new_token.line=line;
|
||||
new_token.str=token_str;
|
||||
for(int i=0;i<TOKEN_TABLE_SIZE;++i)
|
||||
if(token_str==tok_tbl[i].str)
|
||||
{
|
||||
new_token.type=tok_tbl[i].tok_type;
|
||||
break;
|
||||
}
|
||||
token_list.push_back(new_token);
|
||||
}
|
||||
else if(IS_NOTE_HEAD(res[ptr]))
|
||||
{
|
||||
// avoid note
|
||||
while(ptr<res_size && res[ptr]!='\n') ++ptr;
|
||||
// after this process ptr will point to a '\n'
|
||||
// don't ++ptr then the counter for line can work correctly
|
||||
}
|
||||
else
|
||||
{
|
||||
++error;
|
||||
std::cout<<">> [lexer] line "<<line<<": unknown char "<<(int)res[ptr]<<'.'<<std::endl;
|
||||
++ptr;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_lexer::print_token()
|
||||
{
|
||||
int size=token_list.size();
|
||||
for(int i=0;i<size;++i)
|
||||
std::cout<<"("<<token_list[i].line<<" | "<<token_list[i].str<<")\n";
|
||||
return;
|
||||
}
|
||||
|
||||
int nasal_lexer::get_error()
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
std::vector<token>& nasal_lexer::get_token_list()
|
||||
{
|
||||
return token_list;
|
||||
}
|
||||
#endif
|
|
@ -1,258 +1,258 @@
|
|||
#ifndef __NASAL_MISC_H__
|
||||
#define __NASAL_MISC_H__
|
||||
|
||||
/*
|
||||
check_numerable_string:
|
||||
check if a string can be converted to a number
|
||||
|
||||
strings like these below is correct:
|
||||
'0.00012'
|
||||
'12314.234'
|
||||
'1234'
|
||||
'0xdeadbeef'
|
||||
'0xDEADBEEF'
|
||||
'0o71230'
|
||||
'1e23'
|
||||
'1E-123'
|
||||
'1.34E10'
|
||||
*/
|
||||
inline bool check_hex_string(std::string str,int len)
|
||||
{
|
||||
for(int i=2;i<len;++i)
|
||||
if(!(('0'<=str[i] && str[i]<='9') || ('a'<=str[i] && str[i]<='f') || ('A'<=str[i] && str[i]<='F')))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
inline bool check_oct_string(std::string str,int len)
|
||||
{
|
||||
for(int i=2;i<len;++i)
|
||||
if(str[i]<'0' || str[i]>'7')
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
inline bool check_dec_string(std::string str,int len)
|
||||
{
|
||||
int i=0;
|
||||
// check integer part
|
||||
while('0'<=str[i] && str[i]<='9' && i<len) ++i;
|
||||
if(i==len) return true;
|
||||
if(str[i]!='e' && str[i]!='E' && str[i]!='.') return false;
|
||||
// check decimal part
|
||||
if(str[i]=='.')
|
||||
{
|
||||
++i;
|
||||
if(i==len) return false;
|
||||
while('0'<=str[i] && str[i]<='9' && i<len) ++i;
|
||||
}
|
||||
if(i==len) return true;
|
||||
if(str[i]!='e' && str[i]!='E') return false;
|
||||
// check scientific notation
|
||||
if(str[i]=='e' || str[i]=='E')
|
||||
{
|
||||
++i;
|
||||
if(i==len) return false;
|
||||
if(str[i]=='-' || str[i]=='+')
|
||||
{
|
||||
++i;
|
||||
if(i==len) return false;
|
||||
}
|
||||
for(;i<len;++i)
|
||||
if(str[i]<'0' || str[i]>'9')
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool check_numerable_string(std::string str)
|
||||
{
|
||||
int len=str.length();
|
||||
if(!len) return false;
|
||||
if(str[0]=='-' || str[0]=='+')
|
||||
{
|
||||
if(len==1) return false;
|
||||
std::string tmp="";
|
||||
for(int i=1;i<len;++i)
|
||||
tmp+=str[i];
|
||||
str=tmp;
|
||||
--len;
|
||||
}
|
||||
if(len>2 && str[0]=='0' && str[1]=='x')
|
||||
return check_hex_string(str,len);
|
||||
else if(len>2 && str[0]=='0' && str[1]=='o')
|
||||
return check_oct_string(str,len);
|
||||
else if('0'<=str[0] && str[0]<='9')
|
||||
return check_dec_string(str,len);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
trans_string_to_number:
|
||||
convert string to number
|
||||
*/
|
||||
inline double hex_to_double(std::string str,int len)
|
||||
{
|
||||
double ret=0,num_pow=1;
|
||||
for(int i=len-1;i>1;--i)
|
||||
{
|
||||
if('0'<=str[i] && str[i]<='9')
|
||||
ret+=num_pow*(str[i]-'0');
|
||||
else if('a'<=str[i] && str[i]<='f')
|
||||
ret+=num_pow*(str[i]-'a'+10);
|
||||
else if('A'<=str[i] && str[i]<='F')
|
||||
ret+=num_pow*(str[i]-'A'+10);
|
||||
num_pow*=16;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
inline double oct_to_double(std::string str,int len)
|
||||
{
|
||||
double ret=0,num_pow=1;
|
||||
for(int i=len-1;i>1;--i)
|
||||
{
|
||||
ret+=num_pow*(str[i]-'0');
|
||||
num_pow*=8;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
inline double dec_to_double(std::string str,int len)
|
||||
{
|
||||
double ret=0;
|
||||
int i=0;
|
||||
while('0'<=str[i] && str[i]<='9' && i<len)
|
||||
{
|
||||
ret=ret*10+(str[i]-'0');
|
||||
++i;
|
||||
}
|
||||
if(i==len) return ret;
|
||||
if(str[i]=='.')
|
||||
{
|
||||
++i;
|
||||
double num_pow=0.1;
|
||||
while('0'<=str[i] && str[i]<='9' && i<len)
|
||||
{
|
||||
ret+=num_pow*(str[i]-'0');
|
||||
num_pow*=0.1;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
if(i==len) return ret;
|
||||
if(str[i]=='e' || str[i]=='E')
|
||||
{
|
||||
++i;
|
||||
bool is_negative=(str[i]=='-');
|
||||
if(str[i]=='-' || str[i]=='+') ++i;
|
||||
double num_pow=0;
|
||||
for(;i<len;++i) num_pow=num_pow*10+(str[i]-'0');
|
||||
num_pow=std::pow(10,is_negative?-num_pow:num_pow);
|
||||
ret*=num_pow;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
double trans_string_to_number(std::string str)
|
||||
{
|
||||
bool is_negative=false;
|
||||
int len=str.length();
|
||||
double ret_num=0;
|
||||
if(!len) return 0;
|
||||
if(str[0]=='-' || str[0]=='+')
|
||||
{
|
||||
is_negative=(str[0]=='-');
|
||||
std::string tmp="";
|
||||
for(int i=1;i<len;++i)
|
||||
tmp.push_back(str[i]);
|
||||
str=tmp;
|
||||
--len;
|
||||
}
|
||||
if(len>2 && str[0]=='0' && str[1]=='x')
|
||||
ret_num=hex_to_double(str,len);
|
||||
else if(len>2 && str[0]=='0' && str[1]=='o')
|
||||
ret_num=oct_to_double(str,len);
|
||||
else if('0'<=str[0] && str[0]<='9')
|
||||
ret_num=dec_to_double(str,len);
|
||||
return is_negative?-ret_num:ret_num;
|
||||
}
|
||||
|
||||
/*
|
||||
trans_number_to_string:
|
||||
convert number to string
|
||||
*/
|
||||
std::string trans_number_to_string(double number)
|
||||
{
|
||||
std::string trans_num_string="";
|
||||
if(number<0)
|
||||
{
|
||||
trans_num_string+='-';
|
||||
number=-number;
|
||||
}
|
||||
if(number==0)
|
||||
return "0";
|
||||
double integer_bit=1;
|
||||
while(number>=integer_bit)
|
||||
integer_bit*=10;
|
||||
integer_bit/=10;
|
||||
if(integer_bit==0.1)
|
||||
trans_num_string+='0';
|
||||
while(integer_bit!=0.1)
|
||||
{
|
||||
trans_num_string+=(char)('0'+(int(number/integer_bit)));
|
||||
number-=(double)(int(number/integer_bit))*integer_bit;
|
||||
integer_bit/=10;
|
||||
}
|
||||
if(number!=0)
|
||||
trans_num_string+='.';
|
||||
while(number!=0)
|
||||
{
|
||||
trans_num_string+=(char)('0'+int(number*10));
|
||||
number*=10;
|
||||
number-=(double)(int(number));
|
||||
}
|
||||
return trans_num_string;
|
||||
}
|
||||
|
||||
/*
|
||||
prt_hex:
|
||||
transform int to hex format and print it out (std::cout)
|
||||
*/
|
||||
void prt_hex(const int ptr)
|
||||
{
|
||||
char hex[9];
|
||||
hex[8]=0;
|
||||
int tmp_plc=ptr;
|
||||
if(tmp_plc<0)
|
||||
{
|
||||
tmp_plc=-tmp_plc;
|
||||
std::cout<<"-0x";
|
||||
}
|
||||
else
|
||||
std::cout<<"0x";
|
||||
/*
|
||||
int: 00000000 00000000 00000000 00000000
|
||||
int: 0x00 00 00 00
|
||||
example:
|
||||
a=0x13 57 9b df
|
||||
a=00010011 01010111 10011011 11011111
|
||||
a & 0x00 00 00 0f:
|
||||
00010011 01010111 10011011 11011111
|
||||
and 00000000 00000000 00000000 00001111
|
||||
---------------------------------------
|
||||
00000000 00000000 00000000 00001111
|
||||
a>>=4:
|
||||
00000001 00110101 01111001 10111101
|
||||
a & 0x00 00 00 0f
|
||||
00000001 00110101 01111001 10111101
|
||||
and 00000000 00000000 00000000 00001111
|
||||
---------------------------------------
|
||||
00000000 00000000 00000000 00001101
|
||||
then convert 0~15 to 0~9 a~f
|
||||
*/
|
||||
for(int j=7;j>=0;--j)
|
||||
{
|
||||
int tmp=(tmp_plc & 0x0000000f);
|
||||
hex[j]=tmp<10? (char)('0'+tmp):(char)('a'+tmp-10);
|
||||
tmp_plc>>=4;
|
||||
}
|
||||
std::cout<<hex;
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
#ifndef __NASAL_MISC_H__
|
||||
#define __NASAL_MISC_H__
|
||||
|
||||
/*
|
||||
check_numerable_string:
|
||||
check if a string can be converted to a number
|
||||
|
||||
strings like these below is correct:
|
||||
'0.00012'
|
||||
'12314.234'
|
||||
'1234'
|
||||
'0xdeadbeef'
|
||||
'0xDEADBEEF'
|
||||
'0o71230'
|
||||
'1e23'
|
||||
'1E-123'
|
||||
'1.34E10'
|
||||
*/
|
||||
inline bool check_hex_string(std::string str,int len)
|
||||
{
|
||||
for(int i=2;i<len;++i)
|
||||
if(!(('0'<=str[i] && str[i]<='9') || ('a'<=str[i] && str[i]<='f') || ('A'<=str[i] && str[i]<='F')))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
inline bool check_oct_string(std::string str,int len)
|
||||
{
|
||||
for(int i=2;i<len;++i)
|
||||
if(str[i]<'0' || str[i]>'7')
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
inline bool check_dec_string(std::string str,int len)
|
||||
{
|
||||
int i=0;
|
||||
// check integer part
|
||||
while('0'<=str[i] && str[i]<='9' && i<len) ++i;
|
||||
if(i==len) return true;
|
||||
if(str[i]!='e' && str[i]!='E' && str[i]!='.') return false;
|
||||
// check decimal part
|
||||
if(str[i]=='.')
|
||||
{
|
||||
++i;
|
||||
if(i==len) return false;
|
||||
while('0'<=str[i] && str[i]<='9' && i<len) ++i;
|
||||
}
|
||||
if(i==len) return true;
|
||||
if(str[i]!='e' && str[i]!='E') return false;
|
||||
// check scientific notation
|
||||
if(str[i]=='e' || str[i]=='E')
|
||||
{
|
||||
++i;
|
||||
if(i==len) return false;
|
||||
if(str[i]=='-' || str[i]=='+')
|
||||
{
|
||||
++i;
|
||||
if(i==len) return false;
|
||||
}
|
||||
for(;i<len;++i)
|
||||
if(str[i]<'0' || str[i]>'9')
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool check_numerable_string(std::string str)
|
||||
{
|
||||
int len=str.length();
|
||||
if(!len) return false;
|
||||
if(str[0]=='-' || str[0]=='+')
|
||||
{
|
||||
if(len==1) return false;
|
||||
std::string tmp="";
|
||||
for(int i=1;i<len;++i)
|
||||
tmp+=str[i];
|
||||
str=tmp;
|
||||
--len;
|
||||
}
|
||||
if(len>2 && str[0]=='0' && str[1]=='x')
|
||||
return check_hex_string(str,len);
|
||||
else if(len>2 && str[0]=='0' && str[1]=='o')
|
||||
return check_oct_string(str,len);
|
||||
else if('0'<=str[0] && str[0]<='9')
|
||||
return check_dec_string(str,len);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
trans_string_to_number:
|
||||
convert string to number
|
||||
*/
|
||||
inline double hex_to_double(std::string str,int len)
|
||||
{
|
||||
double ret=0,num_pow=1;
|
||||
for(int i=len-1;i>1;--i)
|
||||
{
|
||||
if('0'<=str[i] && str[i]<='9')
|
||||
ret+=num_pow*(str[i]-'0');
|
||||
else if('a'<=str[i] && str[i]<='f')
|
||||
ret+=num_pow*(str[i]-'a'+10);
|
||||
else if('A'<=str[i] && str[i]<='F')
|
||||
ret+=num_pow*(str[i]-'A'+10);
|
||||
num_pow*=16;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
inline double oct_to_double(std::string str,int len)
|
||||
{
|
||||
double ret=0,num_pow=1;
|
||||
for(int i=len-1;i>1;--i)
|
||||
{
|
||||
ret+=num_pow*(str[i]-'0');
|
||||
num_pow*=8;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
inline double dec_to_double(std::string str,int len)
|
||||
{
|
||||
double ret=0;
|
||||
int i=0;
|
||||
while('0'<=str[i] && str[i]<='9' && i<len)
|
||||
{
|
||||
ret=ret*10+(str[i]-'0');
|
||||
++i;
|
||||
}
|
||||
if(i==len) return ret;
|
||||
if(str[i]=='.')
|
||||
{
|
||||
++i;
|
||||
double num_pow=0.1;
|
||||
while('0'<=str[i] && str[i]<='9' && i<len)
|
||||
{
|
||||
ret+=num_pow*(str[i]-'0');
|
||||
num_pow*=0.1;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
if(i==len) return ret;
|
||||
if(str[i]=='e' || str[i]=='E')
|
||||
{
|
||||
++i;
|
||||
bool is_negative=(str[i]=='-');
|
||||
if(str[i]=='-' || str[i]=='+') ++i;
|
||||
double num_pow=0;
|
||||
for(;i<len;++i) num_pow=num_pow*10+(str[i]-'0');
|
||||
num_pow=std::pow(10,is_negative?-num_pow:num_pow);
|
||||
ret*=num_pow;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
double trans_string_to_number(std::string str)
|
||||
{
|
||||
bool is_negative=false;
|
||||
int len=str.length();
|
||||
double ret_num=0;
|
||||
if(!len) return 0;
|
||||
if(str[0]=='-' || str[0]=='+')
|
||||
{
|
||||
is_negative=(str[0]=='-');
|
||||
std::string tmp="";
|
||||
for(int i=1;i<len;++i)
|
||||
tmp.push_back(str[i]);
|
||||
str=tmp;
|
||||
--len;
|
||||
}
|
||||
if(len>2 && str[0]=='0' && str[1]=='x')
|
||||
ret_num=hex_to_double(str,len);
|
||||
else if(len>2 && str[0]=='0' && str[1]=='o')
|
||||
ret_num=oct_to_double(str,len);
|
||||
else if('0'<=str[0] && str[0]<='9')
|
||||
ret_num=dec_to_double(str,len);
|
||||
return is_negative?-ret_num:ret_num;
|
||||
}
|
||||
|
||||
/*
|
||||
trans_number_to_string:
|
||||
convert number to string
|
||||
*/
|
||||
std::string trans_number_to_string(double number)
|
||||
{
|
||||
std::string trans_num_string="";
|
||||
if(number<0)
|
||||
{
|
||||
trans_num_string+='-';
|
||||
number=-number;
|
||||
}
|
||||
if(number==0)
|
||||
return "0";
|
||||
double integer_bit=1;
|
||||
while(number>=integer_bit)
|
||||
integer_bit*=10;
|
||||
integer_bit/=10;
|
||||
if(integer_bit==0.1)
|
||||
trans_num_string+='0';
|
||||
while(integer_bit!=0.1)
|
||||
{
|
||||
trans_num_string+=(char)('0'+(int(number/integer_bit)));
|
||||
number-=(double)(int(number/integer_bit))*integer_bit;
|
||||
integer_bit/=10;
|
||||
}
|
||||
if(number!=0)
|
||||
trans_num_string+='.';
|
||||
while(number!=0)
|
||||
{
|
||||
trans_num_string+=(char)('0'+int(number*10));
|
||||
number*=10;
|
||||
number-=(double)(int(number));
|
||||
}
|
||||
return trans_num_string;
|
||||
}
|
||||
|
||||
/*
|
||||
prt_hex:
|
||||
transform int to hex format and print it out (std::cout)
|
||||
*/
|
||||
void prt_hex(const int ptr)
|
||||
{
|
||||
char hex[9];
|
||||
hex[8]=0;
|
||||
int tmp_plc=ptr;
|
||||
if(tmp_plc<0)
|
||||
{
|
||||
tmp_plc=-tmp_plc;
|
||||
std::cout<<"-0x";
|
||||
}
|
||||
else
|
||||
std::cout<<"0x";
|
||||
/*
|
||||
int: 00000000 00000000 00000000 00000000
|
||||
int: 0x00 00 00 00
|
||||
example:
|
||||
a=0x13 57 9b df
|
||||
a=00010011 01010111 10011011 11011111
|
||||
a & 0x00 00 00 0f:
|
||||
00010011 01010111 10011011 11011111
|
||||
and 00000000 00000000 00000000 00001111
|
||||
---------------------------------------
|
||||
00000000 00000000 00000000 00001111
|
||||
a>>=4:
|
||||
00000001 00110101 01111001 10111101
|
||||
a & 0x00 00 00 0f
|
||||
00000001 00110101 01111001 10111101
|
||||
and 00000000 00000000 00000000 00001111
|
||||
---------------------------------------
|
||||
00000000 00000000 00000000 00001101
|
||||
then convert 0~15 to 0~9 a~f
|
||||
*/
|
||||
for(int j=7;j>=0;--j)
|
||||
{
|
||||
int tmp=(tmp_plc & 0x0000000f);
|
||||
hex[j]=tmp<10? (char)('0'+tmp):(char)('a'+tmp-10);
|
||||
tmp_plc>>=4;
|
||||
}
|
||||
std::cout<<hex;
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -1,75 +1,75 @@
|
|||
#ifndef __NASAL_RESOURCE_H__
|
||||
#define __NASAL_RESOURCE_H__
|
||||
|
||||
class nasal_resource
|
||||
{
|
||||
private:
|
||||
std::vector<char> res;
|
||||
public:
|
||||
bool input_file(std::string);
|
||||
void clear();
|
||||
void print_file();
|
||||
std::vector<char>& get_file();
|
||||
};
|
||||
|
||||
bool nasal_resource::input_file(std::string filename)
|
||||
{
|
||||
res.clear();
|
||||
std::ifstream fin(filename,std::ios::binary);
|
||||
if(fin.fail())
|
||||
{
|
||||
std::cout<<">> [resource] cannot open file \""<<filename<<"\".\n";
|
||||
fin.close();
|
||||
return false;
|
||||
}
|
||||
while(!fin.eof())
|
||||
{
|
||||
char c=fin.get();
|
||||
if(fin.eof())
|
||||
break;
|
||||
res.push_back(c);
|
||||
}
|
||||
fin.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
void nasal_resource::clear()
|
||||
{
|
||||
res.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_resource::print_file()
|
||||
{
|
||||
int size=res.size(),line=1;
|
||||
std::cout<<line<<"\t";
|
||||
std::string unicode_str="";
|
||||
for(int i=0;i<size;++i)
|
||||
{
|
||||
if(res[i]>=0 && unicode_str.length())
|
||||
{
|
||||
std::cout<<unicode_str;
|
||||
unicode_str="";
|
||||
}
|
||||
if(32<=res[i])
|
||||
std::cout<<res[i];
|
||||
else if(res[i]<0)
|
||||
unicode_str+=res[i];
|
||||
else
|
||||
std::cout<<" ";
|
||||
if(res[i]=='\n')
|
||||
{
|
||||
++line;
|
||||
std::cout<<std::endl<<line<<"\t";
|
||||
}
|
||||
}
|
||||
std::cout<<(unicode_str.length()?unicode_str:"")<<'\n';
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<char>& nasal_resource::get_file()
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifndef __NASAL_RESOURCE_H__
|
||||
#define __NASAL_RESOURCE_H__
|
||||
|
||||
class nasal_resource
|
||||
{
|
||||
private:
|
||||
std::vector<char> res;
|
||||
public:
|
||||
bool input_file(std::string);
|
||||
void clear();
|
||||
void print_file();
|
||||
std::vector<char>& get_file();
|
||||
};
|
||||
|
||||
bool nasal_resource::input_file(std::string filename)
|
||||
{
|
||||
res.clear();
|
||||
std::ifstream fin(filename,std::ios::binary);
|
||||
if(fin.fail())
|
||||
{
|
||||
std::cout<<">> [resource] cannot open file \""<<filename<<"\".\n";
|
||||
fin.close();
|
||||
return false;
|
||||
}
|
||||
while(!fin.eof())
|
||||
{
|
||||
char c=fin.get();
|
||||
if(fin.eof())
|
||||
break;
|
||||
res.push_back(c);
|
||||
}
|
||||
fin.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
void nasal_resource::clear()
|
||||
{
|
||||
res.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_resource::print_file()
|
||||
{
|
||||
int size=res.size(),line=1;
|
||||
std::cout<<line<<"\t";
|
||||
std::string unicode_str="";
|
||||
for(int i=0;i<size;++i)
|
||||
{
|
||||
if(res[i]>=0 && unicode_str.length())
|
||||
{
|
||||
std::cout<<unicode_str;
|
||||
unicode_str="";
|
||||
}
|
||||
if(32<=res[i])
|
||||
std::cout<<res[i];
|
||||
else if(res[i]<0)
|
||||
unicode_str+=res[i];
|
||||
else
|
||||
std::cout<<" ";
|
||||
if(res[i]=='\n')
|
||||
{
|
||||
++line;
|
||||
std::cout<<std::endl<<line<<"\t";
|
||||
}
|
||||
}
|
||||
std::cout<<(unicode_str.length()?unicode_str:"")<<'\n';
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<char>& nasal_resource::get_file()
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
BIN
pic/icon.png
BIN
pic/icon.png
Binary file not shown.
Before Width: | Height: | Size: 5.3 KiB |
|
@ -0,0 +1,335 @@
|
|||
import("lib.nas");
|
||||
var activate_function=
|
||||
{
|
||||
sigmoid_func:func(x)
|
||||
{
|
||||
return 1.0/(1.0+math.exp(-x));
|
||||
},
|
||||
diffsigmoid_func:func(x)
|
||||
{
|
||||
var t=func(x){return 1.0/(1.0+math.exp(-x));}(x);
|
||||
return t*(1-t);
|
||||
},
|
||||
tanh_func:func(x)
|
||||
{
|
||||
var t1=math.exp(x);
|
||||
var t2=math.exp(-x);
|
||||
return (t1-t2)/(t1+t2);
|
||||
},
|
||||
difftanh_func:func(x)
|
||||
{
|
||||
var t1=math.exp(x);
|
||||
var t2=math.exp(-x);
|
||||
var t=(t1-t2)/(t1+t2);
|
||||
return 1-t*t;
|
||||
},
|
||||
relu_func:func(x)
|
||||
{
|
||||
return x>0? x:0;
|
||||
},
|
||||
diffrelu_func:func(x)
|
||||
{
|
||||
return x>0;
|
||||
},
|
||||
leaky_relu_func:func(k,x)
|
||||
{
|
||||
return x>0? x:k*x;
|
||||
},
|
||||
diffleaky_relu_func:func(k,x)
|
||||
{
|
||||
return x>0? 1:k;
|
||||
}
|
||||
};
|
||||
|
||||
var matrix=
|
||||
{
|
||||
new:func(col,row)
|
||||
{
|
||||
var new_mat=
|
||||
{
|
||||
col:col,
|
||||
row:row,
|
||||
mat:[]
|
||||
};
|
||||
for(var i=0;i<row;i+=1)
|
||||
{
|
||||
append(new_mat.mat,[]);
|
||||
for(var j=0;j<col;j+=1)
|
||||
append(new_mat.mat[i],nil);
|
||||
}
|
||||
return new_mat;
|
||||
},
|
||||
srand:func(x)
|
||||
{
|
||||
rand(x);
|
||||
return nil;
|
||||
},
|
||||
rand_init:func(mat)
|
||||
{
|
||||
for(var i=0;i<mat.row;i+=1)
|
||||
for(var j=0;j<mat.col;j+=1)
|
||||
{
|
||||
if(rand()>0.5)
|
||||
mat.mat[i][j]=-rand();
|
||||
else
|
||||
mat.mat[i][j]=rand();
|
||||
}
|
||||
return;
|
||||
},
|
||||
prt_mat:func(mat)
|
||||
{
|
||||
var prt_s='[\n';
|
||||
foreach(var i;mat.mat)
|
||||
{
|
||||
var s='[';
|
||||
foreach(var j;i)
|
||||
s~=(j~',');
|
||||
s~='],\n';
|
||||
prt_s~=s;
|
||||
}
|
||||
prt_s~=']';
|
||||
print(prt_s);
|
||||
return nil;
|
||||
},
|
||||
mult_mat:func(mat1,mat2)
|
||||
{
|
||||
if(mat1.col!=mat2.row)
|
||||
{
|
||||
die("[error-mult] mat1\'s col does not match mat2\'s row.");
|
||||
return nil;
|
||||
}
|
||||
var new_mat=me.new(mat2.col,mat1.row);
|
||||
for(var i=0;i<new_mat.row;i+=1)
|
||||
for(var j=0;j<new_mat.col;j+=1)
|
||||
{
|
||||
var sum=0;
|
||||
for(var k=0;k<mat1.col;k+=1)
|
||||
sum+=mat1.mat[i][k]*mat2.mat[k][j];
|
||||
new_mat.mat[i][j]=sum;
|
||||
}
|
||||
return new_mat;
|
||||
},
|
||||
add_mat:func(mat1,mat2)
|
||||
{
|
||||
if(mat1.col!=mat2.col or mat1.row!=mat2.row)
|
||||
{
|
||||
die("[error-add] mat1\'s col or row does not match mat2\'s.");
|
||||
return nil;
|
||||
}
|
||||
var new_mat=me.new(mat1.col,mat1.row);
|
||||
for(var i=0;i<new_mat.row;i+=1)
|
||||
for(var j=0;j<new_mat.col;j+=1)
|
||||
new_mat.mat[i][j]=mat1.mat[i][j]+mat2.mat[i][j];
|
||||
return new_mat;
|
||||
},
|
||||
sub_mat:func(mat1,mat2)
|
||||
{
|
||||
if(mat1.col!=mat2.col or mat1.row!=mat2.row)
|
||||
{
|
||||
die("[error-sub] mat1\'s col or row does not match mat2\'s.");
|
||||
return nil;
|
||||
}
|
||||
var new_mat=me.new(mat1.col,mat1.row);
|
||||
for(var i=0;i<new_mat.row;i+=1)
|
||||
for(var j=0;j<new_mat.col;j+=1)
|
||||
new_mat.mat[i][j]=mat1.mat[i][j]-mat2.mat[i][j];
|
||||
return new_mat;
|
||||
},
|
||||
hadamard:func(mat1,mat2)
|
||||
{
|
||||
if(mat1.col!=mat2.col or mat1.row!=mat2.row)
|
||||
{
|
||||
die("[error-hadamard] mat1\'s col or row does not match mat2\'s.");
|
||||
return nil;
|
||||
}
|
||||
var new_mat=me.new(mat1.col,mat1.row);
|
||||
for(var i=0;i<new_mat.row;i+=1)
|
||||
for(var j=0;j<new_mat.col;j+=1)
|
||||
new_mat.mat[i][j]=mat1.mat[i][j]*mat2.mat[i][j];
|
||||
return new_mat;
|
||||
},
|
||||
transpose:func(mat)
|
||||
{
|
||||
var new_mat=me.new(mat.row,mat.col);
|
||||
for(var i=0;i<new_mat.row;i+=1)
|
||||
for(var j=0;j<new_mat.col;j+=1)
|
||||
new_mat.mat[i][j]=mat.mat[j][i];
|
||||
return new_mat;
|
||||
},
|
||||
sigmoid:func(mat)
|
||||
{
|
||||
var new_mat=me.new(mat.col,mat.row);
|
||||
for(var i=0;i<new_mat.row;i+=1)
|
||||
for(var j=0;j<new_mat.col;j+=1)
|
||||
new_mat.mat[i][j]=activate_function.sigmoid_func(mat.mat[i][j]);
|
||||
return new_mat;
|
||||
},
|
||||
diffsigmoid:func(mat)
|
||||
{
|
||||
var new_mat=me.new(mat.col,mat.row);
|
||||
for(var i=0;i<new_mat.row;i+=1)
|
||||
for(var j=0;j<new_mat.col;j+=1)
|
||||
new_mat.mat[i][j]=activate_function.diffsigmoid_func(mat.mat[i][j]);
|
||||
return new_mat;
|
||||
},
|
||||
tanh:func(mat)
|
||||
{
|
||||
var new_mat=me.new(mat.col,mat.row);
|
||||
for(var i=0;i<new_mat.row;i+=1)
|
||||
for(var j=0;j<new_mat.col;j+=1)
|
||||
new_mat.mat[i][j]=activate_function.tanh_func(mat.mat[i][j]);
|
||||
return new_mat;
|
||||
},
|
||||
difftanh:func(mat)
|
||||
{
|
||||
var new_mat=me.new(mat.col,mat.row);
|
||||
for(var i=0;i<new_mat.row;i+=1)
|
||||
for(var j=0;j<new_mat.col;j+=1)
|
||||
new_mat.mat[i][j]=activate_function.difftanh_func(mat.mat[i][j]);
|
||||
return new_mat;
|
||||
},
|
||||
relu:func(mat)
|
||||
{
|
||||
var new_mat=me.new(mat.col,mat.row);
|
||||
for(var i=0;i<new_mat.row;i+=1)
|
||||
for(var j=0;j<new_mat.col;j+=1)
|
||||
new_mat.mat[i][j]=activate_function.relu_func(mat.mat[i][j]);
|
||||
return new_mat;
|
||||
},
|
||||
diffrelu:func(mat)
|
||||
{
|
||||
var new_mat=me.new(mat.col,mat.row);
|
||||
for(var i=0;i<new_mat.row;i+=1)
|
||||
for(var j=0;j<new_mat.col;j+=1)
|
||||
new_mat.mat[i][j]=activate_function.diffrelu_func(mat.mat[i][j]);
|
||||
return new_mat;
|
||||
},
|
||||
leaky_relu:func(k,mat)
|
||||
{
|
||||
var new_mat=me.new(mat.col,mat.row);
|
||||
for(var i=0;i<new_mat.row;i+=1)
|
||||
for(var j=0;j<new_mat.col;j+=1)
|
||||
new_mat.mat[i][j]=activate_function.leaky_relu_func(k,mat.mat[i][j]);
|
||||
return new_mat;
|
||||
},
|
||||
diffleaky_relu:func(k,mat)
|
||||
{
|
||||
var new_mat=me.new(mat.col,mat.row);
|
||||
for(var i=0;i<new_mat.row;i+=1)
|
||||
for(var j=0;j<new_mat.col;j+=1)
|
||||
new_mat.mat[i][j]=activate_function.diffleaky_relu_func(k,mat.mat[i][j]);
|
||||
return new_mat;
|
||||
}
|
||||
};
|
||||
|
||||
var bp=
|
||||
{
|
||||
inum:2,
|
||||
hnum:4,
|
||||
onum:1,
|
||||
learning_rate:nil,
|
||||
hidden_layer:nil,
|
||||
hidden_res:nil,
|
||||
output_layer:nil,
|
||||
output_res:nil,
|
||||
result:nil,
|
||||
training_set:[],
|
||||
expect_set:[],
|
||||
init:func()
|
||||
{
|
||||
matrix.srand(time(0));
|
||||
me.hidden_layer=matrix.new(me.hnum,me.inum);
|
||||
matrix.rand_init(me.hidden_layer);
|
||||
me.output_layer=matrix.new(me.onum,me.hnum);
|
||||
matrix.rand_init(me.output_layer);
|
||||
return;
|
||||
},
|
||||
set_learning_rate:func(lr)
|
||||
{
|
||||
me.learning_rate=matrix.new(me.onum,1);
|
||||
for(var i=0;i<me.onum;i+=1)
|
||||
me.learning_rate.mat[i][0]=lr;
|
||||
return;
|
||||
},
|
||||
set_training_set:func()
|
||||
{
|
||||
for(var i=0;i<4;i+=1)
|
||||
append(me.training_set,matrix.new(me.inum,1));
|
||||
me.training_set[0].mat[0][0]=0;
|
||||
me.training_set[0].mat[0][1]=0;
|
||||
me.training_set[1].mat[0][0]=0;
|
||||
me.training_set[1].mat[0][1]=1;
|
||||
me.training_set[2].mat[0][0]=1;
|
||||
me.training_set[2].mat[0][1]=0;
|
||||
me.training_set[3].mat[0][0]=1;
|
||||
me.training_set[3].mat[0][1]=1;
|
||||
return;
|
||||
},
|
||||
set_expect_set:func()
|
||||
{
|
||||
for(var i=0;i<4;i+=1)
|
||||
append(me.expect_set,matrix.new(me.onum,1))
|
||||
me.expect_set[0].mat[0][0]=0;
|
||||
me.expect_set[1].mat[0][0]=1;
|
||||
me.expect_set[2].mat[0][0]=1;
|
||||
me.expect_set[3].mat[0][0]=0;
|
||||
return;
|
||||
},
|
||||
forward:func(i)
|
||||
{
|
||||
var tmp=nil;
|
||||
me.hidden_res=matrix.mult_mat(me.training_set[i],me.hidden_layer);
|
||||
tmp=matrix.sigmoid(me.hidden_res);
|
||||
me.output_res=matrix.mult_mat(tmp,me.output_layer);
|
||||
tmp=matrix.sigmoid(me.output_res);
|
||||
me.result=tmp;
|
||||
return;
|
||||
},
|
||||
backward:func(i)
|
||||
{
|
||||
var output_diff=matrix.sub_mat(me.expect_set[i],me.result);
|
||||
output_diff=matrix.hadamard(output_diff,me.learning_rate);
|
||||
output_diff=matrix.hadamard(output_diff,matrix.diffsigmoid(me.output_res));
|
||||
output_diff=matrix.mult_mat(output_diff,matrix.transpose(me.output_layer));
|
||||
matrix.prt_mat(output_diff);
|
||||
var hidden_diff=matrix.mult_mat();
|
||||
matrix.prt_mat(hidden_diff);
|
||||
|
||||
output_layer=matrix.add_mat(output_layer,output_diff);
|
||||
var error=0;
|
||||
foreach(var i;tmp.mat[0])
|
||||
error+=i;
|
||||
error*=0.5;
|
||||
return error;
|
||||
},
|
||||
training_process:func()
|
||||
{
|
||||
var cnt=0;
|
||||
var error=1e8;
|
||||
while(error>0.01)
|
||||
{
|
||||
error=0;
|
||||
for(var i=0;i<4;i+=1)
|
||||
{
|
||||
me.forward(i);
|
||||
error+=me.backward(i);
|
||||
}
|
||||
print(error);
|
||||
}
|
||||
return;
|
||||
}
|
||||
};
|
||||
var main=func()
|
||||
{
|
||||
bp.init();
|
||||
bp.set_learning_rate(0.1);
|
||||
bp.set_training_set();
|
||||
bp.set_expect_set();
|
||||
bp.training_process();
|
||||
return nil;
|
||||
}
|
||||
|
||||
# var (a,b,c)=[1,2,3];
|
||||
# (a,b,c)=(b,c,a);
|
||||
# print(a,b,c);
|
||||
main();
|
|
@ -0,0 +1,135 @@
|
|||
import("lib.nas");
|
||||
var char_ttf=[
|
||||
[" "," "," "," "," "," "],
|
||||
[" ████╗"," ██╔██║"," ██╔╝██║"," ███████║","██╔═══██║","╚═╝ ╚═╝"],
|
||||
["██████╗ ","██╔══██╗","██████╔╝","██╔══██╗","██████╔╝","╚═════╝ "],
|
||||
[" ██████╗","██╔════╝","██║ ","██║ ","╚██████╗"," ╚═════╝"],
|
||||
["██████╗ ","██╔══██╗","██║ ██║","██║ ██║","██████╔╝","╚═════╝ "],
|
||||
["███████╗","██╔════╝","█████╗ ","██╔══╝ ","███████╗","╚══════╝"],
|
||||
["███████╗","██╔════╝","█████╗ ","██╔══╝ ","██║ ","╚═╝ "],
|
||||
[" █████╗ ","██╔═══╝ ","██║ ██╗ ","██║ ╚██╗","╚█████╔╝"," ╚════╝ "],
|
||||
["██╗ ██╗","██║ ██║","███████║","██╔══██║","██║ ██║","╚═╝ ╚═╝"],
|
||||
[" ██████╗"," ██╔═╝"," ██║ "," ██║ "," ██████╗"," ╚═════╝"],
|
||||
[" ██╗"," ██║"," ██║","██ ██║","╚█████╔╝"," ╚════╝ "],
|
||||
["██╗ ██╗","██║ ██╔╝","█████╔╝ ","██╔═██╗ ","██║ ██╗","╚═╝ ╚═╝"],
|
||||
["██╗ ","██║ ","██║ ","██║ ","███████╗","╚══════╝"],
|
||||
["██╗ ██╗","███╗ ███║","████████║","██╔██╔██║","██║╚═╝██║","╚═╝ ╚═╝"],
|
||||
["██╗ ██╗","███╗ ██║","█████╗██║","██╔█████║","██║ ╚███║","╚═╝ ╚══╝"],
|
||||
[" ██████╗ ","██╔═══██╗","██║ ██║","██║ ██║","╚██████╔╝"," ╚═════╝ "],
|
||||
["██████╗ ","██╔══██╗","██████╔╝","██╔═══╝ ","██║ ","╚═╝ "],
|
||||
[" ██████╗ ","██╔═══██╗","██║ ██║","██║ ██╔╝","╚████╔██╗"," ╚═══╝╚═╝"],
|
||||
["██████╗ ","██╔══██╗","██████╔╝","██╔══██╗","██║ ██║","╚═╝ ╚═╝"],
|
||||
["███████╗","██╔════╝","███████╗","╚════██║","███████║","╚══════╝"],
|
||||
["████████╗","╚══██╔══╝"," ██║ "," ██║ "," ██║ "," ╚═╝ "],
|
||||
["██╗ ██╗","██║ ██║","██║ ██║","██║ ██║","╚██████╔╝"," ╚═════╝ "],
|
||||
["██╗ ██╗","██║ ██║","██║ ██║","╚██╗ ██╔╝"," ╚████╔╝ "," ╚═══╝ "],
|
||||
["██╗ ██╗","██║██╗██║","████████║","███╔═███║","██╔╝ ╚██║","╚═╝ ╚═╝"],
|
||||
["██╗ ██╗","╚██╗██╔╝"," ╚███╔╝ "," ██╔██╗ ","██╔╝╚██╗","╚═╝ ╚═╝"],
|
||||
["██╗ ██╗","╚██╗ ██╔╝"," ╚████╔╝ "," ╚██╔╝ "," ██║ "," ╚═╝ "],
|
||||
["████████╗","╚════██╔╝"," ██╔═╝ "," ██╔═╝ ","████████╗","╚═══════╝"],
|
||||
];
|
||||
var trans_ttf=func(string)
|
||||
{
|
||||
var str=["","","","","",""];
|
||||
for(var i=0;i<size(string);i+=1)
|
||||
{
|
||||
var number=string[i];
|
||||
if(97<=number and number<=122)
|
||||
for(var j=0;j<6;j+=1)
|
||||
str[j]~=char_ttf[number-96][j];
|
||||
elsif(65<=number and number<=90)
|
||||
for(var j=0;j<6;j+=1)
|
||||
str[j]~=char_ttf[number-64][j];
|
||||
else
|
||||
for(var j=0;j<6;j+=1)
|
||||
str[j]~=char_ttf[0][j];
|
||||
}
|
||||
foreach(var i;str)
|
||||
print(i);
|
||||
return;
|
||||
}
|
||||
var curve1=func()
|
||||
{
|
||||
var shadow=["░","▒","▓","█","▀","▄","▐","▌"];
|
||||
rand(100);
|
||||
var s="";
|
||||
for(var i=0;i<25;i+=1)
|
||||
{
|
||||
for(var j=0;j<100;j+=1)
|
||||
s~=shadow[int(8*rand())];
|
||||
s~='\n';
|
||||
}
|
||||
print(s);
|
||||
}
|
||||
var curve2=func()
|
||||
{
|
||||
var table=["╚","═","╝","╔","║","╗"];
|
||||
rand(100);
|
||||
var s="";
|
||||
for(var i=0;i<25;i+=1)
|
||||
{
|
||||
for(var j=0;j<100;j+=1)
|
||||
s~=table[int(6*rand())];
|
||||
s~='\n';
|
||||
}
|
||||
print(s);
|
||||
}
|
||||
var curve3=func()
|
||||
{
|
||||
var block=["░░","▒▒","▓▓","██","▀▀","▄▄","▄▀","▀▄","▐▐","▌▌"];
|
||||
rand(100);
|
||||
var s="";
|
||||
for(var i=0;i<25;i+=1)
|
||||
{
|
||||
for(var j=0;j<50;j+=1)
|
||||
s~=block[int(10*rand())];
|
||||
s~='\n';
|
||||
}
|
||||
print(s);
|
||||
}
|
||||
var curve4=func()
|
||||
{
|
||||
var s=["","","","","",""];
|
||||
var cnt=0;
|
||||
foreach(var char;char_ttf)
|
||||
{
|
||||
cnt+=1;
|
||||
forindex(var i;char)
|
||||
s[i]~=char[i];
|
||||
if(cnt==9)
|
||||
{
|
||||
forindex(var i;s)
|
||||
{
|
||||
print(s[i]);
|
||||
s[i]='';
|
||||
}
|
||||
cnt=0;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
var curve5=func()
|
||||
{
|
||||
for(var loop=0;loop<100;loop+=1)
|
||||
{
|
||||
var arr=[0,1,2,3,4,5,6,7,8,0,1,2,3,4,5,6,7,8];
|
||||
for(var i=17;i>=0;i-=1)
|
||||
{
|
||||
var rand_index=int(i*rand());
|
||||
(arr[i],arr[rand_index])=(arr[rand_index],arr[i]);
|
||||
}
|
||||
# 0 1 2 3 4 5 6 7 8
|
||||
var shadow=[" ","░","▒","▓","█","▀","▄","▐","▌"];
|
||||
var s="";
|
||||
for(var i=0;i<size(arr);i+=1)
|
||||
s~=shadow[arr[i]];
|
||||
print(s);
|
||||
}
|
||||
return;
|
||||
}
|
||||
trans_ttf("just for test");
|
||||
curve1();
|
||||
curve2();
|
||||
curve3();
|
||||
curve4();
|
||||
curve5();
|
|
@ -1,83 +1,83 @@
|
|||
# Road check and auto pilot(??) by ValKmjolnir
|
||||
|
||||
var position_change = func(position_val,value){
|
||||
if(position_val+value>180)
|
||||
position_val += value-360;
|
||||
else if(position_val+value<-180)
|
||||
position_val += value+360;
|
||||
else
|
||||
position_val += value;
|
||||
return position_val;
|
||||
}
|
||||
var road_check_func = func(){
|
||||
|
||||
var lat = props.getNode("/position/latitude-deg",1).getValue();
|
||||
var lon = props.getNode("/position/longitude-deg",1).getValue();
|
||||
var position_info = geodinfo(lat,lon);
|
||||
var position_names = position_info[1].names;
|
||||
# the friction_factor of freeway runway and road is 1
|
||||
|
||||
if((position_names[0]=="Freeway") or (position_names[0]=="Road"))
|
||||
{
|
||||
var car_heading = 0;
|
||||
var lat_change = 0;
|
||||
var lon_change = 0;
|
||||
var left_range = 0;
|
||||
var right_range = 0;
|
||||
|
||||
for(var i=0;i>-0.00005;i-=0.000001)
|
||||
{
|
||||
car_heading = props.getNode("/orientation/heading-deg",1).getValue();
|
||||
lat_change = math.sin(math.pi*car_heading/180);
|
||||
lon_change = -math.cos(math.pi*car_heading/180);
|
||||
lat = props.getNode("/position/latitude-deg",1).getValue()+0.0001*math.cos(math.pi*car_heading/180);
|
||||
lon = props.getNode("/position/longitude-deg",1).getValue()+0.0001*math.sin(math.pi*car_heading/180);
|
||||
var other_position_info = geodinfo(position_change(lat,i*lat_change),position_change(lon,i*lon_change));
|
||||
var other_names = other_position_info[1].names;
|
||||
if((other_names[0]=="Freeway") or (other_names[0]=="Road"))
|
||||
right_range += 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
for(var i=0;i<0.00005;i+=0.000001)
|
||||
{
|
||||
car_heading = props.getNode("/orientation/heading-deg",1).getValue();
|
||||
lat_change = math.sin(math.pi*car_heading/180);
|
||||
lon_change = -math.cos(math.pi*car_heading/180);
|
||||
lat = props.getNode("/position/latitude-deg",1).getValue()+0.0001*math.cos(math.pi*car_heading/180);
|
||||
lon = props.getNode("/position/longitude-deg",1).getValue()+0.0001*math.sin(math.pi*car_heading/180);
|
||||
var other_position_info = geodinfo(position_change(lat,i*lat_change),position_change(lon,i*lon_change));
|
||||
var other_names = other_position_info[1].names;
|
||||
if((other_names[0]=="Freeway") or (other_names[0]=="Road"))
|
||||
left_range+=1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
#if(left_range>right_range)
|
||||
#{
|
||||
# setprop("/controls/flight/rudder",-(right_range-left_range)*(right_range-left_range)/10000);
|
||||
# print("right ",right_range);
|
||||
#}
|
||||
#else if(left_range<right_range)
|
||||
#{
|
||||
# setprop("/controls/flight/rudder",(right_range-left_range)*(right_range-left_range)/10000);
|
||||
# print("left ",left_range);
|
||||
#}
|
||||
#else
|
||||
# setprop("/controls/flight/rudder",0);
|
||||
props.getNode("/controls/flight/rudder",1).setValue((right_range-left_range)/200);
|
||||
}
|
||||
};
|
||||
var road_check_timer = maketimer(0.1,road_check_func);
|
||||
var toggle_auto_pilot = func(){
|
||||
if(!road_check_timer.isRunning)
|
||||
{
|
||||
road_check_timer.start();
|
||||
props.getNode("/sim/messages/copilot",1).setValue("ze dong sheng teaan see tong yee tse yung. Auto Sheng Teaan System Activated!");
|
||||
}
|
||||
else
|
||||
{
|
||||
road_check_timer.stop();
|
||||
props.getNode("/sim/messages/copilot",1).setValue("ze dong sheng teaan see tong yee guan bee. Auto Sheng Teaan System is off.");
|
||||
}
|
||||
# Road check and auto pilot(??) by ValKmjolnir
|
||||
|
||||
var position_change = func(position_val,value){
|
||||
if(position_val+value>180)
|
||||
position_val += value-360;
|
||||
else if(position_val+value<-180)
|
||||
position_val += value+360;
|
||||
else
|
||||
position_val += value;
|
||||
return position_val;
|
||||
}
|
||||
var road_check_func = func(){
|
||||
|
||||
var lat = props.getNode("/position/latitude-deg",1).getValue();
|
||||
var lon = props.getNode("/position/longitude-deg",1).getValue();
|
||||
var position_info = geodinfo(lat,lon);
|
||||
var position_names = position_info[1].names;
|
||||
# the friction_factor of freeway runway and road is 1
|
||||
|
||||
if((position_names[0]=="Freeway") or (position_names[0]=="Road"))
|
||||
{
|
||||
var car_heading = 0;
|
||||
var lat_change = 0;
|
||||
var lon_change = 0;
|
||||
var left_range = 0;
|
||||
var right_range = 0;
|
||||
|
||||
for(var i=0;i>-0.00005;i-=0.000001)
|
||||
{
|
||||
car_heading = props.getNode("/orientation/heading-deg",1).getValue();
|
||||
lat_change = math.sin(math.pi*car_heading/180);
|
||||
lon_change = -math.cos(math.pi*car_heading/180);
|
||||
lat = props.getNode("/position/latitude-deg",1).getValue()+0.0001*math.cos(math.pi*car_heading/180);
|
||||
lon = props.getNode("/position/longitude-deg",1).getValue()+0.0001*math.sin(math.pi*car_heading/180);
|
||||
var other_position_info = geodinfo(position_change(lat,i*lat_change),position_change(lon,i*lon_change));
|
||||
var other_names = other_position_info[1].names;
|
||||
if((other_names[0]=="Freeway") or (other_names[0]=="Road"))
|
||||
right_range += 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
for(var i=0;i<0.00005;i+=0.000001)
|
||||
{
|
||||
car_heading = props.getNode("/orientation/heading-deg",1).getValue();
|
||||
lat_change = math.sin(math.pi*car_heading/180);
|
||||
lon_change = -math.cos(math.pi*car_heading/180);
|
||||
lat = props.getNode("/position/latitude-deg",1).getValue()+0.0001*math.cos(math.pi*car_heading/180);
|
||||
lon = props.getNode("/position/longitude-deg",1).getValue()+0.0001*math.sin(math.pi*car_heading/180);
|
||||
var other_position_info = geodinfo(position_change(lat,i*lat_change),position_change(lon,i*lon_change));
|
||||
var other_names = other_position_info[1].names;
|
||||
if((other_names[0]=="Freeway") or (other_names[0]=="Road"))
|
||||
left_range+=1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
#if(left_range>right_range)
|
||||
#{
|
||||
# setprop("/controls/flight/rudder",-(right_range-left_range)*(right_range-left_range)/10000);
|
||||
# print("right ",right_range);
|
||||
#}
|
||||
#else if(left_range<right_range)
|
||||
#{
|
||||
# setprop("/controls/flight/rudder",(right_range-left_range)*(right_range-left_range)/10000);
|
||||
# print("left ",left_range);
|
||||
#}
|
||||
#else
|
||||
# setprop("/controls/flight/rudder",0);
|
||||
props.getNode("/controls/flight/rudder",1).setValue((right_range-left_range)/200);
|
||||
}
|
||||
};
|
||||
var road_check_timer = maketimer(0.1,road_check_func);
|
||||
var toggle_auto_pilot = func(){
|
||||
if(!road_check_timer.isRunning)
|
||||
{
|
||||
road_check_timer.start();
|
||||
props.getNode("/sim/messages/copilot",1).setValue("ze dong sheng teaan see tong yee tse yung. Auto Sheng Teaan System Activated!");
|
||||
}
|
||||
else
|
||||
{
|
||||
road_check_timer.stop();
|
||||
props.getNode("/sim/messages/copilot",1).setValue("ze dong sheng teaan see tong yee guan bee. Auto Sheng Teaan System is off.");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
import("lib.nas");
|
||||
|
||||
rand(time(0));
|
||||
|
||||
var new_neuron=func()
|
||||
{
|
||||
var neuron={
|
||||
in:0,
|
||||
out:0,
|
||||
w:[],
|
||||
bia:0,
|
||||
diff:0
|
||||
};
|
||||
return neuron;
|
||||
}
|
||||
|
||||
var sigmoid=func(x)
|
||||
{
|
||||
return 1/(1+math.exp(-x));
|
||||
}
|
||||
var diffsigmoid=func(x)
|
||||
{
|
||||
x=sigmoid(x);
|
||||
return x*(1-x);
|
||||
}
|
||||
|
||||
var inum=2;
|
||||
var hnum=4;
|
||||
var onum=1;
|
||||
var lr=0.1;
|
||||
var training_set=[[0,0],[0,1],[1,0],[1,1]];
|
||||
var expect=[[0],[1],[1],[0]];
|
||||
|
||||
var hidden=[];
|
||||
for(var i=0;i<hnum;i+=1)
|
||||
{
|
||||
append(hidden,new_neuron());
|
||||
for(var j=0;j<inum;j+=1)
|
||||
append(hidden[i].w,2*rand());
|
||||
hidden[i].bia=5*rand();
|
||||
}
|
||||
|
||||
var output=[];
|
||||
for(var i=0;i<onum;i+=1)
|
||||
{
|
||||
append(output,new_neuron());
|
||||
for(var j=0;j<hnum;j+=1)
|
||||
append(output[i].w,2*rand());
|
||||
output[i].bia=5*rand();
|
||||
}
|
||||
|
||||
var forward=func(x)
|
||||
{
|
||||
var input=training_set[x];
|
||||
for(var i=0;i<hnum;i+=1)
|
||||
{
|
||||
hidden[i].in=hidden[i].bia;
|
||||
for(var j=0;j<inum;j+=1)
|
||||
hidden[i].in+=hidden[i].w[j]*input[j];
|
||||
hidden[i].out=sigmoid(hidden[i].in);
|
||||
}
|
||||
for(var i=0;i<onum;i+=1)
|
||||
{
|
||||
output[i].in=output[i].bia;
|
||||
for(var j=0;j<hnum;j+=1)
|
||||
output[i].in+=output[i].w[j]*hidden[j].out;
|
||||
output[i].out=sigmoid(output[i].in);
|
||||
}
|
||||
return;
|
||||
}
|
||||
var run=func(vec)
|
||||
{
|
||||
var input=vec;
|
||||
for(var i=0;i<hnum;i+=1)
|
||||
{
|
||||
hidden[i].in=hidden[i].bia;
|
||||
for(var j=0;j<inum;j+=1)
|
||||
hidden[i].in+=hidden[i].w[j]*input[j];
|
||||
hidden[i].out=sigmoid(hidden[i].in);
|
||||
}
|
||||
for(var i=0;i<onum;i+=1)
|
||||
{
|
||||
output[i].in=output[i].bia;
|
||||
for(var j=0;j<hnum;j+=1)
|
||||
output[i].in+=output[i].w[j]*hidden[j].out;
|
||||
output[i].out=sigmoid(output[i].in);
|
||||
}
|
||||
return;
|
||||
}
|
||||
var get_error=func(x)
|
||||
{
|
||||
var error=0;
|
||||
var expect_set=expect[x];
|
||||
for(var i=0;i<onum;i+=1)
|
||||
error+=(expect_set[i]-output[i].out)*(expect_set[i]-output[i].out);
|
||||
error*=0.5;
|
||||
return error;
|
||||
}
|
||||
var backward=func(x)
|
||||
{
|
||||
var input=training_set[x];
|
||||
var expect_set=expect[x];
|
||||
for(var i=0;i<onum;i+=1)
|
||||
output[i].diff=(expect_set[i]-output[i].out)*diffsigmoid(output[i].in);
|
||||
for(var i=0;i<hnum;i+=1)
|
||||
{
|
||||
hidden[i].diff=0;
|
||||
for(var j=0;j<onum;j+=1)
|
||||
hidden[i].diff+=output[j].w[i]*output[j].diff;
|
||||
hidden[i].diff*=diffsigmoid(hidden[i].in);
|
||||
}
|
||||
for(var i=0;i<hnum;i+=1)
|
||||
{
|
||||
hidden[i].bia+=hidden[i].diff;
|
||||
for(var j=0;j<inum;j+=1)
|
||||
hidden[i].w[j]+=hidden[i].diff*input[j];
|
||||
}
|
||||
for(var i=0;i<onum;i+=1)
|
||||
{
|
||||
output[i].bia+=output[i].diff;
|
||||
for(var j=0;j<hnum;j+=1)
|
||||
output[i].w[j]+=output[i].diff*hidden[j].out;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var cnt=0;
|
||||
var error=1e8;
|
||||
while(error>0.01)
|
||||
{
|
||||
error=0;
|
||||
for(var i=0;i<4;i+=1)
|
||||
{
|
||||
forward(i);
|
||||
error+=get_error(i);
|
||||
backward(i);
|
||||
}
|
||||
cnt+=1;
|
||||
print('epoch ',cnt,':',error);
|
||||
}
|
||||
print('\afinished.');
|
||||
while(1)
|
||||
{
|
||||
var vec=[];
|
||||
var command=input();
|
||||
if(command=="exit")break;
|
||||
append(vec,num(command));
|
||||
command=input();
|
||||
if(command=="exit")break;
|
||||
append(vec,num(command));
|
||||
run(vec);
|
||||
print(output[0].out);
|
||||
}
|
|
@ -1,30 +1,30 @@
|
|||
id[0] and id[1];
|
||||
1 or 2;
|
||||
"str" ==1;
|
||||
1*1/1+1;
|
||||
2*3*4/1-2+3;
|
||||
1-1+20-2*10;
|
||||
1+s1*(s2+s3[0])-1;
|
||||
var e=1+s1*(s2+s3[0])-1;
|
||||
id;
|
||||
"str";
|
||||
id(id);
|
||||
id("str",1,1);
|
||||
var e=1;
|
||||
var x=10*2-20;
|
||||
var id;
|
||||
var id=[1,2,3,4];
|
||||
var id={id:"str"};
|
||||
id();
|
||||
id.id();
|
||||
id.id.id();
|
||||
id[0].id.id(id,"str",1,2,3,4).id[10];
|
||||
id(0)[1].id;
|
||||
var hash={
|
||||
h:"hello",
|
||||
parent:[id],
|
||||
};
|
||||
function_test([1,2,3,4,55],1,2,3,{str:"str"});
|
||||
var (i,j,k,l,m,n) =[1,2,3,4,5,6];
|
||||
(var i,j,k)=[1,2,3];
|
||||
id[0] and id[1];
|
||||
1 or 2;
|
||||
"str" ==1;
|
||||
1*1/1+1;
|
||||
2*3*4/1-2+3;
|
||||
1-1+20-2*10;
|
||||
1+s1*(s2+s3[0])-1;
|
||||
var e=1+s1*(s2+s3[0])-1;
|
||||
id;
|
||||
"str";
|
||||
id(id);
|
||||
id("str",1,1);
|
||||
var e=1;
|
||||
var x=10*2-20;
|
||||
var id;
|
||||
var id=[1,2,3,4];
|
||||
var id={id:"str"};
|
||||
id();
|
||||
id.id();
|
||||
id.id.id();
|
||||
id[0].id.id(id,"str",1,2,3,4).id[10];
|
||||
id(0)[1].id;
|
||||
var hash={
|
||||
h:"hello",
|
||||
parent:[id],
|
||||
};
|
||||
function_test([1,2,3,4,55],1,2,3,{str:"str"});
|
||||
var (i,j,k,l,m,n) =[1,2,3,4,5,6];
|
||||
(var i,j,k)=[1,2,3];
|
||||
e=e[1:][0];
|
|
@ -1,38 +1,38 @@
|
|||
if(this_token.type==__if)
|
||||
{
|
||||
parse.push(this_token);
|
||||
return;
|
||||
}
|
||||
elsif(this_token.type==__elsif)
|
||||
{
|
||||
parse.push(this_token);
|
||||
return;
|
||||
}
|
||||
else if(this_token.type!=__else)
|
||||
{
|
||||
exit(0);
|
||||
}
|
||||
elsif(this_token.type==__elsif)
|
||||
{
|
||||
parse.push(this_token);
|
||||
return;
|
||||
}
|
||||
elsif(this_token.type==__elsif)
|
||||
{
|
||||
parse.push(this_token);
|
||||
return;
|
||||
}
|
||||
else if(this==(1+2+3*1))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
else
|
||||
{
|
||||
parse.push(this_token);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!id)
|
||||
{
|
||||
exit(0);
|
||||
}
|
||||
if(this_token.type==__if)
|
||||
{
|
||||
parse.push(this_token);
|
||||
return;
|
||||
}
|
||||
elsif(this_token.type==__elsif)
|
||||
{
|
||||
parse.push(this_token);
|
||||
return;
|
||||
}
|
||||
else if(this_token.type!=__else)
|
||||
{
|
||||
exit(0);
|
||||
}
|
||||
elsif(this_token.type==__elsif)
|
||||
{
|
||||
parse.push(this_token);
|
||||
return;
|
||||
}
|
||||
elsif(this_token.type==__elsif)
|
||||
{
|
||||
parse.push(this_token);
|
||||
return;
|
||||
}
|
||||
else if(this==(1+2+3*1))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
else
|
||||
{
|
||||
parse.push(this_token);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!id)
|
||||
{
|
||||
exit(0);
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
print("hello world!\n");
|
||||
print("This is the first program for nasal--\n");
|
||||
var cnt=0;
|
||||
for(var i=1;i<101;i+=1)
|
||||
cnt+=i;
|
||||
print("hello world!\n");
|
||||
print("This is the first program for nasal--\n");
|
||||
var cnt=0;
|
||||
for(var i=1;i<101;i+=1)
|
||||
cnt+=i;
|
||||
print(cnt);
|
|
@ -1,10 +1,10 @@
|
|||
var f=func(n,m,dynamic...)
|
||||
{
|
||||
print(n+m," ",dynamic);
|
||||
n=dynamic;
|
||||
m=dynamic;
|
||||
n+=m;
|
||||
return dynamic;
|
||||
};
|
||||
print(f(1,1,0,0,0,0,0,(1+2+3+(1+2+3+4)))[3]);
|
||||
var f=func(n,m,dynamic...)
|
||||
{
|
||||
print(n+m," ",dynamic);
|
||||
n=dynamic;
|
||||
m=dynamic;
|
||||
n+=m;
|
||||
return dynamic;
|
||||
};
|
||||
print(f(1,1,0,0,0,0,0,(1+2+3+(1+2+3+4)))[3]);
|
||||
function([0,1,2,3],{str:"str"});
|
|
@ -1,38 +1,38 @@
|
|||
while(n==1 )
|
||||
{
|
||||
i=i+1;
|
||||
f(i);
|
||||
print("str");
|
||||
}
|
||||
|
||||
while(n==1 and "str"==str)
|
||||
{
|
||||
print("str");
|
||||
}
|
||||
|
||||
i+=i1;
|
||||
i+=i.i[0];
|
||||
i=i.i[0].i(0);
|
||||
var hash={
|
||||
f:func {var e=1;return 0;},
|
||||
};
|
||||
for(var i=0;i<1024;i+=1)
|
||||
{
|
||||
print(i);
|
||||
}
|
||||
for(var i=0;(2*512)>=i;i+=1)
|
||||
{
|
||||
print(i);
|
||||
}
|
||||
foreach(var i;[1+(1+1),2,3,4])
|
||||
{
|
||||
print(i);
|
||||
}
|
||||
forindex(var i=list;[1,2,3,4])
|
||||
{
|
||||
print(i[0]);
|
||||
}
|
||||
while(!id)
|
||||
{
|
||||
print("yes");
|
||||
while(n==1 )
|
||||
{
|
||||
i=i+1;
|
||||
f(i);
|
||||
print("str");
|
||||
}
|
||||
|
||||
while(n==1 and "str"==str)
|
||||
{
|
||||
print("str");
|
||||
}
|
||||
|
||||
i+=i1;
|
||||
i+=i.i[0];
|
||||
i=i.i[0].i(0);
|
||||
var hash={
|
||||
f:func {var e=1;return 0;},
|
||||
};
|
||||
for(var i=0;i<1024;i+=1)
|
||||
{
|
||||
print(i);
|
||||
}
|
||||
for(var i=0;(2*512)>=i;i+=1)
|
||||
{
|
||||
print(i);
|
||||
}
|
||||
foreach(var i;[1+(1+1),2,3,4])
|
||||
{
|
||||
print(i);
|
||||
}
|
||||
forindex(var i=list;[1,2,3,4])
|
||||
{
|
||||
print(i[0]);
|
||||
}
|
||||
while(!id)
|
||||
{
|
||||
print("yes");
|
||||
}
|
189
version1.2/ast.h
189
version1.2/ast.h
|
@ -1,189 +0,0 @@
|
|||
#ifndef __NASAL_ABSTRACT_SYNTAX_TREE_RUN_H__
|
||||
#define __NASAL_ABSTRACT_SYNTAX_TREE_RUN_H__
|
||||
|
||||
class abstract_syntax_tree
|
||||
{
|
||||
private:
|
||||
int ast_node_type;
|
||||
double var_number;
|
||||
std::string var_string;
|
||||
std::string var_name;
|
||||
std::list<abstract_syntax_tree> children;
|
||||
public:
|
||||
abstract_syntax_tree()
|
||||
{
|
||||
ast_node_type=0;
|
||||
var_number=0;
|
||||
var_string="";
|
||||
var_name="";
|
||||
children.clear();
|
||||
return;
|
||||
}
|
||||
abstract_syntax_tree(const abstract_syntax_tree& p)
|
||||
{
|
||||
ast_node_type=p.ast_node_type;
|
||||
var_number=p.var_number;
|
||||
var_string=p.var_string;
|
||||
var_name=p.var_name;
|
||||
children=p.children;
|
||||
return;
|
||||
}
|
||||
abstract_syntax_tree& operator=(const abstract_syntax_tree& p)
|
||||
{
|
||||
ast_node_type=p.ast_node_type;
|
||||
var_number=p.var_number;
|
||||
var_string=p.var_string;
|
||||
var_name=p.var_name;
|
||||
children.clear();
|
||||
children=p.children;
|
||||
return *this;
|
||||
}
|
||||
void set_clear()
|
||||
{
|
||||
ast_node_type=0;
|
||||
var_number=0;
|
||||
var_string="";
|
||||
var_name="";
|
||||
children.clear();
|
||||
return;
|
||||
}
|
||||
void print_tree(const int n)
|
||||
{
|
||||
std::string str="";
|
||||
for(int i=0;i<n;++i)
|
||||
str+="| ";
|
||||
std::cout<<str;
|
||||
print_token(ast_node_type);
|
||||
switch(ast_node_type)
|
||||
{
|
||||
case __number:std::cout<<": "<<var_number;break;
|
||||
case __string:std::cout<<": "<<var_string;break;
|
||||
case __id:
|
||||
case __list_search:
|
||||
case __hash_search:
|
||||
case __call_function:std::cout<<": "<<var_name;break;
|
||||
}
|
||||
std::cout<<std::endl;
|
||||
if(!children.empty())
|
||||
{
|
||||
for(auto i=children.begin();i!=children.end();++i)
|
||||
i->print_tree(n+1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
void set_node_type(const int type)
|
||||
{
|
||||
ast_node_type=type;
|
||||
return;
|
||||
}
|
||||
void set_var_string(std::string str)
|
||||
{
|
||||
var_string=str;
|
||||
return;
|
||||
}
|
||||
void set_var_number(std::string str)
|
||||
{
|
||||
if(str=="nil")
|
||||
{
|
||||
var_number=0;
|
||||
return;
|
||||
}
|
||||
if((int)str.length()>2 && (str[1]=='x' || str[1]=='o'))
|
||||
{
|
||||
if(str[1]=='x')
|
||||
{
|
||||
int num=0;
|
||||
int pw=1;
|
||||
for(int i=(int)str.length()-1;i>1;--i)
|
||||
{
|
||||
if('0'<=str[i] && str[i]<='9')
|
||||
num+=(str[i]-'0')*pw;
|
||||
else if('a'<=str[i] && str[i]<='f')
|
||||
num+=(10+str[i]-'a')*pw;
|
||||
else if('A'<=str[i] && str[i]<='F')
|
||||
num+=(10+str[i]-'A')*pw;
|
||||
pw<<=4;
|
||||
}
|
||||
var_number=(double)num;
|
||||
}
|
||||
else
|
||||
{
|
||||
int num=0;
|
||||
int pw=1;
|
||||
for(int i=(int)str.length()-1;i>1;--i)
|
||||
{
|
||||
num+=(str[i]-'0')*pw;
|
||||
pw<<=3;
|
||||
}
|
||||
var_number=(double)num;
|
||||
}
|
||||
return;
|
||||
}
|
||||
int dot_place=-1;
|
||||
for(int i=0;i<(int)str.length();++i)
|
||||
if(str[i]=='.')
|
||||
{
|
||||
dot_place=i;
|
||||
break;
|
||||
}
|
||||
if(dot_place==-1)
|
||||
{
|
||||
var_number=0;
|
||||
double pw=1;
|
||||
for(int i=(int)str.length()-1;i>=0;--i)
|
||||
{
|
||||
var_number+=(str[i]-'0')*pw;
|
||||
pw*=10;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var_number=0;
|
||||
double pw=0.1;
|
||||
for(int i=dot_place+1;i<(int)str.length();++i)
|
||||
{
|
||||
var_number+=(str[i]-'0')*pw;
|
||||
pw/=10;
|
||||
}
|
||||
pw=1;
|
||||
for(int i=dot_place-1;i>=0;--i)
|
||||
{
|
||||
var_number+=(str[i]-'0')*pw;
|
||||
pw*=10;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
void set_var_name(std::string& str)
|
||||
{
|
||||
var_name=str;
|
||||
return;
|
||||
}
|
||||
void add_child(abstract_syntax_tree p)
|
||||
{
|
||||
children.push_back(p);
|
||||
return;
|
||||
}
|
||||
int get_type()
|
||||
{
|
||||
return ast_node_type;
|
||||
}
|
||||
double get_var_number()
|
||||
{
|
||||
return var_number;
|
||||
}
|
||||
std::string get_var_string()
|
||||
{
|
||||
return var_string;
|
||||
}
|
||||
std::string get_var_name()
|
||||
{
|
||||
return var_name;
|
||||
}
|
||||
std::list<abstract_syntax_tree>& get_children()
|
||||
{
|
||||
return children;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1 +0,0 @@
|
|||
print("hello world!\n");
|
|
@ -1,86 +0,0 @@
|
|||
#include "nasal.h"
|
||||
int main()
|
||||
{
|
||||
resource_programme_process prog;
|
||||
nasal_lexer lex;
|
||||
nasal_parser pas;
|
||||
nasal_runtime vm;
|
||||
std::string command;
|
||||
std::cout<<">> Nasal interpreter by ValKmjolnir"<<std::endl;
|
||||
std::cout<<">> Input [help] to find help."<<std::endl;
|
||||
while(1)
|
||||
{
|
||||
std::cout<<">> ";
|
||||
std::getline(std::cin,command);
|
||||
if(command=="help")
|
||||
{
|
||||
std::cout<<">> Nasal interpreter by ValKmjolnir"<<std::endl;
|
||||
std::cout<<">> 1. [ ] |input file name to load the file."<<std::endl;
|
||||
std::cout<<">> 2. [cls ] |clear the screen."<<std::endl;
|
||||
std::cout<<">> 3. [exit ] |shut down the interpreter."<<std::endl;
|
||||
std::cout<<">> 4. [lexer ] |run and show the lexer. (-lexer)"<<std::endl;
|
||||
std::cout<<">> 5. [parser] |run parser and see parse stack & parse result(s). (-parser)"<<std::endl;
|
||||
std::cout<<">> 6. [ast ] |print the abstract syntax tree."<<std::endl;
|
||||
std::cout<<">> 7. [del ] |delete program in memory."<<std::endl;
|
||||
std::cout<<">> 8. [run ] |run the programme in stack. (-lexer -parser)"<<std::endl;
|
||||
std::cout<<">> 9. [rs ] |check the source program."<<std::endl;
|
||||
}
|
||||
else if(command=="cls")
|
||||
{
|
||||
system("cls");
|
||||
//windows system("cls");
|
||||
//linux system("clear");
|
||||
//macOS system("clear");
|
||||
}
|
||||
else if(command=="rs")
|
||||
prog.print_file();
|
||||
else if(command=="exit")
|
||||
break;
|
||||
else if(command=="lexer")
|
||||
{
|
||||
lex.lexer_process(prog.use_file());
|
||||
lex.print_lexer();
|
||||
}
|
||||
else if(command=="del")
|
||||
{
|
||||
prog.del_file();
|
||||
std::cout<<">>[Delete] Complete."<<std::endl;
|
||||
}
|
||||
else if(command=="parser")
|
||||
{
|
||||
lex.lexer_process(prog.use_file());
|
||||
lex.token_list_type_detail_edit();
|
||||
pas.parse_process(lex.return_list());
|
||||
pas.print_parser_stack();
|
||||
pas.parse_main_work();
|
||||
}
|
||||
else if(command=="ast")
|
||||
{
|
||||
lex.lexer_process(prog.use_file());
|
||||
lex.token_list_type_detail_edit();
|
||||
pas.parse_process(lex.return_list());
|
||||
pas.parse_main_work();
|
||||
if(!pas.get_error_num())
|
||||
pas.print_generated_ast();
|
||||
else
|
||||
std::cout<<">>[Abstract_syntax_tree] error(s) occurred,stop."<<std::endl;
|
||||
}
|
||||
else if(command=="run")
|
||||
{
|
||||
lex.lexer_process(prog.use_file());
|
||||
lex.token_list_type_detail_edit();
|
||||
pas.parse_process(lex.return_list());
|
||||
pas.parse_main_work();
|
||||
if(!pas.get_error_num())
|
||||
{
|
||||
vm.set_root(pas.get_tree());
|
||||
vm.run();
|
||||
}
|
||||
else
|
||||
std::cout<<">>[Runtime] error(s) occurred,stop."<<std::endl;
|
||||
}
|
||||
else
|
||||
prog.input_file(command);
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
#ifndef __NASAL_H__
|
||||
#define __NASAL_H__
|
||||
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <thread>
|
||||
#include <stack>
|
||||
#include <list>
|
||||
#include <ctime>
|
||||
|
||||
#include "nasal_token_type.h"
|
||||
#include "ast.h"
|
||||
#include "nasal_runtime.h"
|
||||
#include "nasal_lexer.h"
|
||||
#include "nasal_parser.h"
|
||||
|
||||
|
||||
#endif
|
|
@ -1,543 +0,0 @@
|
|||
#ifndef __NASAL_LEXER_H__
|
||||
#define __NASAL_LEXER_H__
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <list>
|
||||
#include <cstring>
|
||||
|
||||
#define OPERATOR 1 // operator
|
||||
#define IDENTIFIER 2 // id
|
||||
#define NUMBER 3 // number
|
||||
#define RESERVEWORD 4 // reserve word
|
||||
#define STRING 5 // string
|
||||
#define DYNAMIC_ID 6 // id...
|
||||
#define FAIL -1 //fail
|
||||
#define SCANEND -2 //complete scanning
|
||||
#define ERRORFOUND -3 //error occurred
|
||||
|
||||
std::string reserve_word[15]=
|
||||
{
|
||||
"for","foreach","forindex","while",
|
||||
"var","func","break","continue","return",
|
||||
"if","else","elsif","nil","and","or"
|
||||
};
|
||||
|
||||
int isReserveWord(std::string &p)
|
||||
{
|
||||
for(int i=0;i<15;++i)
|
||||
if(reserve_word[i]==p)
|
||||
return i+1;
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
bool isLetter(char t)
|
||||
{
|
||||
return (('a'<=t) && (t<='z') || ('A'<=t) && (t<='Z'));
|
||||
}
|
||||
|
||||
bool isNumber(char t)
|
||||
{
|
||||
return (('0'<=t) && (t<='9'));
|
||||
}
|
||||
|
||||
bool isHex(char t)
|
||||
{
|
||||
return ((('0'<=t) && (t<='9')) || (('a'<=t) && (t<='f')));
|
||||
}
|
||||
|
||||
bool isOct(char t)
|
||||
{
|
||||
return (('0'<=t) && (t<='7'));
|
||||
}
|
||||
|
||||
class resource_programme_process
|
||||
{
|
||||
private:
|
||||
char *resource;
|
||||
public:
|
||||
resource_programme_process()
|
||||
{
|
||||
resource=NULL;
|
||||
resource=new char[16777216];
|
||||
}
|
||||
~resource_programme_process()
|
||||
{
|
||||
if(resource)
|
||||
delete []resource;
|
||||
}
|
||||
char* use_file()
|
||||
{
|
||||
return resource;
|
||||
}
|
||||
void input_file(std::string& filename)
|
||||
{
|
||||
std::ifstream fin(filename);
|
||||
if(fin.fail())
|
||||
{
|
||||
std::cout<<">>[Error] Cannot load file: "<<filename<<" ."<<std::endl;
|
||||
fin.close();
|
||||
return;
|
||||
}
|
||||
memset(resource,0,sizeof(char));
|
||||
int i=0;
|
||||
int instring=0;
|
||||
bool findnote=false;// to find the note with # at the head of line.
|
||||
while(!fin.eof())
|
||||
{
|
||||
resource[i]=fin.get();
|
||||
if(resource[i]=='\'' || resource[i]=='\"')
|
||||
++instring;
|
||||
if(resource[i]=='\n')
|
||||
findnote=false;
|
||||
//when meeting '\n' the findnote is set to false then the next statement can be executed.
|
||||
if(resource[i]!='#' && !findnote)
|
||||
++i;
|
||||
else if(resource[i]=='#')
|
||||
{
|
||||
if(instring & 1)
|
||||
++i;
|
||||
else
|
||||
findnote=true;
|
||||
}
|
||||
if(fin.eof())
|
||||
break;
|
||||
}
|
||||
resource[i]='\0';
|
||||
fin.close();
|
||||
return;
|
||||
}
|
||||
void print_file()
|
||||
{
|
||||
if(!resource[0])
|
||||
{
|
||||
std::cout<<"0 null"<<std::endl;
|
||||
return;
|
||||
}
|
||||
int line=1;
|
||||
std::cout<<line<<" ";
|
||||
for(int i=0;i<16777216;++i)
|
||||
{
|
||||
if(!resource[i])
|
||||
break;
|
||||
std::cout<<resource[i];
|
||||
if(resource[i]=='\n')
|
||||
{
|
||||
++line;
|
||||
std::cout<<line<<" ";
|
||||
}
|
||||
}
|
||||
std::cout<<std::endl;
|
||||
return;
|
||||
}
|
||||
void del_file()
|
||||
{
|
||||
memset(resource,0,sizeof(char));
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
struct token
|
||||
{
|
||||
int line;
|
||||
int type;
|
||||
std::string content;
|
||||
};
|
||||
|
||||
class nasal_lexer
|
||||
{
|
||||
private:
|
||||
std::list<token> lexer;
|
||||
public:
|
||||
void scanner(int &syn,const char* source,std::string &__token,int &ptr,int &line)
|
||||
{
|
||||
char temp;
|
||||
temp=source[ptr];
|
||||
while(temp==' ' || temp=='\n' || temp=='\t' || temp=='\r' || temp<0 || temp>127)
|
||||
{
|
||||
++ptr;
|
||||
if(temp=='\n')
|
||||
++line;
|
||||
temp=source[ptr];
|
||||
}
|
||||
__token="";
|
||||
if(isLetter(temp) || temp=='_')
|
||||
{
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
while(isLetter(temp) || isNumber(temp) || temp=='_')
|
||||
{
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
}
|
||||
syn=isReserveWord(__token);
|
||||
if(syn==FAIL)
|
||||
syn=IDENTIFIER;
|
||||
else
|
||||
syn=RESERVEWORD;
|
||||
if((syn==IDENTIFIER) && source[ptr]=='.' && source[ptr+1]=='.' && source[ptr+2]=='.')
|
||||
{
|
||||
__token+="...";
|
||||
syn=DYNAMIC_ID;
|
||||
ptr+=3;
|
||||
}
|
||||
}
|
||||
else if(isNumber(temp))
|
||||
{
|
||||
if((source[ptr]=='0') && (source[ptr+1]=='x'))
|
||||
{
|
||||
__token+=source[ptr];
|
||||
__token+=source[ptr+1];
|
||||
ptr+=2;
|
||||
temp=source[ptr];
|
||||
while(isNumber(temp) || isHex(temp))
|
||||
{
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
}
|
||||
if((int)__token.length()==2)
|
||||
{
|
||||
std::cout<<">>[Lexer-warning] lexer: expect a hex-number string after '0x' ."<<std::endl;
|
||||
__token+="0";
|
||||
}
|
||||
}
|
||||
else if((source[ptr]=='0') && (source[ptr+1]=='o'))
|
||||
{
|
||||
__token+=source[ptr];
|
||||
__token+=source[ptr+1];
|
||||
ptr+=2;
|
||||
temp=source[ptr];
|
||||
while(isNumber(temp) || isOct(temp))
|
||||
{
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
}
|
||||
if((int)__token.length()==2)
|
||||
{
|
||||
std::cout<<">>[Lexer-warning] lexer: expect a oct-number string after '0o' ."<<std::endl;
|
||||
__token+="0";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int PointCnt=0;
|
||||
while(isNumber(temp))
|
||||
{
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
if(temp=='.' && !PointCnt)
|
||||
{
|
||||
++PointCnt;
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
}
|
||||
}
|
||||
}
|
||||
syn=NUMBER;
|
||||
}
|
||||
else if(temp=='(' || temp==')' || temp=='[' || temp==']' || temp=='{' ||
|
||||
temp=='}' || temp==',' || temp==';' || temp=='|' || temp==':' ||
|
||||
temp=='?' || temp=='.' || temp=='`' || temp=='&' || temp=='@' ||
|
||||
temp=='%' || temp=='$' || temp=='^')
|
||||
{
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
syn=OPERATOR;
|
||||
}
|
||||
else if(temp=='\'')
|
||||
{
|
||||
syn=STRING;
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
while(temp!='\'')
|
||||
{
|
||||
if(temp=='\\')
|
||||
{
|
||||
__token+=temp;
|
||||
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
__token+=temp;
|
||||
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
}
|
||||
else
|
||||
{
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
}
|
||||
if(temp==0 || temp=='\n')
|
||||
break;
|
||||
}
|
||||
//add the last char \"
|
||||
if(temp=='\'')
|
||||
{
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
}
|
||||
else
|
||||
__token+=" __missing_end_of_string";
|
||||
}
|
||||
else if(temp=='=' || temp=='+' || temp=='-' || temp=='*' || temp=='!' || temp=='/' || temp=='<' || temp=='>' || temp=='~')
|
||||
{
|
||||
syn=OPERATOR;
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
if(temp=='=')
|
||||
{
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
}
|
||||
}
|
||||
else if(temp=='\\')
|
||||
{
|
||||
syn=OPERATOR;
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
if(temp=='=' || temp=='n' || temp=='t' || temp=='r' || temp=='\\' || temp=='\'' || temp=='\"')
|
||||
{
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
}
|
||||
}
|
||||
else if(temp=='\"')
|
||||
{
|
||||
syn=STRING;
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
while(temp!='\"')
|
||||
{
|
||||
if(temp=='\\')
|
||||
{
|
||||
__token+=temp;
|
||||
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
__token+=temp;
|
||||
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
}
|
||||
else
|
||||
{
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
}
|
||||
if(temp==0 || temp=='\n')
|
||||
break;
|
||||
}
|
||||
//add the last char \"
|
||||
if(temp=='\"')
|
||||
{
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
}
|
||||
else
|
||||
__token+=" __missing_end_of_string";
|
||||
}
|
||||
else if(temp==0)
|
||||
{
|
||||
syn=SCANEND;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
syn=FAIL;
|
||||
std::cout<<">>[Error] unexpected error occurred: "<<temp<<std::endl;
|
||||
system("pause");
|
||||
++ptr;
|
||||
return;
|
||||
}
|
||||
if(__token=="")
|
||||
{
|
||||
syn=ERRORFOUND;
|
||||
std::cout<<">>[Error] cannot identify "<<std::endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
void lexer_process(const char *source)
|
||||
{
|
||||
std::cout<<">>[Lexer] max size: "<<lexer.max_size()<<" ."<<std::endl;
|
||||
lexer.clear();
|
||||
int syn=0;//token type
|
||||
int ptr=0;//pointer to one char in ResourcePrograme
|
||||
int line=1;
|
||||
std::string __token;
|
||||
token temp;
|
||||
while(syn!=SCANEND && syn!=ERRORFOUND)
|
||||
{
|
||||
scanner(syn,source,__token,ptr,line);
|
||||
if(syn>0)//all Syn type is larger than zero
|
||||
{
|
||||
temp.line=line;
|
||||
temp.type=syn;
|
||||
temp.content=__token;
|
||||
lexer.push_back(temp);
|
||||
}
|
||||
}
|
||||
std::cout<<">>[Lexer] complete scanning."<<std::endl;
|
||||
return;
|
||||
}
|
||||
void print_lexer()
|
||||
{
|
||||
token temp;
|
||||
for(std::list<token>::iterator i=lexer.begin();i!=lexer.end();++i)
|
||||
{
|
||||
temp=*i;
|
||||
std::cout<<"line "<<temp.line<<": ";
|
||||
if(temp.type==OPERATOR)
|
||||
std::cout<<"( Operator | ";
|
||||
else if(temp.type==IDENTIFIER)
|
||||
std::cout<<"( Identifier | ";
|
||||
else if(temp.type==NUMBER)
|
||||
std::cout<<"( Number | ";
|
||||
else if(temp.type==RESERVEWORD)
|
||||
std::cout<<"( ReserveWord | ";
|
||||
else if(temp.type==STRING)
|
||||
std::cout<<"( String | ";
|
||||
else if(temp.type==DYNAMIC_ID)
|
||||
std::cout<<"( Identifier | ";
|
||||
std::cout<<temp.content<<" )"<<std::endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
void token_list_type_detail_edit()
|
||||
{
|
||||
for(std::list<token>::iterator i=lexer.begin();i!=lexer.end();++i)
|
||||
{
|
||||
if((*i).type==RESERVEWORD)
|
||||
{
|
||||
if((*i).content=="var")
|
||||
(*i).type=__var;
|
||||
else if((*i).content=="func")
|
||||
(*i).type=__func;
|
||||
else if((*i).content=="return")
|
||||
(*i).type=__return;
|
||||
else if((*i).content=="nil")
|
||||
(*i).type=__number;
|
||||
else if((*i).content=="continue")
|
||||
(*i).type=__continue;
|
||||
else if((*i).content=="break")
|
||||
(*i).type=__break;
|
||||
else if((*i).content=="and")
|
||||
(*i).type=__and_operator;
|
||||
else if((*i).content=="or")
|
||||
(*i).type=__or_operator;
|
||||
else if((*i).content=="for")
|
||||
(*i).type=__for;
|
||||
else if((*i).content=="forindex")
|
||||
(*i).type=__forindex;
|
||||
else if((*i).content=="foreach")
|
||||
(*i).type=__foreach;
|
||||
else if((*i).content=="while")
|
||||
(*i).type=__while;
|
||||
else if((*i).content=="if")
|
||||
(*i).type=__if;
|
||||
else if((*i).content=="else")
|
||||
(*i).type=__else;
|
||||
else if((*i).content=="elsif")
|
||||
(*i).type=__elsif;
|
||||
}
|
||||
else if(((*i).content=="==") || ((*i).content=="!=") || ((*i).content==">") || ((*i).content==">=") || ((*i).content=="<") || ((*i).content=="<="))
|
||||
{
|
||||
if((*i).content=="==")
|
||||
(*i).type=__cmp_equal;
|
||||
else if((*i).content=="!=")
|
||||
(*i).type=__cmp_not_equal;
|
||||
else if((*i).content==">")
|
||||
(*i).type=__cmp_more;
|
||||
else if((*i).content==">=")
|
||||
(*i).type=__cmp_more_or_equal;
|
||||
else if((*i).content=="<")
|
||||
(*i).type=__cmp_less;
|
||||
else if((*i).content=="<=")
|
||||
(*i).type=__cmp_less_or_equal;
|
||||
}
|
||||
else if(((*i).content==";") || ((*i).content==",") || ((*i).content=="=") || ((*i).content==":") || ((*i).content==".") || ((*i).content=="?") || ((*i).content=="|") || ((*i).content=="&") || ((*i).content=="%") || ((*i).content=="$") || ((*i).content=="`") || ((*i).content=="^") || ((*i).content=="@"))
|
||||
{
|
||||
char c=(*i).content[0];
|
||||
switch(c)
|
||||
{
|
||||
case ';':(*i).type=__semi;break;
|
||||
case ',':(*i).type=__comma;break;
|
||||
case '=':(*i).type=__equal;break;
|
||||
case ':':(*i).type=__colon;break;
|
||||
case '.':(*i).type=__dot;break;
|
||||
default:(*i).type=__unknown_operator;break;
|
||||
}
|
||||
}
|
||||
else if(((*i).type==NUMBER) || ((*i).type==STRING) || ((*i).type==IDENTIFIER) || ((*i).type==DYNAMIC_ID))
|
||||
{
|
||||
int t=(*i).type;
|
||||
switch(t)
|
||||
{
|
||||
case NUMBER:(*i).type=__number;break;
|
||||
case STRING:(*i).type=__string;break;
|
||||
case IDENTIFIER:(*i).type=__id;break;
|
||||
case DYNAMIC_ID:(*i).type=__dynamic_id;break;
|
||||
}
|
||||
}
|
||||
else if(((*i).content=="+") || ((*i).content=="-") || ((*i).content=="*") || ((*i).content=="/") || ((*i).content=="~") || ((*i).content=="!"))
|
||||
{
|
||||
char c=(*i).content[0];
|
||||
switch(c)
|
||||
{
|
||||
case '+':(*i).type=__add_operator;break;
|
||||
case '-':(*i).type=__sub_operator;break;
|
||||
case '*':(*i).type=__mul_operator;break;
|
||||
case '/':(*i).type=__div_operator;break;
|
||||
case '~':(*i).type=__link_operator;break;
|
||||
case '!':(*i).type=__nor_operator;break;
|
||||
}
|
||||
}
|
||||
else if(((*i).content=="+=") || ((*i).content=="-=") || ((*i).content=="*=") || ((*i).content=="/=") || ((*i).content=="~="))
|
||||
{
|
||||
char c=(*i).content[0];
|
||||
switch(c)
|
||||
{
|
||||
case '+':(*i).type=__add_equal;break;
|
||||
case '-':(*i).type=__sub_equal;break;
|
||||
case '*':(*i).type=__mul_equal;break;
|
||||
case '/':(*i).type=__div_equal;break;
|
||||
case '~':(*i).type=__link_equal;break;
|
||||
}
|
||||
}
|
||||
else if(((*i).content=="(") || ((*i).content==")") || ((*i).content=="[") || ((*i).content=="]") || ((*i).content=="{") || ((*i).content=="}"))
|
||||
{
|
||||
char c=(*i).content[0];
|
||||
switch(c)
|
||||
{
|
||||
case '(':(*i).type=__left_curve;break;
|
||||
case ')':(*i).type=__right_curve;break;
|
||||
case '[':(*i).type=__left_bracket;break;
|
||||
case ']':(*i).type=__right_bracket;break;
|
||||
case '{':(*i).type=__left_brace;break;
|
||||
case '}':(*i).type=__right_brace;break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
std::list<token>& return_list()
|
||||
{
|
||||
return lexer;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -1,614 +0,0 @@
|
|||
#ifndef __NASAL_RUNTIME_H__
|
||||
#define __NASAL_RUNTIME_H__
|
||||
|
||||
class var
|
||||
{
|
||||
private:
|
||||
int type;
|
||||
std::string name;
|
||||
double number;
|
||||
std::string str;
|
||||
std::list<var> var_list;
|
||||
std::list<var> var_hash;
|
||||
abstract_syntax_tree function;
|
||||
public:
|
||||
var()
|
||||
{
|
||||
type=0;
|
||||
name="";
|
||||
number=0;
|
||||
str="";
|
||||
function.set_clear();
|
||||
}
|
||||
var(const var& p)
|
||||
{
|
||||
type=p.type;
|
||||
name=p.name;
|
||||
number=p.number;
|
||||
str=p.str;
|
||||
function=p.function;
|
||||
}
|
||||
var& operator=(const var& p)
|
||||
{
|
||||
type=p.type;
|
||||
name=p.name;
|
||||
number=p.number;
|
||||
str=p.str;
|
||||
function=p.function;
|
||||
return *this;
|
||||
}
|
||||
void print_information()
|
||||
{
|
||||
std::cout<<"[ type: ";print_token(type);std::cout<<" ]";
|
||||
std::cout<<"[ name: "<<name<<" ]";
|
||||
std::cout<<"[ number: "<<number<<" ]";
|
||||
std::cout<<"[ string: "<<str<<" ]"<<std::endl;
|
||||
std::cout<<"[ function: ";
|
||||
function.print_tree(1);
|
||||
std::cout<<" ]"<<std::endl;
|
||||
return;
|
||||
}
|
||||
void print_detail()
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case __function:
|
||||
std::cout<<std::endl<<">>[Runtime-error] function type cannot be printed."<<std::endl;
|
||||
break;
|
||||
case __number:
|
||||
std::cout<<number;
|
||||
break;
|
||||
case __string:
|
||||
for(int i=1;i<str.length()-1;++i)
|
||||
{
|
||||
if(str[i]!='\\')
|
||||
std::cout<<str[i];
|
||||
else
|
||||
{
|
||||
switch(str[i+1])
|
||||
{
|
||||
case 'n':std::cout<<"\n";++i;break;
|
||||
case 't':std::cout<<"\t";++i;break;
|
||||
case 'r':std::cout<<"\r";++i;break;
|
||||
case '\\':std::cout<<"\\";++i;break;
|
||||
case '\'':std::cout<<"\'";++i;break;
|
||||
case '\"':std::cout<<"\"";++i;break;
|
||||
default:std::cout<<"\\";break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
void set_type(const int var_type)
|
||||
{
|
||||
type=var_type;
|
||||
return;
|
||||
}
|
||||
void set_name(std::string var_name_str)
|
||||
{
|
||||
name=var_name_str;
|
||||
return;
|
||||
}
|
||||
void set_number(const double var_number)
|
||||
{
|
||||
number=var_number;
|
||||
return;
|
||||
}
|
||||
void set_string(std::string s)
|
||||
{
|
||||
str=s;
|
||||
return;
|
||||
}
|
||||
void set_function(abstract_syntax_tree func)
|
||||
{
|
||||
function=func;
|
||||
return;
|
||||
}
|
||||
void set_list(std::list<var> p)
|
||||
{
|
||||
var_list=p;
|
||||
return;
|
||||
}
|
||||
void append_list(var p)
|
||||
{
|
||||
var_list.push_back(p);
|
||||
return;
|
||||
}
|
||||
void set_hash(std::list<var> p)
|
||||
{
|
||||
var_hash=p;
|
||||
return;
|
||||
}
|
||||
void append_hash(var p)
|
||||
{
|
||||
var_hash.push_back(p);
|
||||
return;
|
||||
}
|
||||
int get_type()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
std::string get_name()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
double get_number()
|
||||
{
|
||||
return number;
|
||||
}
|
||||
std::string get_string()
|
||||
{
|
||||
return str;
|
||||
}
|
||||
abstract_syntax_tree get_function()
|
||||
{
|
||||
return function;
|
||||
}
|
||||
std::list<var> get_list()
|
||||
{
|
||||
return var_list;
|
||||
}
|
||||
std::list<var> get_hash()
|
||||
{
|
||||
return var_hash;
|
||||
}
|
||||
};
|
||||
|
||||
class var_scope_manager
|
||||
{
|
||||
private:
|
||||
std::list<std::list<var>> scope_list;
|
||||
std::list<int> scope_type;
|
||||
var error_var;
|
||||
public:
|
||||
var_scope_manager()
|
||||
{
|
||||
scope_list.clear();
|
||||
std::string str="__nas_strc_error_ret";
|
||||
error_var.set_name(str);
|
||||
error_var.set_type(__null_type);
|
||||
return;
|
||||
}
|
||||
void set_clear()
|
||||
{
|
||||
scope_list.clear();
|
||||
scope_type.clear();
|
||||
return;
|
||||
}
|
||||
var& search_var(std::string str)
|
||||
{
|
||||
for(std::list<std::list<var>>::iterator i=scope_list.begin();i!=scope_list.end();++i)
|
||||
for(std::list<var>::iterator j=i->begin();j!=i->end();++j)
|
||||
if(j->get_name()==str)
|
||||
return *j;
|
||||
std::cout<<std::endl<<">>[Runtime-error] could not find the var '"<<str<<"' ."<<std::endl;
|
||||
return error_var;
|
||||
}
|
||||
void add_var(var new_var)
|
||||
{
|
||||
std::list<std::list<var>>::iterator i=scope_list.begin();
|
||||
std::list<int>::iterator t=scope_type.begin();
|
||||
// get global scopes
|
||||
for(;i!=scope_list.end();++i,++t)
|
||||
{
|
||||
if(*t!=__function)
|
||||
{
|
||||
for(std::list<var>::iterator j=i->begin();j!=i->end();++j)
|
||||
if(j->get_name()==new_var.get_name())
|
||||
{
|
||||
std::cout<<std::endl<<">>[Runtime-error] redeclaration of var '"<<new_var.get_name()<<"' ."<<std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// get parameters_list scope
|
||||
i=scope_list.end();
|
||||
--i;
|
||||
t=scope_type.end();
|
||||
--t;
|
||||
if(*t==__function)
|
||||
{
|
||||
for(std::list<var>::iterator j=i->begin();j!=i->end();++j)
|
||||
if(j->get_name()==new_var.get_name())
|
||||
{
|
||||
std::cout<<std::endl<<">>[Runtime-error] redeclaration of var '"<<new_var.get_name()<<"' ."<<std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(!scope_list.empty())
|
||||
{
|
||||
i=scope_list.end();
|
||||
--i;
|
||||
i->push_back(new_var);
|
||||
}
|
||||
else
|
||||
std::cout<<std::endl<<">>[Runtime-error] empty scope list."<<std::endl;
|
||||
return;
|
||||
}
|
||||
void add_new_scope(int type)
|
||||
{
|
||||
std::list<var> new_list;
|
||||
scope_list.push_back(new_list);
|
||||
scope_type.push_back(type);
|
||||
return;
|
||||
}
|
||||
void pop_last_scope()
|
||||
{
|
||||
if(!scope_list.empty())
|
||||
{
|
||||
scope_list.pop_back();
|
||||
scope_type.pop_back();
|
||||
}
|
||||
else
|
||||
std::cout<<std::endl<<">>[Runtime-error] scope poped empty thing."<<std::endl;
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
class nasal_runtime
|
||||
{
|
||||
private:
|
||||
abstract_syntax_tree root;
|
||||
var_scope_manager scope;
|
||||
public:
|
||||
nasal_runtime()
|
||||
{
|
||||
root.set_clear();
|
||||
return;
|
||||
}
|
||||
void run()
|
||||
{
|
||||
std::cout<<">>[Runtime] process begins."<<std::endl;
|
||||
int time_beg,time_end;
|
||||
time_beg=time(NULL);
|
||||
scope.set_clear();
|
||||
run_root(root);
|
||||
time_end=time(NULL);
|
||||
std::cout<<std::endl<<">>[Runtime] process exited after "<<time_beg-time_end<<" sec(s)."<<std::endl;
|
||||
return;
|
||||
}
|
||||
void set_root(abstract_syntax_tree& tree)
|
||||
{
|
||||
root.set_clear();
|
||||
root=tree;
|
||||
std::cout<<">>[Runtime] runtime got the ast-root: "<<((void *)&tree)<<"->"<<((void *)&root)<<"."<<std::endl;
|
||||
return;
|
||||
}
|
||||
void run_definition(abstract_syntax_tree& tree);
|
||||
void run_assignment(abstract_syntax_tree& tree);
|
||||
void run_loop(abstract_syntax_tree& tree);
|
||||
void run_if_else(abstract_syntax_tree& tree);
|
||||
void run_block(abstract_syntax_tree& tree,int run_type);
|
||||
void run_root(abstract_syntax_tree& tree);
|
||||
var run_calculation(abstract_syntax_tree& tree);
|
||||
var run_function(abstract_syntax_tree& tree);
|
||||
var list_generation(abstract_syntax_tree& tree);
|
||||
var hash_generation(abstract_syntax_tree& tree);
|
||||
var list_search(abstract_syntax_tree& tree);
|
||||
var hash_search(abstract_syntax_tree& tree);
|
||||
var identifier_call(abstract_syntax_tree& tree);
|
||||
var scalar_call(abstract_syntax_tree& tree);
|
||||
};
|
||||
|
||||
void nasal_runtime::run_root(abstract_syntax_tree& tree)
|
||||
{
|
||||
scope.add_new_scope(__root);
|
||||
if(!tree.get_children().empty())
|
||||
{
|
||||
for(std::list<abstract_syntax_tree>::iterator i=tree.get_children().begin();i!=tree.get_children().end();++i)
|
||||
{
|
||||
switch(i->get_type())
|
||||
{
|
||||
case __add_operator:
|
||||
case __sub_operator:
|
||||
case __mul_operator:
|
||||
case __div_operator:
|
||||
case __link_operator:
|
||||
case __and_operator:
|
||||
case __or_operator:
|
||||
case __nor_operator:
|
||||
case __cmp_equal:
|
||||
case __cmp_not_equal:
|
||||
case __cmp_less:
|
||||
case __cmp_less_or_equal:
|
||||
case __cmp_more:
|
||||
case __cmp_more_or_equal:
|
||||
run_calculation(*i);
|
||||
break;
|
||||
case __definition:
|
||||
run_definition(*i);
|
||||
break;
|
||||
case __assignment:
|
||||
run_assignment(*i);
|
||||
break;
|
||||
case __while:
|
||||
case __for:
|
||||
case __forindex:
|
||||
case __foreach:
|
||||
run_loop(*i);
|
||||
break;
|
||||
case __ifelse:
|
||||
run_if_else(*i);
|
||||
break;
|
||||
case __call_function:
|
||||
run_function(*i);
|
||||
break;
|
||||
case __id:
|
||||
case __hash_search:
|
||||
case __list_search:
|
||||
identifier_call(*i);
|
||||
break;
|
||||
case __number:
|
||||
case __string:
|
||||
scalar_call(*i);
|
||||
break;
|
||||
default:
|
||||
std::cout<<">>[Debug] error occurred."<<std::endl;
|
||||
scope.pop_last_scope();
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
scope.pop_last_scope();
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_runtime::run_definition(abstract_syntax_tree& tree)
|
||||
{
|
||||
var new_var;
|
||||
std::list<abstract_syntax_tree>::iterator iter=tree.get_children().begin();
|
||||
std::string var_name=iter->get_var_name();
|
||||
++iter;
|
||||
if(iter==tree.get_children().end())
|
||||
{
|
||||
new_var.set_type(__null_type);
|
||||
new_var.set_name(var_name);
|
||||
scope.add_var(new_var);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(iter->get_type())
|
||||
{
|
||||
case __add_operator:
|
||||
case __sub_operator:
|
||||
case __mul_operator:
|
||||
case __div_operator:
|
||||
case __link_operator:
|
||||
case __and_operator:
|
||||
case __or_operator:
|
||||
case __nor_operator:
|
||||
case __cmp_equal:
|
||||
case __cmp_not_equal:
|
||||
case __cmp_less:
|
||||
case __cmp_less_or_equal:
|
||||
case __cmp_more:
|
||||
case __cmp_more_or_equal:
|
||||
new_var=run_calculation(*iter);
|
||||
break;
|
||||
case __call_function:
|
||||
new_var=run_function(*iter);
|
||||
break;
|
||||
case __id:
|
||||
case __hash_search:
|
||||
case __list_search:
|
||||
break;
|
||||
case __number:
|
||||
case __string:
|
||||
new_var=scalar_call(*iter);
|
||||
break;
|
||||
case __function:
|
||||
new_var.set_type(__function);
|
||||
new_var.set_function(*iter);
|
||||
break;
|
||||
case __list:
|
||||
break;
|
||||
case __hash:
|
||||
break;
|
||||
default:
|
||||
std::cout<<">>[Debug] error occurred."<<std::endl;
|
||||
return;
|
||||
break;
|
||||
}
|
||||
new_var.set_name(var_name);
|
||||
scope.add_var(new_var);
|
||||
}
|
||||
return;
|
||||
}
|
||||
void nasal_runtime::run_assignment(abstract_syntax_tree& tree)
|
||||
{
|
||||
return;
|
||||
}
|
||||
void nasal_runtime::run_loop(abstract_syntax_tree& tree)
|
||||
{
|
||||
return;
|
||||
}
|
||||
void nasal_runtime::run_if_else(abstract_syntax_tree& tree)
|
||||
{
|
||||
return;
|
||||
}
|
||||
void nasal_runtime::run_block(abstract_syntax_tree& tree,int run_type)
|
||||
{
|
||||
scope.add_new_scope(run_type);
|
||||
|
||||
scope.pop_last_scope();
|
||||
return;
|
||||
}
|
||||
|
||||
var nasal_runtime::run_calculation(abstract_syntax_tree& tree)
|
||||
{
|
||||
var ret_var;
|
||||
var left_child;
|
||||
var right_child;
|
||||
|
||||
std::list<abstract_syntax_tree>::iterator i;
|
||||
i=tree.get_children().begin();
|
||||
switch(i->get_type())
|
||||
{
|
||||
case __id:left_child=identifier_call(*i);break;
|
||||
case __number:
|
||||
case __string:left_child=scalar_call(*i);break;
|
||||
case __call_function:left_child=run_function(*i);break;
|
||||
case __list_search:left_child=list_search(*i);break;
|
||||
case __hash_search:left_child=hash_search(*i);break;
|
||||
case __or_operator:
|
||||
case __and_operator:
|
||||
case __add_operator:
|
||||
case __mul_operator:
|
||||
case __div_operator:
|
||||
case __link_operator:
|
||||
case __nor_operator:
|
||||
case __sub_operator:
|
||||
case __cmp_equal:
|
||||
case __cmp_not_equal:
|
||||
case __cmp_less:
|
||||
case __cmp_less_or_equal:
|
||||
case __cmp_more:
|
||||
case __cmp_more_or_equal:left_child=run_calculation(*i);break;
|
||||
default:std::cout<<">>[Runtime-error] invalid var."<<std::endl;break;
|
||||
}
|
||||
++i;
|
||||
if(i==tree.get_children().end())
|
||||
return left_child;
|
||||
switch(i->get_type())
|
||||
{
|
||||
case __id:right_child=identifier_call(*i);break;
|
||||
case __number:
|
||||
case __string:right_child=scalar_call(*i);break;
|
||||
case __call_function:right_child=run_function(*i);break;
|
||||
case __list_search:right_child=list_search(*i);break;
|
||||
case __hash_search:right_child=hash_search(*i);break;
|
||||
case __or_operator:
|
||||
case __and_operator:
|
||||
case __add_operator:
|
||||
case __mul_operator:
|
||||
case __div_operator:
|
||||
case __link_operator:
|
||||
case __nor_operator:
|
||||
case __sub_operator:
|
||||
case __cmp_equal:
|
||||
case __cmp_not_equal:
|
||||
case __cmp_less:
|
||||
case __cmp_less_or_equal:
|
||||
case __cmp_more:
|
||||
case __cmp_more_or_equal:right_child=run_calculation(*i);break;
|
||||
default:std::cout<<">>[Runtime-error] invalid var."<<std::endl;break;
|
||||
}
|
||||
switch(tree.get_type())
|
||||
{
|
||||
case __or_operator:
|
||||
case __and_operator:
|
||||
break;
|
||||
case __add_operator:
|
||||
case __mul_operator:
|
||||
case __div_operator:
|
||||
case __link_operator:
|
||||
break;
|
||||
case __nor_operator:
|
||||
case __sub_operator:
|
||||
break;
|
||||
case __cmp_equal:
|
||||
case __cmp_not_equal:
|
||||
case __cmp_less:
|
||||
case __cmp_less_or_equal:
|
||||
case __cmp_more:
|
||||
case __cmp_more_or_equal:
|
||||
break;
|
||||
}
|
||||
return ret_var;
|
||||
}
|
||||
var nasal_runtime::run_function(abstract_syntax_tree& tree)
|
||||
{
|
||||
var ret_var;
|
||||
scope.add_new_scope(__function);
|
||||
if(tree.get_var_name()=="print")
|
||||
{
|
||||
std::list<var> dynamic_para;
|
||||
var list_member;
|
||||
for(std::list<abstract_syntax_tree>::iterator i=tree.get_children().begin();i!=tree.get_children().end();++i)
|
||||
{
|
||||
switch(i->get_type())
|
||||
{
|
||||
case __id:list_member=identifier_call(*i);break;
|
||||
case __number:
|
||||
case __string:list_member=scalar_call(*i);break;
|
||||
case __call_function:list_member=run_function(*i);break;
|
||||
case __list_search:list_member=list_search(*i);break;
|
||||
case __hash_search:list_member=hash_search(*i);break;
|
||||
case __or_operator:
|
||||
case __and_operator:
|
||||
case __add_operator:
|
||||
case __mul_operator:
|
||||
case __div_operator:
|
||||
case __link_operator:
|
||||
case __nor_operator:
|
||||
case __sub_operator:
|
||||
case __cmp_equal:
|
||||
case __cmp_not_equal:
|
||||
case __cmp_less:
|
||||
case __cmp_less_or_equal:
|
||||
case __cmp_more:
|
||||
case __cmp_more_or_equal:list_member=run_calculation(*i);break;
|
||||
default:std::cout<<">>[Runtime-error] invalid var."<<std::endl;break;
|
||||
}
|
||||
dynamic_para.push_back(list_member);
|
||||
}
|
||||
for(std::list<var>::iterator i=dynamic_para.begin();i!=dynamic_para.end();++i)
|
||||
i->print_detail();
|
||||
}
|
||||
scope.pop_last_scope();
|
||||
return ret_var;
|
||||
}
|
||||
var nasal_runtime::list_generation(abstract_syntax_tree& tree)
|
||||
{
|
||||
var new_list;
|
||||
new_list.set_type(__list);
|
||||
return new_list;
|
||||
}
|
||||
var nasal_runtime::hash_generation(abstract_syntax_tree& tree)
|
||||
{
|
||||
var new_hash;
|
||||
new_hash.set_type(__hash);
|
||||
return new_hash;
|
||||
}
|
||||
var nasal_runtime::list_search(abstract_syntax_tree& tree)
|
||||
{
|
||||
var ret_var;
|
||||
return ret_var;
|
||||
}
|
||||
var nasal_runtime::hash_search(abstract_syntax_tree& tree)
|
||||
{
|
||||
var ret_var;
|
||||
return ret_var;
|
||||
}
|
||||
var nasal_runtime::identifier_call(abstract_syntax_tree& tree)
|
||||
{
|
||||
var ret_var;
|
||||
ret_var=scope.search_var(tree.get_var_name());
|
||||
if(ret_var.get_type()==__null_type)
|
||||
return ret_var;
|
||||
if(ret_var.get_type()==__number)
|
||||
std::cout<<ret_var.get_number()<<std::endl;
|
||||
else if(ret_var.get_type()==__string)
|
||||
std::cout<<ret_var.get_string()<<std::endl;
|
||||
return ret_var;
|
||||
}
|
||||
var nasal_runtime::scalar_call(abstract_syntax_tree& tree)
|
||||
{
|
||||
var ret_var;
|
||||
if(tree.get_type()==__number)
|
||||
{
|
||||
ret_var.set_type(__number);
|
||||
ret_var.set_number(tree.get_var_number());
|
||||
}
|
||||
else if(tree.get_type()==__string)
|
||||
{
|
||||
ret_var.set_type(__string);
|
||||
ret_var.set_string(tree.get_var_string());
|
||||
}
|
||||
return ret_var;
|
||||
}
|
||||
#endif
|
|
@ -1,118 +0,0 @@
|
|||
#ifndef __NASAL_TOKEN_TYPE_H__
|
||||
#define __NASAL_TOKEN_TYPE_H__
|
||||
|
||||
#include <cstring>
|
||||
|
||||
enum token_type
|
||||
{
|
||||
__stack_end=1,
|
||||
__equal, // =
|
||||
__cmp_equal,__cmp_not_equal, // == !=
|
||||
__cmp_less,__cmp_less_or_equal, // < <=
|
||||
__cmp_more,__cmp_more_or_equal, // > >=
|
||||
__and_operator,__or_operator,__nor_operator, // and or !
|
||||
__add_operator,__sub_operator, // + -
|
||||
__mul_operator,__div_operator,__link_operator, // * / ~
|
||||
__add_equal,__sub_equal, // += -=
|
||||
__mul_equal,__div_equal,__link_equal, // *= /= ~=
|
||||
__left_brace,__right_brace, // {}
|
||||
__left_bracket,__right_bracket, // []
|
||||
__left_curve,__right_curve, // ()
|
||||
__semi,__comma,__colon,__dot, // ; , : .
|
||||
__unknown_operator,
|
||||
__var,__func,__return,
|
||||
__if,__elsif,__else,
|
||||
__continue,__break,
|
||||
__for,__forindex,__foreach,__while,
|
||||
//operators & reserve words
|
||||
|
||||
__number,__string,__id,__dynamic_id,
|
||||
//basic elements
|
||||
|
||||
__root,
|
||||
__null_type,
|
||||
__list,__hash,
|
||||
__hash_member,
|
||||
__call_function,__list_search,__hash_search,
|
||||
__normal_statement_block,
|
||||
__definition,__assignment,
|
||||
__function,__loop,__ifelse
|
||||
};
|
||||
|
||||
void print_token(int type)
|
||||
{
|
||||
std::string context="";
|
||||
switch(type)
|
||||
{
|
||||
case __stack_end: context="#"; break;
|
||||
case __equal: context="="; break;
|
||||
case __cmp_equal: context="==";break;
|
||||
case __cmp_not_equal: context="!=";break;
|
||||
case __cmp_less: context="<"; break;
|
||||
case __cmp_less_or_equal: context="<=";break;
|
||||
case __cmp_more: context=">"; break;
|
||||
case __cmp_more_or_equal: context=">=";break;
|
||||
case __and_operator: context="and";break;
|
||||
case __or_operator: context="or"; break;
|
||||
case __nor_operator: context="!"; break;
|
||||
case __add_operator: context="+"; break;
|
||||
case __sub_operator: context="-"; break;
|
||||
case __mul_operator: context="*"; break;
|
||||
case __div_operator: context="/"; break;
|
||||
case __link_operator: context="~"; break;
|
||||
case __add_equal: context="+=";break;
|
||||
case __sub_equal: context="-=";break;
|
||||
case __mul_equal: context="*=";break;
|
||||
case __div_equal: context="/=";break;
|
||||
case __link_equal: context="~=";break;
|
||||
case __left_brace: context="{"; break;
|
||||
case __right_brace: context="}"; break;
|
||||
case __left_bracket: context="["; break;
|
||||
case __right_bracket: context="]"; break;
|
||||
case __left_curve: context="("; break;
|
||||
case __right_curve: context=")"; break;
|
||||
case __semi: context=";"; break;
|
||||
case __comma: context=","; break;
|
||||
case __colon: context=":"; break;
|
||||
case __dot: context="."; break;
|
||||
case __unknown_operator: context="unknown_operator";break;
|
||||
case __var: context="var"; break;
|
||||
case __func: context="func";break;
|
||||
case __continue: context="continye"; break;
|
||||
case __break: context="break"; break;
|
||||
case __for: context="for"; break;
|
||||
case __forindex: context="forindex";break;
|
||||
case __foreach: context="foreach";break;
|
||||
case __while: context="while";break;
|
||||
case __if: context="if";break;
|
||||
case __elsif: context="elsif";break;
|
||||
case __else: context="else";break;
|
||||
case __return: context="return";break;
|
||||
|
||||
case __id: context="id";break;
|
||||
case __dynamic_id: context="id...";break;
|
||||
case __number: context="num";break;
|
||||
case __string: context="str";break;
|
||||
|
||||
case __root: context="root";break;
|
||||
case __null_type: context="null_type";break;
|
||||
case __list: context="list";break;
|
||||
case __hash: context="hash";break;
|
||||
case __hash_member: context="hash_member";break;
|
||||
case __call_function: context="call_func";break;
|
||||
case __list_search: context="call_list";break;
|
||||
case __hash_search: context="call_hash";break;
|
||||
case __normal_statement_block:context="block";break;
|
||||
case __definition: context="definition";break;
|
||||
case __assignment: context="assignment";break;
|
||||
case __function: context="function";break;
|
||||
case __loop: context="loop";break;
|
||||
case __ifelse: context="if-else";break;
|
||||
default: context="undefined_token";break;
|
||||
}
|
||||
std::cout<<context;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
191
version1.3/ast.h
191
version1.3/ast.h
|
@ -1,191 +0,0 @@
|
|||
#ifndef __NASAL_ABSTRACT_SYNTAX_TREE_RUN_H__
|
||||
#define __NASAL_ABSTRACT_SYNTAX_TREE_RUN_H__
|
||||
|
||||
class abstract_syntax_tree
|
||||
{
|
||||
private:
|
||||
int ast_node_type;
|
||||
double var_number;
|
||||
std::string var_string;
|
||||
std::string var_name;
|
||||
std::list<abstract_syntax_tree> children;
|
||||
public:
|
||||
abstract_syntax_tree()
|
||||
{
|
||||
ast_node_type=0;
|
||||
var_number=0;
|
||||
var_string="";
|
||||
var_name="";
|
||||
children.clear();
|
||||
return;
|
||||
}
|
||||
abstract_syntax_tree(const abstract_syntax_tree& p)
|
||||
{
|
||||
ast_node_type=p.ast_node_type;
|
||||
var_number=p.var_number;
|
||||
var_string=p.var_string;
|
||||
var_name=p.var_name;
|
||||
children=p.children;
|
||||
return;
|
||||
}
|
||||
abstract_syntax_tree& operator=(const abstract_syntax_tree& p)
|
||||
{
|
||||
ast_node_type=p.ast_node_type;
|
||||
var_number=p.var_number;
|
||||
var_string=p.var_string;
|
||||
var_name=p.var_name;
|
||||
children.clear();
|
||||
children=p.children;
|
||||
return *this;
|
||||
}
|
||||
void set_clear()
|
||||
{
|
||||
ast_node_type=0;
|
||||
var_number=0;
|
||||
var_string="";
|
||||
var_name="";
|
||||
children.clear();
|
||||
return;
|
||||
}
|
||||
void print_tree(const int n)
|
||||
{
|
||||
std::string str="";
|
||||
for(int i=0;i<n;++i)
|
||||
str+="| ";
|
||||
std::cout<<str;
|
||||
print_token(ast_node_type);
|
||||
switch(ast_node_type)
|
||||
{
|
||||
case __number:std::cout<<": "<<var_number;break;
|
||||
case __string:std::cout<<": "<<var_string;break;
|
||||
case __id:
|
||||
case __list_search:
|
||||
case __hash_search:
|
||||
case __call_function:std::cout<<": "<<var_name;break;
|
||||
}
|
||||
std::cout<<std::endl;
|
||||
if(!children.empty())
|
||||
{
|
||||
for(auto i=children.begin();i!=children.end();++i)
|
||||
i->print_tree(n+1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
void set_node_type(const int type)
|
||||
{
|
||||
ast_node_type=type;
|
||||
return;
|
||||
}
|
||||
void set_var_string(std::string str)
|
||||
{
|
||||
var_string="";
|
||||
for(int i=1;i<(int)str.length()-1;++i)
|
||||
var_string+=str[i];
|
||||
return;
|
||||
}
|
||||
void set_var_number(std::string str)
|
||||
{
|
||||
if(str=="nil")
|
||||
{
|
||||
var_number=0;
|
||||
return;
|
||||
}
|
||||
if((int)str.length()>2 && (str[1]=='x' || str[1]=='o'))
|
||||
{
|
||||
if(str[1]=='x')
|
||||
{
|
||||
double num=0;
|
||||
double pw=1;
|
||||
for(int i=(int)str.length()-1;i>1;--i)
|
||||
{
|
||||
if('0'<=str[i] && str[i]<='9')
|
||||
num+=(str[i]-'0')*pw;
|
||||
else if('a'<=str[i] && str[i]<='f')
|
||||
num+=(10+str[i]-'a')*pw;
|
||||
else if('A'<=str[i] && str[i]<='F')
|
||||
num+=(10+str[i]-'A')*pw;
|
||||
pw*=16;
|
||||
}
|
||||
var_number=num;
|
||||
}
|
||||
else
|
||||
{
|
||||
double num=0;
|
||||
double pw=1;
|
||||
for(int i=(int)str.length()-1;i>1;--i)
|
||||
{
|
||||
num+=(str[i]-'0')*pw;
|
||||
pw*=8;
|
||||
}
|
||||
var_number=num;
|
||||
}
|
||||
return;
|
||||
}
|
||||
int dot_place=-1;
|
||||
for(int i=0;i<(int)str.length();++i)
|
||||
if(str[i]=='.')
|
||||
{
|
||||
dot_place=i;
|
||||
break;
|
||||
}
|
||||
if(dot_place==-1)
|
||||
{
|
||||
var_number=0;
|
||||
double pw=1;
|
||||
for(int i=(int)str.length()-1;i>=0;--i)
|
||||
{
|
||||
var_number+=(str[i]-'0')*pw;
|
||||
pw*=10;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var_number=0;
|
||||
double pw=0.1;
|
||||
for(int i=dot_place+1;i<(int)str.length();++i)
|
||||
{
|
||||
var_number+=(str[i]-'0')*pw;
|
||||
pw/=10;
|
||||
}
|
||||
pw=1;
|
||||
for(int i=dot_place-1;i>=0;--i)
|
||||
{
|
||||
var_number+=(str[i]-'0')*pw;
|
||||
pw*=10;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
void set_var_name(std::string& str)
|
||||
{
|
||||
var_name=str;
|
||||
return;
|
||||
}
|
||||
void add_child(abstract_syntax_tree p)
|
||||
{
|
||||
children.push_back(p);
|
||||
return;
|
||||
}
|
||||
int get_type()
|
||||
{
|
||||
return ast_node_type;
|
||||
}
|
||||
double get_var_number()
|
||||
{
|
||||
return var_number;
|
||||
}
|
||||
std::string get_var_string()
|
||||
{
|
||||
return var_string;
|
||||
}
|
||||
std::string get_var_name()
|
||||
{
|
||||
return var_name;
|
||||
}
|
||||
std::list<abstract_syntax_tree>& get_children()
|
||||
{
|
||||
return children;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,86 +0,0 @@
|
|||
#include "nasal.h"
|
||||
int main()
|
||||
{
|
||||
resource_programme_process prog;
|
||||
nasal_lexer lex;
|
||||
nasal_parser pas;
|
||||
nasal_vm vm;
|
||||
std::string command;
|
||||
std::cout<<">> Nasal interpreter by ValKmjolnir"<<std::endl;
|
||||
std::cout<<">> Input [help] to find help."<<std::endl;
|
||||
while(1)
|
||||
{
|
||||
std::cout<<">> ";
|
||||
std::getline(std::cin,command);
|
||||
if(command=="help")
|
||||
{
|
||||
std::cout<<">> Nasal interpreter by ValKmjolnir"<<std::endl;
|
||||
std::cout<<">> 1. [ ] |input file name to load the file."<<std::endl;
|
||||
std::cout<<">> 2. [cls ] |clear the screen."<<std::endl;
|
||||
std::cout<<">> 3. [exit ] |shut down the interpreter."<<std::endl;
|
||||
std::cout<<">> 4. [lexer ] |run and show the lexer. (-lexer)"<<std::endl;
|
||||
std::cout<<">> 5. [parser] |run parser and see parse stack & parse result(s). (-parser)"<<std::endl;
|
||||
std::cout<<">> 6. [ast ] |print the abstract syntax tree."<<std::endl;
|
||||
std::cout<<">> 7. [del ] |delete program in memory."<<std::endl;
|
||||
std::cout<<">> 8. [run ] |run the programme in stack. (-lexer -parser)"<<std::endl;
|
||||
std::cout<<">> 9. [rs ] |check the source program."<<std::endl;
|
||||
}
|
||||
else if(command=="cls")
|
||||
{
|
||||
system("cls");
|
||||
//windows system("cls");
|
||||
//linux system("clear");
|
||||
//macOS system("clear");
|
||||
}
|
||||
else if(command=="rs")
|
||||
prog.print_file();
|
||||
else if(command=="exit")
|
||||
break;
|
||||
else if(command=="lexer")
|
||||
{
|
||||
lex.lexer_process(prog.use_file());
|
||||
lex.print_lexer();
|
||||
}
|
||||
else if(command=="del")
|
||||
{
|
||||
prog.del_file();
|
||||
std::cout<<">>[Delete] Complete."<<std::endl;
|
||||
}
|
||||
else if(command=="parser")
|
||||
{
|
||||
lex.lexer_process(prog.use_file());
|
||||
lex.token_list_type_detail_edit();
|
||||
pas.parse_process(lex.return_list());
|
||||
pas.print_parser_stack();
|
||||
pas.parse_main_work();
|
||||
}
|
||||
else if(command=="ast")
|
||||
{
|
||||
lex.lexer_process(prog.use_file());
|
||||
lex.token_list_type_detail_edit();
|
||||
pas.parse_process(lex.return_list());
|
||||
pas.parse_main_work();
|
||||
if(!pas.get_error_num())
|
||||
pas.print_generated_ast();
|
||||
else
|
||||
std::cout<<">>[Abstract_syntax_tree] error(s) occurred,stop."<<std::endl;
|
||||
}
|
||||
else if(command=="run")
|
||||
{
|
||||
lex.lexer_process(prog.use_file());
|
||||
lex.token_list_type_detail_edit();
|
||||
pas.parse_process(lex.return_list());
|
||||
pas.parse_main_work();
|
||||
if(!pas.get_error_num())
|
||||
{
|
||||
vm.set_root(pas.get_tree());
|
||||
vm.run();
|
||||
}
|
||||
else
|
||||
std::cout<<">>[Runtime] error(s) occurred,stop."<<std::endl;
|
||||
}
|
||||
else
|
||||
prog.input_file(command);
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
#ifndef __NASAL_H__
|
||||
#define __NASAL_H__
|
||||
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <thread>
|
||||
#include <stack>
|
||||
#include <list>
|
||||
#include <ctime>
|
||||
|
||||
#include "nasal_token_type.h"
|
||||
#include "ast.h"
|
||||
#include "nasal_vm.h"
|
||||
#include "nasal_lexer.h"
|
||||
#include "nasal_parser.h"
|
||||
|
||||
|
||||
#endif
|
|
@ -1,543 +0,0 @@
|
|||
#ifndef __NASAL_LEXER_H__
|
||||
#define __NASAL_LEXER_H__
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <list>
|
||||
#include <cstring>
|
||||
|
||||
#define OPERATOR 1 // operator
|
||||
#define IDENTIFIER 2 // id
|
||||
#define NUMBER 3 // number
|
||||
#define RESERVEWORD 4 // reserve word
|
||||
#define STRING 5 // string
|
||||
#define DYNAMIC_ID 6 // id...
|
||||
#define FAIL -1 //fail
|
||||
#define SCANEND -2 //complete scanning
|
||||
#define ERRORFOUND -3 //error occurred
|
||||
|
||||
std::string reserve_word[15]=
|
||||
{
|
||||
"for","foreach","forindex","while",
|
||||
"var","func","break","continue","return",
|
||||
"if","else","elsif","nil","and","or"
|
||||
};
|
||||
|
||||
int isReserveWord(std::string &p)
|
||||
{
|
||||
for(int i=0;i<15;++i)
|
||||
if(reserve_word[i]==p)
|
||||
return i+1;
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
bool isLetter(char t)
|
||||
{
|
||||
return (('a'<=t) && (t<='z') || ('A'<=t) && (t<='Z'));
|
||||
}
|
||||
|
||||
bool isNumber(char t)
|
||||
{
|
||||
return (('0'<=t) && (t<='9'));
|
||||
}
|
||||
|
||||
bool isHex(char t)
|
||||
{
|
||||
return ((('0'<=t) && (t<='9')) || (('a'<=t) && (t<='f')));
|
||||
}
|
||||
|
||||
bool isOct(char t)
|
||||
{
|
||||
return (('0'<=t) && (t<='7'));
|
||||
}
|
||||
|
||||
class resource_programme_process
|
||||
{
|
||||
private:
|
||||
char *resource;
|
||||
public:
|
||||
resource_programme_process()
|
||||
{
|
||||
resource=NULL;
|
||||
resource=new char[16777216];
|
||||
}
|
||||
~resource_programme_process()
|
||||
{
|
||||
if(resource)
|
||||
delete []resource;
|
||||
}
|
||||
char* use_file()
|
||||
{
|
||||
return resource;
|
||||
}
|
||||
void input_file(std::string& filename)
|
||||
{
|
||||
std::ifstream fin(filename);
|
||||
if(fin.fail())
|
||||
{
|
||||
std::cout<<">>[Error] Cannot load file: "<<filename<<" ."<<std::endl;
|
||||
fin.close();
|
||||
return;
|
||||
}
|
||||
memset(resource,0,sizeof(char));
|
||||
int i=0;
|
||||
int instring=0;
|
||||
bool findnote=false;// to find the note with # at the head of line.
|
||||
while(!fin.eof())
|
||||
{
|
||||
resource[i]=fin.get();
|
||||
if(resource[i]=='\'' || resource[i]=='\"')
|
||||
++instring;
|
||||
if(resource[i]=='\n')
|
||||
findnote=false;
|
||||
//when meeting '\n' the findnote is set to false then the next statement can be executed.
|
||||
if(resource[i]!='#' && !findnote)
|
||||
++i;
|
||||
else if(resource[i]=='#')
|
||||
{
|
||||
if(instring & 1)
|
||||
++i;
|
||||
else
|
||||
findnote=true;
|
||||
}
|
||||
if(fin.eof())
|
||||
break;
|
||||
}
|
||||
resource[i]='\0';
|
||||
fin.close();
|
||||
return;
|
||||
}
|
||||
void print_file()
|
||||
{
|
||||
if(!resource[0])
|
||||
{
|
||||
std::cout<<"0 null"<<std::endl;
|
||||
return;
|
||||
}
|
||||
int line=1;
|
||||
std::cout<<line<<" ";
|
||||
for(int i=0;i<16777216;++i)
|
||||
{
|
||||
if(!resource[i])
|
||||
break;
|
||||
std::cout<<resource[i];
|
||||
if(resource[i]=='\n')
|
||||
{
|
||||
++line;
|
||||
std::cout<<line<<" ";
|
||||
}
|
||||
}
|
||||
std::cout<<std::endl;
|
||||
return;
|
||||
}
|
||||
void del_file()
|
||||
{
|
||||
memset(resource,0,sizeof(char));
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
struct token
|
||||
{
|
||||
int line;
|
||||
int type;
|
||||
std::string content;
|
||||
};
|
||||
|
||||
class nasal_lexer
|
||||
{
|
||||
private:
|
||||
std::list<token> lexer;
|
||||
public:
|
||||
void scanner(int &syn,const char* source,std::string &__token,int &ptr,int &line)
|
||||
{
|
||||
char temp;
|
||||
temp=source[ptr];
|
||||
while(temp==' ' || temp=='\n' || temp=='\t' || temp=='\r' || temp<0 || temp>127)
|
||||
{
|
||||
++ptr;
|
||||
if(temp=='\n')
|
||||
++line;
|
||||
temp=source[ptr];
|
||||
}
|
||||
__token="";
|
||||
if(isLetter(temp) || temp=='_')
|
||||
{
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
while(isLetter(temp) || isNumber(temp) || temp=='_')
|
||||
{
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
}
|
||||
syn=isReserveWord(__token);
|
||||
if(syn==FAIL)
|
||||
syn=IDENTIFIER;
|
||||
else
|
||||
syn=RESERVEWORD;
|
||||
if((syn==IDENTIFIER) && source[ptr]=='.' && source[ptr+1]=='.' && source[ptr+2]=='.')
|
||||
{
|
||||
__token+="...";
|
||||
syn=DYNAMIC_ID;
|
||||
ptr+=3;
|
||||
}
|
||||
}
|
||||
else if(isNumber(temp))
|
||||
{
|
||||
if((source[ptr]=='0') && (source[ptr+1]=='x'))
|
||||
{
|
||||
__token+=source[ptr];
|
||||
__token+=source[ptr+1];
|
||||
ptr+=2;
|
||||
temp=source[ptr];
|
||||
while(isNumber(temp) || isHex(temp))
|
||||
{
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
}
|
||||
if((int)__token.length()==2)
|
||||
{
|
||||
std::cout<<">>[Lexer-warning] lexer: expect a hex-number string after '0x' ."<<std::endl;
|
||||
__token+="0";
|
||||
}
|
||||
}
|
||||
else if((source[ptr]=='0') && (source[ptr+1]=='o'))
|
||||
{
|
||||
__token+=source[ptr];
|
||||
__token+=source[ptr+1];
|
||||
ptr+=2;
|
||||
temp=source[ptr];
|
||||
while(isNumber(temp) || isOct(temp))
|
||||
{
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
}
|
||||
if((int)__token.length()==2)
|
||||
{
|
||||
std::cout<<">>[Lexer-warning] lexer: expect a oct-number string after '0o' ."<<std::endl;
|
||||
__token+="0";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int PointCnt=0;
|
||||
while(isNumber(temp))
|
||||
{
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
if(temp=='.' && !PointCnt)
|
||||
{
|
||||
++PointCnt;
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
}
|
||||
}
|
||||
}
|
||||
syn=NUMBER;
|
||||
}
|
||||
else if(temp=='(' || temp==')' || temp=='[' || temp==']' || temp=='{' ||
|
||||
temp=='}' || temp==',' || temp==';' || temp=='|' || temp==':' ||
|
||||
temp=='?' || temp=='.' || temp=='`' || temp=='&' || temp=='@' ||
|
||||
temp=='%' || temp=='$' || temp=='^')
|
||||
{
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
syn=OPERATOR;
|
||||
}
|
||||
else if(temp=='\'')
|
||||
{
|
||||
syn=STRING;
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
while(temp!='\'')
|
||||
{
|
||||
if(temp=='\\')
|
||||
{
|
||||
__token+=temp;
|
||||
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
__token+=temp;
|
||||
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
}
|
||||
else
|
||||
{
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
}
|
||||
if(temp==0 || temp=='\n')
|
||||
break;
|
||||
}
|
||||
//add the last char \"
|
||||
if(temp=='\'')
|
||||
{
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
}
|
||||
else
|
||||
__token+=" __missing_end_of_string";
|
||||
}
|
||||
else if(temp=='=' || temp=='+' || temp=='-' || temp=='*' || temp=='!' || temp=='/' || temp=='<' || temp=='>' || temp=='~')
|
||||
{
|
||||
syn=OPERATOR;
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
if(temp=='=')
|
||||
{
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
}
|
||||
}
|
||||
else if(temp=='\\')
|
||||
{
|
||||
syn=OPERATOR;
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
if(temp=='=' || temp=='n' || temp=='t' || temp=='r' || temp=='\\' || temp=='\'' || temp=='\"')
|
||||
{
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
}
|
||||
}
|
||||
else if(temp=='\"')
|
||||
{
|
||||
syn=STRING;
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
while(temp!='\"')
|
||||
{
|
||||
if(temp=='\\')
|
||||
{
|
||||
__token+=temp;
|
||||
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
__token+=temp;
|
||||
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
}
|
||||
else
|
||||
{
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
temp=source[ptr];
|
||||
}
|
||||
if(temp==0 || temp=='\n')
|
||||
break;
|
||||
}
|
||||
//add the last char \"
|
||||
if(temp=='\"')
|
||||
{
|
||||
__token+=temp;
|
||||
++ptr;
|
||||
}
|
||||
else
|
||||
__token+=" __missing_end_of_string";
|
||||
}
|
||||
else if(temp==0)
|
||||
{
|
||||
syn=SCANEND;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
syn=FAIL;
|
||||
std::cout<<">>[Error] unexpected error occurred: "<<temp<<std::endl;
|
||||
system("pause");
|
||||
++ptr;
|
||||
return;
|
||||
}
|
||||
if(__token=="")
|
||||
{
|
||||
syn=ERRORFOUND;
|
||||
std::cout<<">>[Error] cannot identify "<<std::endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
void lexer_process(const char *source)
|
||||
{
|
||||
std::cout<<">>[Lexer] max size: "<<lexer.max_size()<<" ."<<std::endl;
|
||||
lexer.clear();
|
||||
int syn=0;//token type
|
||||
int ptr=0;//pointer to one char in ResourcePrograme
|
||||
int line=1;
|
||||
std::string __token;
|
||||
token temp;
|
||||
while(syn!=SCANEND && syn!=ERRORFOUND)
|
||||
{
|
||||
scanner(syn,source,__token,ptr,line);
|
||||
if(syn>0)//all Syn type is larger than zero
|
||||
{
|
||||
temp.line=line;
|
||||
temp.type=syn;
|
||||
temp.content=__token;
|
||||
lexer.push_back(temp);
|
||||
}
|
||||
}
|
||||
std::cout<<">>[Lexer] complete scanning."<<std::endl;
|
||||
return;
|
||||
}
|
||||
void print_lexer()
|
||||
{
|
||||
token temp;
|
||||
for(std::list<token>::iterator i=lexer.begin();i!=lexer.end();++i)
|
||||
{
|
||||
temp=*i;
|
||||
std::cout<<"line "<<temp.line<<": ";
|
||||
if(temp.type==OPERATOR)
|
||||
std::cout<<"( Operator | ";
|
||||
else if(temp.type==IDENTIFIER)
|
||||
std::cout<<"( Identifier | ";
|
||||
else if(temp.type==NUMBER)
|
||||
std::cout<<"( Number | ";
|
||||
else if(temp.type==RESERVEWORD)
|
||||
std::cout<<"( ReserveWord | ";
|
||||
else if(temp.type==STRING)
|
||||
std::cout<<"( String | ";
|
||||
else if(temp.type==DYNAMIC_ID)
|
||||
std::cout<<"( Identifier | ";
|
||||
std::cout<<temp.content<<" )"<<std::endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
void token_list_type_detail_edit()
|
||||
{
|
||||
for(std::list<token>::iterator i=lexer.begin();i!=lexer.end();++i)
|
||||
{
|
||||
if((*i).type==RESERVEWORD)
|
||||
{
|
||||
if((*i).content=="var")
|
||||
(*i).type=__var;
|
||||
else if((*i).content=="func")
|
||||
(*i).type=__func;
|
||||
else if((*i).content=="return")
|
||||
(*i).type=__return;
|
||||
else if((*i).content=="nil")
|
||||
(*i).type=__number;
|
||||
else if((*i).content=="continue")
|
||||
(*i).type=__continue;
|
||||
else if((*i).content=="break")
|
||||
(*i).type=__break;
|
||||
else if((*i).content=="and")
|
||||
(*i).type=__and_operator;
|
||||
else if((*i).content=="or")
|
||||
(*i).type=__or_operator;
|
||||
else if((*i).content=="for")
|
||||
(*i).type=__for;
|
||||
else if((*i).content=="forindex")
|
||||
(*i).type=__forindex;
|
||||
else if((*i).content=="foreach")
|
||||
(*i).type=__foreach;
|
||||
else if((*i).content=="while")
|
||||
(*i).type=__while;
|
||||
else if((*i).content=="if")
|
||||
(*i).type=__if;
|
||||
else if((*i).content=="else")
|
||||
(*i).type=__else;
|
||||
else if((*i).content=="elsif")
|
||||
(*i).type=__elsif;
|
||||
}
|
||||
else if(((*i).content=="==") || ((*i).content=="!=") || ((*i).content==">") || ((*i).content==">=") || ((*i).content=="<") || ((*i).content=="<="))
|
||||
{
|
||||
if((*i).content=="==")
|
||||
(*i).type=__cmp_equal;
|
||||
else if((*i).content=="!=")
|
||||
(*i).type=__cmp_not_equal;
|
||||
else if((*i).content==">")
|
||||
(*i).type=__cmp_more;
|
||||
else if((*i).content==">=")
|
||||
(*i).type=__cmp_more_or_equal;
|
||||
else if((*i).content=="<")
|
||||
(*i).type=__cmp_less;
|
||||
else if((*i).content=="<=")
|
||||
(*i).type=__cmp_less_or_equal;
|
||||
}
|
||||
else if(((*i).content==";") || ((*i).content==",") || ((*i).content=="=") || ((*i).content==":") || ((*i).content==".") || ((*i).content=="?") || ((*i).content=="|") || ((*i).content=="&") || ((*i).content=="%") || ((*i).content=="$") || ((*i).content=="`") || ((*i).content=="^") || ((*i).content=="@"))
|
||||
{
|
||||
char c=(*i).content[0];
|
||||
switch(c)
|
||||
{
|
||||
case ';':(*i).type=__semi;break;
|
||||
case ',':(*i).type=__comma;break;
|
||||
case '=':(*i).type=__equal;break;
|
||||
case ':':(*i).type=__colon;break;
|
||||
case '.':(*i).type=__dot;break;
|
||||
default:(*i).type=__unknown_operator;break;
|
||||
}
|
||||
}
|
||||
else if(((*i).type==NUMBER) || ((*i).type==STRING) || ((*i).type==IDENTIFIER) || ((*i).type==DYNAMIC_ID))
|
||||
{
|
||||
int t=(*i).type;
|
||||
switch(t)
|
||||
{
|
||||
case NUMBER:(*i).type=__number;break;
|
||||
case STRING:(*i).type=__string;break;
|
||||
case IDENTIFIER:(*i).type=__id;break;
|
||||
case DYNAMIC_ID:(*i).type=__dynamic_id;break;
|
||||
}
|
||||
}
|
||||
else if(((*i).content=="+") || ((*i).content=="-") || ((*i).content=="*") || ((*i).content=="/") || ((*i).content=="~") || ((*i).content=="!"))
|
||||
{
|
||||
char c=(*i).content[0];
|
||||
switch(c)
|
||||
{
|
||||
case '+':(*i).type=__add_operator;break;
|
||||
case '-':(*i).type=__sub_operator;break;
|
||||
case '*':(*i).type=__mul_operator;break;
|
||||
case '/':(*i).type=__div_operator;break;
|
||||
case '~':(*i).type=__link_operator;break;
|
||||
case '!':(*i).type=__nor_operator;break;
|
||||
}
|
||||
}
|
||||
else if(((*i).content=="+=") || ((*i).content=="-=") || ((*i).content=="*=") || ((*i).content=="/=") || ((*i).content=="~="))
|
||||
{
|
||||
char c=(*i).content[0];
|
||||
switch(c)
|
||||
{
|
||||
case '+':(*i).type=__add_equal;break;
|
||||
case '-':(*i).type=__sub_equal;break;
|
||||
case '*':(*i).type=__mul_equal;break;
|
||||
case '/':(*i).type=__div_equal;break;
|
||||
case '~':(*i).type=__link_equal;break;
|
||||
}
|
||||
}
|
||||
else if(((*i).content=="(") || ((*i).content==")") || ((*i).content=="[") || ((*i).content=="]") || ((*i).content=="{") || ((*i).content=="}"))
|
||||
{
|
||||
char c=(*i).content[0];
|
||||
switch(c)
|
||||
{
|
||||
case '(':(*i).type=__left_curve;break;
|
||||
case ')':(*i).type=__right_curve;break;
|
||||
case '[':(*i).type=__left_bracket;break;
|
||||
case ']':(*i).type=__right_bracket;break;
|
||||
case '{':(*i).type=__left_brace;break;
|
||||
case '}':(*i).type=__right_brace;break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
std::list<token>& return_list()
|
||||
{
|
||||
return lexer;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -1,118 +0,0 @@
|
|||
#ifndef __NASAL_TOKEN_TYPE_H__
|
||||
#define __NASAL_TOKEN_TYPE_H__
|
||||
|
||||
#include <cstring>
|
||||
|
||||
enum token_type
|
||||
{
|
||||
__stack_end=1,
|
||||
__equal, // =
|
||||
__cmp_equal,__cmp_not_equal, // == !=
|
||||
__cmp_less,__cmp_less_or_equal, // < <=
|
||||
__cmp_more,__cmp_more_or_equal, // > >=
|
||||
__and_operator,__or_operator,__nor_operator, // and or !
|
||||
__add_operator,__sub_operator, // + -
|
||||
__mul_operator,__div_operator,__link_operator, // * / ~
|
||||
__add_equal,__sub_equal, // += -=
|
||||
__mul_equal,__div_equal,__link_equal, // *= /= ~=
|
||||
__left_brace,__right_brace, // {}
|
||||
__left_bracket,__right_bracket, // []
|
||||
__left_curve,__right_curve, // ()
|
||||
__semi,__comma,__colon,__dot, // ; , : .
|
||||
__unknown_operator,
|
||||
__var,__func,__return,
|
||||
__if,__elsif,__else,
|
||||
__continue,__break,
|
||||
__for,__forindex,__foreach,__while,
|
||||
//operators & reserve words
|
||||
|
||||
__number,__string,__id,__dynamic_id,
|
||||
//basic elements
|
||||
|
||||
__root,
|
||||
__null_type,
|
||||
__list,__hash,
|
||||
__hash_member,
|
||||
__call_function,__list_search,__hash_search,
|
||||
__normal_statement_block,
|
||||
__definition,__assignment,
|
||||
__function,__loop,__ifelse
|
||||
};
|
||||
|
||||
void print_token(int type)
|
||||
{
|
||||
std::string context="";
|
||||
switch(type)
|
||||
{
|
||||
case __stack_end: context="#"; break;
|
||||
case __equal: context="="; break;
|
||||
case __cmp_equal: context="==";break;
|
||||
case __cmp_not_equal: context="!=";break;
|
||||
case __cmp_less: context="<"; break;
|
||||
case __cmp_less_or_equal: context="<=";break;
|
||||
case __cmp_more: context=">"; break;
|
||||
case __cmp_more_or_equal: context=">=";break;
|
||||
case __and_operator: context="and";break;
|
||||
case __or_operator: context="or"; break;
|
||||
case __nor_operator: context="!"; break;
|
||||
case __add_operator: context="+"; break;
|
||||
case __sub_operator: context="-"; break;
|
||||
case __mul_operator: context="*"; break;
|
||||
case __div_operator: context="/"; break;
|
||||
case __link_operator: context="~"; break;
|
||||
case __add_equal: context="+=";break;
|
||||
case __sub_equal: context="-=";break;
|
||||
case __mul_equal: context="*=";break;
|
||||
case __div_equal: context="/=";break;
|
||||
case __link_equal: context="~=";break;
|
||||
case __left_brace: context="{"; break;
|
||||
case __right_brace: context="}"; break;
|
||||
case __left_bracket: context="["; break;
|
||||
case __right_bracket: context="]"; break;
|
||||
case __left_curve: context="("; break;
|
||||
case __right_curve: context=")"; break;
|
||||
case __semi: context=";"; break;
|
||||
case __comma: context=","; break;
|
||||
case __colon: context=":"; break;
|
||||
case __dot: context="."; break;
|
||||
case __unknown_operator: context="unknown_operator";break;
|
||||
case __var: context="var"; break;
|
||||
case __func: context="func";break;
|
||||
case __continue: context="continye"; break;
|
||||
case __break: context="break"; break;
|
||||
case __for: context="for"; break;
|
||||
case __forindex: context="forindex";break;
|
||||
case __foreach: context="foreach";break;
|
||||
case __while: context="while";break;
|
||||
case __if: context="if";break;
|
||||
case __elsif: context="elsif";break;
|
||||
case __else: context="else";break;
|
||||
case __return: context="return";break;
|
||||
|
||||
case __id: context="id";break;
|
||||
case __dynamic_id: context="id...";break;
|
||||
case __number: context="num";break;
|
||||
case __string: context="str";break;
|
||||
|
||||
case __root: context="root";break;
|
||||
case __null_type: context="null_type";break;
|
||||
case __list: context="list";break;
|
||||
case __hash: context="hash";break;
|
||||
case __hash_member: context="hash_member";break;
|
||||
case __call_function: context="call_func";break;
|
||||
case __list_search: context="call_list";break;
|
||||
case __hash_search: context="call_hash";break;
|
||||
case __normal_statement_block:context="block";break;
|
||||
case __definition: context="definition";break;
|
||||
case __assignment: context="assignment";break;
|
||||
case __function: context="function";break;
|
||||
case __loop: context="loop";break;
|
||||
case __ifelse: context="if-else";break;
|
||||
default: context="undefined_token";break;
|
||||
}
|
||||
std::cout<<context;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -1,260 +0,0 @@
|
|||
#ifndef __NASAL_VM_H__
|
||||
#define __NASAL_VM_H__
|
||||
|
||||
class var
|
||||
{
|
||||
private:
|
||||
int type;
|
||||
std::string name;
|
||||
double number;
|
||||
std::string str;
|
||||
std::list<var> var_list;
|
||||
std::list<var> var_hash;
|
||||
abstract_syntax_tree function;
|
||||
public:
|
||||
var()
|
||||
{
|
||||
type=0;
|
||||
name="";
|
||||
number=0;
|
||||
str="";
|
||||
function.set_clear();
|
||||
}
|
||||
var(const var& p)
|
||||
{
|
||||
type=p.type;
|
||||
name=p.name;
|
||||
number=p.number;
|
||||
str=p.str;
|
||||
function=p.function;
|
||||
}
|
||||
var& operator=(const var& p)
|
||||
{
|
||||
type=p.type;
|
||||
name=p.name;
|
||||
number=p.number;
|
||||
str=p.str;
|
||||
function=p.function;
|
||||
return *this;
|
||||
}
|
||||
void print_information()
|
||||
{
|
||||
std::cout<<"[ type: ";print_token(type);std::cout<<" ]";
|
||||
std::cout<<"[ name: "<<name<<" ]";
|
||||
std::cout<<"[ number: "<<number<<" ]";
|
||||
std::cout<<"[ string: "<<str<<" ]"<<std::endl;
|
||||
std::cout<<"[ function: ";
|
||||
function.print_tree(1);
|
||||
std::cout<<" ]"<<std::endl;
|
||||
return;
|
||||
}
|
||||
void print_detail()
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case __function:
|
||||
std::cout<<std::endl<<">>[Runtime-error] function type cannot be printed."<<std::endl;
|
||||
break;
|
||||
case __number:
|
||||
std::cout<<number;
|
||||
break;
|
||||
case __string:
|
||||
for(int i=1;i<str.length()-1;++i)
|
||||
{
|
||||
if(str[i]!='\\')
|
||||
std::cout<<str[i];
|
||||
else
|
||||
{
|
||||
switch(str[i+1])
|
||||
{
|
||||
case 'n':std::cout<<"\n";++i;break;
|
||||
case 't':std::cout<<"\t";++i;break;
|
||||
case 'r':std::cout<<"\r";++i;break;
|
||||
case '\\':std::cout<<"\\";++i;break;
|
||||
case '\'':std::cout<<"\'";++i;break;
|
||||
case '\"':std::cout<<"\"";++i;break;
|
||||
default:std::cout<<"\\";break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
void set_type(const int var_type)
|
||||
{
|
||||
type=var_type;
|
||||
return;
|
||||
}
|
||||
void set_name(std::string var_name_str)
|
||||
{
|
||||
name=var_name_str;
|
||||
return;
|
||||
}
|
||||
void set_number(const double var_number)
|
||||
{
|
||||
number=var_number;
|
||||
return;
|
||||
}
|
||||
void set_string(std::string s)
|
||||
{
|
||||
str=s;
|
||||
return;
|
||||
}
|
||||
void set_function(abstract_syntax_tree func)
|
||||
{
|
||||
function=func;
|
||||
return;
|
||||
}
|
||||
void set_list(std::list<var> p)
|
||||
{
|
||||
var_list=p;
|
||||
return;
|
||||
}
|
||||
void append_list(var p)
|
||||
{
|
||||
var_list.push_back(p);
|
||||
return;
|
||||
}
|
||||
void set_hash(std::list<var> p)
|
||||
{
|
||||
var_hash=p;
|
||||
return;
|
||||
}
|
||||
void append_hash(var p)
|
||||
{
|
||||
var_hash.push_back(p);
|
||||
return;
|
||||
}
|
||||
int get_type()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
std::string get_name()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
double get_number()
|
||||
{
|
||||
return number;
|
||||
}
|
||||
std::string get_string()
|
||||
{
|
||||
return str;
|
||||
}
|
||||
abstract_syntax_tree get_function()
|
||||
{
|
||||
return function;
|
||||
}
|
||||
std::list<var> get_list()
|
||||
{
|
||||
return var_list;
|
||||
}
|
||||
std::list<var> get_hash()
|
||||
{
|
||||
return var_hash;
|
||||
}
|
||||
};
|
||||
|
||||
class var_scope_manager
|
||||
{
|
||||
private:
|
||||
std::list<std::list<var> > scope_list;
|
||||
var error_var;
|
||||
public:
|
||||
var_scope_manager()
|
||||
{
|
||||
scope_list.clear();
|
||||
std::string str="__nas_strc_lang_error_ret";
|
||||
error_var.set_name(str);
|
||||
error_var.set_type(__null_type);
|
||||
return;
|
||||
}
|
||||
void set_clear()
|
||||
{
|
||||
scope_list.clear();
|
||||
return;
|
||||
}
|
||||
var& search_var(std::string str)
|
||||
{
|
||||
std::list<std::list<var>>::iterator i=scope_list.end();
|
||||
--i;
|
||||
for(;;--i)
|
||||
{
|
||||
for(std::list<var>::iterator j=i->begin();j!=i->end();++j)
|
||||
if(j->get_name()==str)
|
||||
return *j;
|
||||
if(i==scope_list.begin())
|
||||
break;
|
||||
}
|
||||
std::cout<<std::endl<<">>[Runtime-error] could not find the var '"<<str<<"' ."<<std::endl;
|
||||
return error_var;
|
||||
}
|
||||
void add_var(var new_var)
|
||||
{
|
||||
if(scope_list.empty())
|
||||
{
|
||||
std::cout<<std::endl<<">>[Runtime-error] empty scope list."<<std::endl;
|
||||
return;
|
||||
}
|
||||
std::list<std::list<var>>::iterator i=scope_list.end();
|
||||
--i;
|
||||
for(std::list<var>::iterator j=i->begin();j!=i->end();++j)
|
||||
{
|
||||
if(j->get_name()==new_var.get_name())
|
||||
{
|
||||
std::cout<<std::endl<<">>[Runtime-error] redeclaration of var '"<<new_var.get_name()<<"' ."<<std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
i->push_back(new_var);
|
||||
return;
|
||||
}
|
||||
void add_new_scope()
|
||||
{
|
||||
std::list<var> new_list;
|
||||
scope_list.push_back(new_list);
|
||||
return;
|
||||
}
|
||||
void pop_last_scope()
|
||||
{
|
||||
if(!scope_list.empty())
|
||||
scope_list.pop_back();
|
||||
else
|
||||
std::cout<<std::endl<<">>[Runtime-error] scope poped empty thing."<<std::endl;
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
class nasal_vm
|
||||
{
|
||||
private:
|
||||
abstract_syntax_tree root;
|
||||
var_scope_manager scope;
|
||||
public:
|
||||
nasal_vm()
|
||||
{
|
||||
root.set_clear();
|
||||
return;
|
||||
}
|
||||
void run()
|
||||
{
|
||||
std::cout<<">>[Runtime] process begins."<<std::endl;
|
||||
int time_beg,time_end;
|
||||
time_beg=time(NULL);
|
||||
scope.set_clear();
|
||||
|
||||
time_end=time(NULL);
|
||||
std::cout<<std::endl<<">>[Runtime] process exited after "<<time_beg-time_end<<" sec(s)."<<std::endl;
|
||||
return;
|
||||
}
|
||||
void set_root(abstract_syntax_tree& tree)
|
||||
{
|
||||
root.set_clear();
|
||||
root=tree;
|
||||
std::cout<<">>[Runtime] runtime got the ast-root: "<<((void *)&tree)<<"->"<<((void *)&root)<<"."<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
};
|
||||
#endif
|
|
@ -1,172 +0,0 @@
|
|||
# nasal lib base.nas
|
||||
# 2020/2/4
|
||||
# this file is used to avoid name confliction
|
||||
# and is used to avoid name undefined
|
||||
# before running this file will be translated to abstract syntax tree
|
||||
# and this ast will be linked before main ast as main-ast's beginning
|
||||
|
||||
# append
|
||||
# The first argument specifies a vector.
|
||||
# Appends the remaining arguments to the end of the vector.
|
||||
var append=func(vector,elements...)
|
||||
{
|
||||
nasal_call_builtin_push_back(vector,elements);
|
||||
return nil;
|
||||
}
|
||||
|
||||
# setsize
|
||||
# Sets the size of a vector.
|
||||
# The first argument specifies a vector, the second a number representing the desired size of that vector.
|
||||
# If the vector is currently larger than the specified size,it is truncated.
|
||||
# If it is smaller, it is padded with nil entries.Returns the vector operated upon.
|
||||
var setsize=func(vector,__size)
|
||||
{
|
||||
nasal_call_builtin_set_size(vector,__size);
|
||||
return nil;
|
||||
}
|
||||
|
||||
# subvec
|
||||
# Returns a sub-range of a vector.
|
||||
# The first argument specifies a vector, the second a starting index,
|
||||
# and the optional third argument indicates a length (the default is to the end of the vector).
|
||||
var subvec=func(vector,start,length=nil)
|
||||
{
|
||||
return nasal_call_builtin_subvec(vector,start,length);
|
||||
}
|
||||
|
||||
# contains
|
||||
# The first argument specifies a hash, the second must be a scalar.
|
||||
# Returns 1 if the hash contains the scalar as a key, 0 if not.
|
||||
var contains=func(hash,key)
|
||||
{
|
||||
return nasal_call_builtin_contains(hash,key);
|
||||
}
|
||||
|
||||
# delete
|
||||
# The first argument specifies a hash, the second must be a scalar key.
|
||||
# Deletes the key from the hash if it exists.
|
||||
# Operationally, this is identical to setting the hash value specified by the key to nil,
|
||||
# but this variant potentially frees storage by deleting the reference to the key and by shrinking the hash.
|
||||
var delete=func(hash,key)
|
||||
{
|
||||
nasal_call_builtin_delete(hash,key);
|
||||
return;
|
||||
}
|
||||
|
||||
# int
|
||||
# Returns the integer part of the numeric value of the single argument, or nil if none exists.
|
||||
# Truncates towards zero, not negative infinity (i.e. it's implemented in C as a double tointeger typecast).
|
||||
var int=func(value)
|
||||
{
|
||||
return nasal_call_builtin_trans_int(value);
|
||||
}
|
||||
|
||||
# num
|
||||
# Returns the numeric value of the single argument, or nil if none exists.
|
||||
var num=func(value)
|
||||
{
|
||||
return nasal_call_builtin_trans_num(value);
|
||||
}
|
||||
|
||||
# keys
|
||||
# Returns a vector containing the list of keys found in the single hash argument.
|
||||
var keys=func(hash)
|
||||
{
|
||||
return nasal_call_builtin_get_keys(hash);
|
||||
}
|
||||
|
||||
# pop
|
||||
# Removes and returns the last element of the single vector argument.
|
||||
var pop=func(vector)
|
||||
{
|
||||
return nasal_call_builtin_pop_back(vector);
|
||||
}
|
||||
|
||||
# size
|
||||
# Returns the size of the single argument.
|
||||
# For strings, this is the length in bytes.
|
||||
# For vectors, this is the number of elements.
|
||||
# For hashes, it is the number of key/value pairs.
|
||||
# Returns nil for number and nil arguments.
|
||||
var size=func(object)
|
||||
{
|
||||
return nasal_call_builtin_sizeof(object);
|
||||
}
|
||||
|
||||
# streq
|
||||
# Tests the string values of the two arguments for equality.
|
||||
# Needed because the == operator in Nasal tests for numeric equality, as in perl.
|
||||
# So "0" == "0.0" is true,but streq("0", "0.0") is false.
|
||||
# This is rarely required in typical code.
|
||||
var streq=func(__a,__b)
|
||||
{
|
||||
return nasal_call_builtin_str_cmp_equal(__a,__b);
|
||||
}
|
||||
|
||||
# cmp
|
||||
# Compares two strings, returning -1 if a is less than b, 0 if theyare identical, and 1 if a is greater than b.
|
||||
var cmp=func(__a,__b)
|
||||
{
|
||||
return nasal_call_builtin_cmp(__a,__b);
|
||||
}
|
||||
|
||||
# sort
|
||||
# Creates a new vector containing the elements in the input vector sorted in ascending order according to the rule givenby function,
|
||||
# which takes two arguments (elements of the input vector) and should return less than zero, zero, or greater than zero if the first argument is,
|
||||
# respectively, less than, equal to, or greater than the second argument. Despite being implemented with ANSI C qsort(),
|
||||
# the sort is stable; "equal" elements in the output vector will appear in the same relative order as they do in the input.
|
||||
var sort=func(vector,function)
|
||||
{
|
||||
nasal_call_builtin_cpp_sort(vector,function);
|
||||
return;
|
||||
}
|
||||
|
||||
# substr
|
||||
# Computes a substring.
|
||||
# The first argument specifes a string, the second is an integer index of the start of a substring,
|
||||
# the optional third argument specifies a length (the default is to return the remaining string).
|
||||
# Example: substr("abcde", 1, 3) returns "bcd".
|
||||
var substr=func(__string,start,length=nil)
|
||||
{
|
||||
return nasal_call_builtin_substr(__string,start,length);
|
||||
}
|
||||
|
||||
# sprintf
|
||||
# Creates and returns a string formatted as per ANSI C sprintf().
|
||||
var sprintf=func(__format,var_args...)
|
||||
{
|
||||
return nasal_call_builtin_sprintf(__format,var_args);
|
||||
}
|
||||
|
||||
# find
|
||||
# Finds and returns the index of the first occurence of the string needle in the string haystack, or -1 if no such occurence was found.
|
||||
var find=func(needle,haystack)
|
||||
{
|
||||
return nasal_call_builtin_find_first_occur(needle,haystack);
|
||||
}
|
||||
|
||||
# split
|
||||
# Splits the input string into a vector of substrings bounded by occurences of the delimeter substring.
|
||||
var split=func(delimeter,__string)
|
||||
{
|
||||
return nasal_call_builtin_split(delimeter,__string);
|
||||
}
|
||||
|
||||
# rand
|
||||
# Returns a random number in the range [0:1) (that is, 0.0 is a possible return value. 1.0 is not).
|
||||
# If a numeric argument is specified, it is used as a seed instead and the function returns nil.
|
||||
# Implemented in terms of the C library's rand/srand functions;
|
||||
# the result should have a full double-precision number's worth of randomness even on systems with a 15 bit rand().
|
||||
var rand=func(seed=nil)
|
||||
{
|
||||
return nasal_call_builtin_rand(seed);
|
||||
}
|
||||
|
||||
# id
|
||||
# Returns a unique string identifying the object.
|
||||
# Two id strings are equal if and only if the two references point to the same object in memory.
|
||||
# Numbers don't have id's and will cause a runtime error if passed to id().
|
||||
var id=func(thing)
|
||||
{
|
||||
return nasal_call_builtin_get_id(thing);
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
# nasal lib bits.nas
|
||||
# 2020/2/8
|
||||
# this file is used to avoid name confliction
|
||||
# and is used to avoid name undefined
|
||||
# before running this file will be translated to abstract syntax tree
|
||||
# and this ast will be linked before main ast as main-ast's beginning
|
||||
|
||||
var bits=
|
||||
{
|
||||
# Interpreting the string str as bits,
|
||||
# returns the bitfield of the specified length starting at startbit.
|
||||
# Interprets the result as an unsigned integer.
|
||||
# The bit order is bytewise big endian: The 0th bit is the high bit of the first byte.
|
||||
# The last bit is the low bit of the last byte in the string.
|
||||
fld:func(__string,startbit,length)
|
||||
{
|
||||
return nasal_call_builtin_bitcalc(__string,startbit,length);
|
||||
},
|
||||
# As bits.fld(), but interprets the result as a 2's complement signed value.
|
||||
sfld:func(__string,startbit,length)
|
||||
{
|
||||
return nasal_call_builtin_sbitcalc(__string,startbit,length);
|
||||
},
|
||||
# Sets the specified value into the bit string at the specified position.
|
||||
# The string must be mutable: either the result of a runtime concatenation (the ~ operator) or a call to bits.buf()(see below).
|
||||
# Attempts to modify immutable strings (e.g. compile time constants) will produce a runtime error.
|
||||
setfld:func(__string,startbit,length,value)
|
||||
{
|
||||
return nasal_call_builtin_setbit(__string,startbit,length,value);
|
||||
},
|
||||
# Returns a zero-filled mutable string of the specified length.
|
||||
buf:func(length)
|
||||
{
|
||||
return nasal_call_builtin_null_string_gen(length);
|
||||
},
|
||||
};
|
|
@ -1,74 +0,0 @@
|
|||
# nasal lib io.nas
|
||||
# 2020/2/8
|
||||
# this file is used to avoid name confliction
|
||||
# and is used to avoid name undefined
|
||||
# before running this file will be translated to abstract syntax tree
|
||||
# and this ast will be linked before main ast as main-ast's beginning
|
||||
|
||||
var io=
|
||||
{
|
||||
# Opens the file with the specified mode (as per ANSI fopen()) and returns a ghost object representing the filehandle.
|
||||
# Failures are thrown as runtime errors as per die().
|
||||
open:func(filename,mode="r")
|
||||
{
|
||||
return nasal_call_builtin_c_fopen(filename,mode);
|
||||
},
|
||||
# Closes the specified file as per ANSI fclose().
|
||||
close:func(filehandle)
|
||||
{
|
||||
nasal_call_builtin_c_fclose(filehandle);
|
||||
return;
|
||||
},
|
||||
# Attempts to read length bytes from the filehandle into the beginning of the mutable string buf.
|
||||
# Failures (including overruns when length > size(buf)) are thrown as runtime errors as per die().
|
||||
# Returns the number of bytes successfully read.
|
||||
read:func(filehandle,buf,length)
|
||||
{
|
||||
return nasal_call_builtin_c_read(filehandle,buf,length);
|
||||
},
|
||||
# Attempts to write the entirety of the specified string to the filehandle.
|
||||
# Failures are thrown as runtime errors as per die().
|
||||
# Returns the number of bytes successfully written.
|
||||
write:func(filehandle,str)
|
||||
{
|
||||
return nasal_call_builtin_c_write(filehandle,str);
|
||||
},
|
||||
# As ANSI fseek().
|
||||
# Attempts to seek to the specified position based on the whence value
|
||||
# (which must be one of io.SEEK_SET,io.SEEK_END, or io.SEEK_CUR)
|
||||
SEEK_SET:1,
|
||||
SEEK_CUR:2,
|
||||
SEEK_END:3,
|
||||
seek:func(filehandle,position,whence)
|
||||
{
|
||||
nasal_call_builtin_c_seek(filehandle,position,whence);
|
||||
return;
|
||||
},
|
||||
# Returns the current seek position of the filehandle.
|
||||
tell:func(filehandle)
|
||||
{
|
||||
return nasal_call_builtin_c_tell(filehandle);
|
||||
},
|
||||
# Reads and returns a single text line from the filehandle.
|
||||
# Interprets both "\n" and "\r\n" as end of line markers,
|
||||
# and does not include the "\r" or "\n" bytes in the returned string.
|
||||
# End offile or error is signaled by returning nil.
|
||||
readln:func(filehandle)
|
||||
{
|
||||
return nasal_call_builtin_builtin_c_getline(filehandle);
|
||||
},
|
||||
# Calls unix or win32 stat() on the specified file name and
|
||||
# returns a seven element array whose contents are,
|
||||
# in order: dev, ino, mode,nlink, uid, gid, rdef, size, atime, mtime, ctime.
|
||||
# Errors are signaled as exceptions as per die().
|
||||
stat:func(filename)
|
||||
{
|
||||
return nasal_call_builtin_builtin_stat(filename);
|
||||
},
|
||||
};
|
||||
|
||||
var print=func(dyn...)
|
||||
{
|
||||
nasal_call_builtin_c_std_puts(dyn);
|
||||
return nil;
|
||||
};
|
|
@ -1,49 +0,0 @@
|
|||
# nasal lib math.nas
|
||||
# 2020/2/8
|
||||
# this file is used to avoid name confliction
|
||||
# and is used to avoid name undefined
|
||||
# before running this file will be translated to abstract syntax tree
|
||||
# and this ast will be linked before main ast as main-ast's beginning
|
||||
|
||||
var math=
|
||||
{
|
||||
# Euler's constant
|
||||
e:2.7182818284590452354,
|
||||
pi:3.14159265358979323846,
|
||||
# Returns the sine of the single argument
|
||||
sin:func(x)
|
||||
{
|
||||
return nasal_call_builtin_sin(x);
|
||||
},
|
||||
# Returns the cosine of the single argument
|
||||
cos:func(x)
|
||||
{
|
||||
return nasal_call_builtin_cos(x);
|
||||
},
|
||||
# you know what the f*ck this is
|
||||
tan:func(x)
|
||||
{
|
||||
return nasal_call_builtin_tan(x);
|
||||
},
|
||||
# Returns e (Euler's constant) raised to the power specified by the single argument
|
||||
exp:func(x)
|
||||
{
|
||||
return nasal_call_builtin_exp(x);
|
||||
},
|
||||
# Returns the natural logarithm of the single argument.
|
||||
ln:func(x)
|
||||
{
|
||||
return nasal_call_builtin_cpp_math_ln(x);
|
||||
},
|
||||
# Returns the square root of the single argument.
|
||||
sqrt:func(x)
|
||||
{
|
||||
return nasal_call_builtin_cpp_math_sqrt(x);
|
||||
},
|
||||
# Returns the arctangent of y/x, with the correct sign for the quadrant.
|
||||
# Wraps the ANSI C function of the same name.
|
||||
atan2:func(x,y)
|
||||
{
|
||||
return nasal_call_builtin_cpp_atan2(x,y);
|
||||
},
|
||||
};
|
|
@ -1,12 +0,0 @@
|
|||
# nasal lib readline.nas
|
||||
# 2020/2/6
|
||||
# this file is used to avoid name confliction
|
||||
# and is used to avoid name undefined
|
||||
# before running this file will be translated to abstract syntax tree
|
||||
# and this ast will be linked before main ast as main-ast's beginning
|
||||
|
||||
# GNU Readline Library
|
||||
var readline=func(prompt="> ")
|
||||
{
|
||||
return;
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
# nasal lib regex.nas
|
||||
# 2020/2/6
|
||||
# this file is used to avoid name confliction
|
||||
# and is used to avoid name undefined
|
||||
# before running this file will be translated to abstract syntax tree
|
||||
# and this ast will be linked before main ast as main-ast's beginning
|
||||
|
||||
var regex=
|
||||
{
|
||||
comp:func(){},
|
||||
exec:func(){},
|
||||
};
|
|
@ -1,15 +0,0 @@
|
|||
# nasal lib sqlite.nas
|
||||
# 2020/2/6
|
||||
# this file is used to avoid name confliction
|
||||
# and is used to avoid name undefined
|
||||
# before running this file will be translated to abstract syntax tree
|
||||
# and this ast will be linked before main ast as main-ast's beginning
|
||||
|
||||
var sqlite=
|
||||
{
|
||||
open:func(){},
|
||||
close:func(){},
|
||||
prepare:func(){},
|
||||
exec:func(){},
|
||||
finalize:func(){},
|
||||
};
|
|
@ -1,9 +0,0 @@
|
|||
var system=
|
||||
{
|
||||
# print the type of thing on the screen
|
||||
type:func(thing)
|
||||
{
|
||||
nasal_call_builtin_scalar_type(thing);
|
||||
return;
|
||||
}
|
||||
};
|
|
@ -1,17 +0,0 @@
|
|||
# nasal lib thread.nas
|
||||
# 2020/2/6
|
||||
# this file is used to avoid name confliction
|
||||
# and is used to avoid name undefined
|
||||
# before running this file will be translated to abstract syntax tree
|
||||
# and this ast will be linked before main ast as main-ast's beginning
|
||||
|
||||
var thread=
|
||||
{
|
||||
newthread:func(){},
|
||||
newlock:func(){},
|
||||
lock:func(){},
|
||||
unlock:func(){},
|
||||
newsem:func(){},
|
||||
semdown:func(){},
|
||||
semup:func(){},
|
||||
};
|
|
@ -1,22 +0,0 @@
|
|||
# nasal lib unix.nas
|
||||
# 2020/2/6
|
||||
# this file is used to avoid name confliction
|
||||
# and is used to avoid name undefined
|
||||
# before running this file will be translated to abstract syntax tree
|
||||
# and this ast will be linked before main ast as main-ast's beginning
|
||||
|
||||
var unix=
|
||||
{
|
||||
pipe:func(){},
|
||||
fork:func(){},
|
||||
dup2:func(){},
|
||||
exec:func(){},
|
||||
waitpid:func(){},
|
||||
opendir:func(){},
|
||||
readdir:func(){},
|
||||
closedir:func(){},
|
||||
time:func(){},
|
||||
chdir:func(){},
|
||||
environ:func(){},
|
||||
sleep:func(){},
|
||||
};
|
|
@ -1,15 +0,0 @@
|
|||
# nasal lib utf8.nas
|
||||
# 2020/2/6
|
||||
# this file is used to avoid name confliction
|
||||
# and is used to avoid name undefined
|
||||
# before running this file will be translated to abstract syntax tree
|
||||
# and this ast will be linked before main ast as main-ast's beginning
|
||||
|
||||
var utf8=
|
||||
{
|
||||
chstr:func(){},
|
||||
strc:func(){},
|
||||
substr:func(){},
|
||||
size:func(){},
|
||||
validate:func(){},
|
||||
};
|
|
@ -1,195 +0,0 @@
|
|||
#include "nasal.h"
|
||||
|
||||
// source code will be put in resource
|
||||
resource_file resource;
|
||||
// source code will be generated to tokens in lexer
|
||||
nasal_lexer lexer;
|
||||
// token list will be checked in parser and output the abstract syntax tree
|
||||
nasal_parse parser;
|
||||
// libroot stores the ast of lib file
|
||||
abstract_syntax_tree libroot;
|
||||
// root stores the ast of source code
|
||||
abstract_syntax_tree root;
|
||||
// executable_ast generates libroot and root together
|
||||
// this ast will be sent into nasal runtime
|
||||
abstract_syntax_tree executable_ast;
|
||||
// main process is running here
|
||||
nasal_runtime runtime;
|
||||
|
||||
// command is used in main()
|
||||
std::string command;
|
||||
int main()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// use chcp 65001 to use unicode io
|
||||
system("chcp 65001");
|
||||
#endif
|
||||
// this curve looks really cool
|
||||
std::cout<<" __ _ "<<std::endl;
|
||||
std::cout<<" /\\ \\ \\__ _ ___ __ _| | "<<std::endl;
|
||||
std::cout<<" / \\/ / _` / __|/ _` | | "<<std::endl;
|
||||
std::cout<<" / /\\ / (_| \\__ \\ (_| | | "<<std::endl;
|
||||
std::cout<<" \\_\\ \\/ \\__,_|___/\\__,_|_|"<<std::endl;
|
||||
#ifdef _WIN32
|
||||
std::cout<<">> [system] Windows system."<<std::endl;
|
||||
#endif
|
||||
#ifdef _linux_
|
||||
std::cout<<">> [system] Linux system."<<std::endl;
|
||||
#endif
|
||||
#ifdef TARGET_OS_MAC
|
||||
std::cout<<">> [system] MacOS system."<<std::endl;
|
||||
#endif
|
||||
std::cout<<">> Nasal interpreter ver 2.0 ."<<std::endl;
|
||||
std::cout<<">> Code: https://github.com/ValKmjolnir/Nasal-Interpreter"<<std::endl;
|
||||
std::cout<<">> More info: http://wiki.flightgear.org/Nasal_scripting_language"<<std::endl;
|
||||
std::cout<<">> Input \"help\" to get help ."<<std::endl;
|
||||
while(1)
|
||||
{
|
||||
std::cout<<">> ";
|
||||
std::cin>>command;
|
||||
if(command=="help")
|
||||
{
|
||||
std::cout<<">> [\'file\'] input a file."<<std::endl;
|
||||
std::cout<<">> [cls ] clear the screen."<<std::endl;
|
||||
std::cout<<">> [del ] clear the resource code."<<std::endl;
|
||||
std::cout<<">> [lib ] add lib file."<<std::endl;
|
||||
std::cout<<">> [rs ] print resource code."<<std::endl;
|
||||
std::cout<<">> [lex ] turn code into tokens."<<std::endl;
|
||||
std::cout<<">> [par ] turn tokens into abstract syntax tree."<<std::endl;
|
||||
std::cout<<">> [ast ] check the abstract syntax tree."<<std::endl;
|
||||
std::cout<<">> [run ] run code."<<std::endl;
|
||||
std::cout<<">> [logo ] print logo of nasal ."<<std::endl;
|
||||
std::cout<<">> [exit ] quit nasal interpreter."<<std::endl;
|
||||
}
|
||||
// clear the window
|
||||
else if(command=="cls")
|
||||
{
|
||||
#ifdef _WIN32
|
||||
system("cls");
|
||||
#endif
|
||||
#ifdef _linux_
|
||||
system("clear");
|
||||
#endif
|
||||
#ifdef TARGET_OS_MAC
|
||||
system("clear");
|
||||
#endif
|
||||
}
|
||||
// del all the source codes and asts
|
||||
else if(command=="del")
|
||||
{
|
||||
resource.delete_all_source();
|
||||
lexer.delete_all_tokens();
|
||||
parser.delete_all_elements();
|
||||
root.set_clear();
|
||||
executable_ast.set_clear();
|
||||
std::cout<<">> [Delete] complete."<<std::endl;
|
||||
}
|
||||
// add lib
|
||||
else if(command=="lib")
|
||||
{
|
||||
libroot.set_clear();
|
||||
resource.load_lib_file();
|
||||
lexer.scanner(resource.get_source());
|
||||
lexer.generate_detail_token();
|
||||
if(!lexer.get_error())
|
||||
{
|
||||
parser.get_token_list(lexer.get_detail_token_list());
|
||||
parser.main_generate();
|
||||
if(!parser.get_error())
|
||||
{
|
||||
libroot=parser.get_root();
|
||||
std::cout<<">> [Lib] loaded."<<std::endl;
|
||||
}
|
||||
else
|
||||
std::cout<<">> [Lib] lib files have parse error(s),stop."<<std::endl;
|
||||
}
|
||||
else
|
||||
std::cout<<">> [Lib] lib files have lexer error(s),stop."<<std::endl;
|
||||
resource.delete_all_source();
|
||||
lexer.delete_all_tokens();
|
||||
parser.delete_all_elements();
|
||||
}
|
||||
// print source codes
|
||||
else if(command=="rs")
|
||||
resource.print_resource();
|
||||
// print detail token after scanning source codes
|
||||
else if(command=="lex")
|
||||
{
|
||||
lexer.scanner(resource.get_source());
|
||||
lexer.generate_detail_token();
|
||||
if(!lexer.get_error())
|
||||
lexer.print_token_list();
|
||||
else
|
||||
std::cout<<">> [Lexer] error occurred,stop."<<std::endl;
|
||||
}
|
||||
// print the parse result of source codes
|
||||
else if(command=="par")
|
||||
{
|
||||
lexer.scanner(resource.get_source());
|
||||
lexer.generate_detail_token();
|
||||
if(!lexer.get_error())
|
||||
{
|
||||
parser.get_token_list(lexer.get_detail_token_list());
|
||||
parser.print_detail_token();
|
||||
parser.main_generate();
|
||||
}
|
||||
else
|
||||
std::cout<<">> [Lexer] error occurred,stop."<<std::endl;
|
||||
}
|
||||
// print the ast of source codes
|
||||
else if(command=="ast")
|
||||
{
|
||||
lexer.scanner(resource.get_source());
|
||||
lexer.generate_detail_token();
|
||||
if(!lexer.get_error())
|
||||
{
|
||||
parser.get_token_list(lexer.get_detail_token_list());
|
||||
parser.main_generate();
|
||||
if(!parser.get_error())
|
||||
parser.get_root().print_tree();
|
||||
else
|
||||
std::cout<<">> [Parse] error occurred,stop."<<std::endl;
|
||||
}
|
||||
else
|
||||
std::cout<<">> [Lexer] error occurred,stop."<<std::endl;
|
||||
}
|
||||
// running process begins here
|
||||
else if(command=="run")
|
||||
{
|
||||
lexer.scanner(resource.get_source());
|
||||
lexer.generate_detail_token();
|
||||
if(!lexer.get_error())
|
||||
{
|
||||
parser.get_token_list(lexer.get_detail_token_list());
|
||||
parser.main_generate();
|
||||
if(!parser.get_error())
|
||||
{
|
||||
executable_ast.set_clear();
|
||||
executable_ast=libroot;
|
||||
executable_ast.merge_children(parser.get_root());
|
||||
runtime.main_proc(executable_ast);
|
||||
//root.print_tree();
|
||||
}
|
||||
else
|
||||
std::cout<<">> [Parse] error occurred,stop."<<std::endl;
|
||||
}
|
||||
else
|
||||
std::cout<<">> [Lexer] error occurred,stop."<<std::endl;
|
||||
}
|
||||
// do you wanna see it again?
|
||||
else if(command=="logo")
|
||||
{
|
||||
std::cout<<" __ _ "<<std::endl;
|
||||
std::cout<<" /\\ \\ \\__ _ ___ __ _| | "<<std::endl;
|
||||
std::cout<<" / \\/ / _` / __|/ _` | | "<<std::endl;
|
||||
std::cout<<" / /\\ / (_| \\__ \\ (_| | | "<<std::endl;
|
||||
std::cout<<" \\_\\ \\/ \\__,_|___/\\__,_|_|"<<std::endl;
|
||||
}
|
||||
// exit interpreter
|
||||
else if(command=="exit")
|
||||
break;
|
||||
else
|
||||
resource.input_file(command);
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
#ifndef __NASAL_H__
|
||||
#define __NASAL_H__
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <cmath>
|
||||
/* if thread is used, don't forget to add -std=c++11 or higher standard before executing */
|
||||
// #include <thread>
|
||||
#include <list>
|
||||
#include <stack>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
/*
|
||||
nasal_misc.h:
|
||||
including some functions that change number to string or change string to number
|
||||
including a function that check if a string is a numerable string
|
||||
including a function that print the hex format number of an integer
|
||||
*/
|
||||
#include "nasal_misc.h"
|
||||
|
||||
/*
|
||||
nasal_enum.h
|
||||
including enums of: lexer token type,parse generated type,scalar type
|
||||
lexer token type is used by nasal_lexer
|
||||
parse generated type is used both by nasal_parse and abstract_syntax_tree
|
||||
parse generated type is also used when lexer is generating detailed tokens which are used in nasal_parse
|
||||
scalar type is used in nasal_runtime and nasal_gc
|
||||
*/
|
||||
#include "nasal_enum.h"
|
||||
|
||||
/*
|
||||
nasal_ast.h
|
||||
including a class named abstract_syntax_tree
|
||||
this class is frequently used in nasal_parse nasal_runtime
|
||||
*/
|
||||
#include "nasal_ast.h"
|
||||
|
||||
/*
|
||||
nasal_lexer.h
|
||||
including a class named resource_file
|
||||
including a class named nasal_lexer
|
||||
including a string[] named lib_filename, by this way resource_file can load lib files
|
||||
including a string[] named reserve_word, it is used in lexer,when generating an identifier,nasal_lexer will check if it is a reserve word
|
||||
including a struct named token, this struct is often used in nasal_lexer and nasal_parse
|
||||
including a function named is_reserve_word, checking if an identifier is a reserve word
|
||||
*/
|
||||
#include "nasal_lexer.h"
|
||||
|
||||
/*
|
||||
nasal_parse.h
|
||||
including a class named nasal_parse
|
||||
nasal_parse uses tokens generated by lexer and generats them into abstract syntax tree
|
||||
this class has a special enum named parse_error_type
|
||||
if parse errors occur,this enum will be into use
|
||||
*/
|
||||
#include "nasal_parse.h"
|
||||
|
||||
/*
|
||||
nasal_gc.h(garbage collector and memory manager of nasal_runtime)
|
||||
including basic classed named: nasal_number, nasal_string, nasal_vector, nasal_hash, nasal_function
|
||||
including important class named gc_manager
|
||||
including struct named gc_unit, it is the smallest memory unit.used in gc_manager
|
||||
nasal_gc is an object of class gc_manager,and nasal_runtime uses this object as it's memory manager
|
||||
*/
|
||||
#include "nasal_gc.h"
|
||||
|
||||
/*
|
||||
nasal_builtinfunc.h
|
||||
including built-in functions of nasal lib
|
||||
all functions in this .cpp will be used in nasal_runtime::builtin_function()
|
||||
*/
|
||||
#include "nasal_builtinfunc.h"
|
||||
|
||||
/*
|
||||
nasal_runtime.h
|
||||
including a class named nasal_runtime
|
||||
including a string[] named inline_func_name
|
||||
function that mentioned in inline_func_name is special functions that were written by cpp,so they can be ca;;ed directly
|
||||
|
||||
if you want to add new built-in functions:
|
||||
add it's name into inline_func_name
|
||||
change the number of nas_lib_func_num
|
||||
write it's function in nasal_runtime::inline_function
|
||||
and don't forget to warp it up with a function that written by nasal
|
||||
|
||||
for example: print(dyn...)
|
||||
var print=func(dyn...)
|
||||
{
|
||||
nasal_call_inline_c_std_puts(dyn);
|
||||
return nil;
|
||||
}
|
||||
*/
|
||||
#include "nasal_runtime.h"
|
||||
|
||||
#endif
|
|
@ -1,786 +0,0 @@
|
|||
#ifndef __NASAL_AST_H__
|
||||
#define __NASAL_AST_H__
|
||||
|
||||
class abstract_syntax_tree
|
||||
{
|
||||
private:
|
||||
/*
|
||||
basic elements of ast node:
|
||||
line: this marks the generated node's line in source code
|
||||
node_type: this marks the node type
|
||||
children: store the children of this node
|
||||
*/
|
||||
int line;
|
||||
int node_type;
|
||||
std::list<abstract_syntax_tree> children;
|
||||
|
||||
/*
|
||||
var_number is used when the node_type is __number
|
||||
var_string is used when the node_type is __string
|
||||
var_name is used when the node_type is __id, __dynamic_id, call_hash
|
||||
*/
|
||||
double var_number;
|
||||
std::string var_string;
|
||||
std::string var_name;
|
||||
public:
|
||||
/* basic */
|
||||
abstract_syntax_tree();
|
||||
abstract_syntax_tree(const abstract_syntax_tree&);
|
||||
~abstract_syntax_tree();
|
||||
abstract_syntax_tree& operator=(const abstract_syntax_tree&);
|
||||
|
||||
/* main functions */
|
||||
/*
|
||||
print_tree is the entrance of print function
|
||||
print_tree will print the root address and call print_tree_block(1)
|
||||
print_tree_block will print the information of each node by using DFS
|
||||
*/
|
||||
void print_tree();
|
||||
void print_tree_block(const int);
|
||||
|
||||
/*
|
||||
set_clear : clear all the elements in ast node
|
||||
set_node_line : set the private:line
|
||||
set_node_type : set the private:node_type
|
||||
set_var_number: set the private:var_number
|
||||
set_var_string: set the private:var_string
|
||||
set_var_name : set the private:var_name
|
||||
*/
|
||||
void set_clear();
|
||||
void set_node_line(const int);
|
||||
void set_node_type(const int);
|
||||
void set_var_number(std::string);
|
||||
void set_var_string(std::string);
|
||||
void set_var_name(std::string);
|
||||
void add_children(abstract_syntax_tree);
|
||||
|
||||
/*
|
||||
get_node_line : get the private:line
|
||||
get_node_type : get the private:node_type
|
||||
get_var_number: get private:var_number
|
||||
get_var_string: get private:var_string
|
||||
get_var_name : get private:var_name
|
||||
*/
|
||||
int get_node_line();
|
||||
int get_node_type();
|
||||
double get_var_number();
|
||||
std::string get_var_string();
|
||||
std::string get_var_name();
|
||||
std::list<abstract_syntax_tree>& get_children();
|
||||
|
||||
/*
|
||||
merge children of another ast into this one
|
||||
used to link lib ast and source codes' ast together
|
||||
*/
|
||||
void merge_children(abstract_syntax_tree&);
|
||||
};
|
||||
|
||||
abstract_syntax_tree::abstract_syntax_tree()
|
||||
{
|
||||
node_type=__null_type;
|
||||
line=0;
|
||||
var_number=0;
|
||||
var_string="";
|
||||
var_name="";
|
||||
children.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
abstract_syntax_tree::abstract_syntax_tree(const abstract_syntax_tree& tmp)
|
||||
{
|
||||
node_type=tmp.node_type;
|
||||
line=tmp.line;
|
||||
var_number=tmp.var_number;
|
||||
var_string=tmp.var_string;
|
||||
var_name=tmp.var_name;
|
||||
children=tmp.children;
|
||||
return;
|
||||
}
|
||||
|
||||
abstract_syntax_tree::~abstract_syntax_tree()
|
||||
{
|
||||
node_type=__null_type;
|
||||
line=0;
|
||||
var_number=0;
|
||||
var_string.clear();
|
||||
var_name.clear();
|
||||
children.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
abstract_syntax_tree& abstract_syntax_tree::operator=(const abstract_syntax_tree& tmp)
|
||||
{
|
||||
node_type=tmp.node_type;
|
||||
line=tmp.line;
|
||||
var_number=tmp.var_number;
|
||||
var_string=tmp.var_string;
|
||||
var_name=tmp.var_name;
|
||||
children.clear();
|
||||
children=tmp.children;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void abstract_syntax_tree::print_tree()
|
||||
{
|
||||
std::cout<<">> [Abstract-syntax-tree] get tree root: "<<(this)<<""<<std::endl;
|
||||
print_tree_block(1);
|
||||
return;
|
||||
}
|
||||
|
||||
void abstract_syntax_tree::print_tree_block(const int n)
|
||||
{
|
||||
std::string __str="";
|
||||
for(int i=0;i<n;++i)
|
||||
__str+="| ";
|
||||
std::cout<<__str;
|
||||
print_ast_type(node_type);
|
||||
switch(node_type)
|
||||
{
|
||||
case __number: std::cout<<": "<<var_number;break;
|
||||
case __string: std::cout<<": "<<var_string;break;
|
||||
case __id:
|
||||
case __dynamic_id:
|
||||
case __call_hash: std::cout<<": "<<var_name;break;
|
||||
case __call_vector:
|
||||
case __call_function: break;
|
||||
default: break;
|
||||
}
|
||||
std::cout<<std::endl;
|
||||
if(!children.empty())
|
||||
{
|
||||
for(std::list<abstract_syntax_tree>::iterator i=children.begin();i!=children.end();++i)
|
||||
i->print_tree_block(n+1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void abstract_syntax_tree::set_clear()
|
||||
{
|
||||
node_type=__null_type;
|
||||
line=0;
|
||||
var_number=0;
|
||||
var_string="";
|
||||
var_name="";
|
||||
children.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
void abstract_syntax_tree::set_node_type(const int __node_type)
|
||||
{
|
||||
node_type=__node_type;
|
||||
return;
|
||||
}
|
||||
|
||||
void abstract_syntax_tree::set_node_line(const int __line)
|
||||
{
|
||||
if(__line>=0)
|
||||
line=__line;
|
||||
else
|
||||
{
|
||||
std::cout<<">> [Abstract-syntax-tree-warning] incorrect line under 0: "<<__line<<"."<<std::endl;
|
||||
line=0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void abstract_syntax_tree::set_var_string(std::string __str)
|
||||
{
|
||||
var_string=__str;
|
||||
return;
|
||||
}
|
||||
|
||||
void abstract_syntax_tree::set_var_number(std::string __str)
|
||||
{
|
||||
var_number=trans_string_to_number(__str);
|
||||
return;
|
||||
}
|
||||
|
||||
void abstract_syntax_tree::set_var_name(std::string __str)
|
||||
{
|
||||
var_name=__str;
|
||||
return;
|
||||
}
|
||||
|
||||
void abstract_syntax_tree::add_children(abstract_syntax_tree p)
|
||||
{
|
||||
// use abstract_syntax_tree instead of abstract_syntax_tree&
|
||||
// because when this function get a 'p' from returned value of
|
||||
// another function,this may result in s SIGSEGV.
|
||||
children.push_back(p);
|
||||
return;
|
||||
}
|
||||
|
||||
int abstract_syntax_tree::get_node_type()
|
||||
{
|
||||
return node_type;
|
||||
}
|
||||
|
||||
int abstract_syntax_tree::get_node_line()
|
||||
{
|
||||
return line;
|
||||
}
|
||||
|
||||
double abstract_syntax_tree::get_var_number()
|
||||
{
|
||||
return var_number;
|
||||
}
|
||||
|
||||
std::string abstract_syntax_tree::get_var_string()
|
||||
{
|
||||
return var_string;
|
||||
}
|
||||
|
||||
std::string abstract_syntax_tree::get_var_name()
|
||||
{
|
||||
return var_name;
|
||||
}
|
||||
|
||||
std::list<abstract_syntax_tree>& abstract_syntax_tree::get_children()
|
||||
{
|
||||
return children;
|
||||
}
|
||||
|
||||
void abstract_syntax_tree::merge_children(abstract_syntax_tree& tmp)
|
||||
{
|
||||
for(std::list<abstract_syntax_tree>::iterator i=tmp.children.begin();i!=tmp.children.end();++i)
|
||||
this->children.push_back(*i);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
examples of each type of sub-tree
|
||||
|
||||
ast begins in root node:
|
||||
root
|
||||
statement_1
|
||||
statement_2
|
||||
...
|
||||
|
||||
note: interpreter in flightgear can recognize 1*(2+(var a=2))
|
||||
but this type of expression is meaningless
|
||||
so this interpreter does not recognize this.
|
||||
|
||||
source code:
|
||||
0xdeadbeef;
|
||||
'str';
|
||||
"str";
|
||||
ast:
|
||||
root
|
||||
num: 3.73593e+009
|
||||
str: str
|
||||
str: str
|
||||
|
||||
source code:
|
||||
[0,1,2,3][0:2];
|
||||
ast:
|
||||
root
|
||||
vector:
|
||||
num: 0
|
||||
num: 1
|
||||
num: 2
|
||||
num: 3
|
||||
call_vector
|
||||
sub_vector
|
||||
num: 0
|
||||
num: 2
|
||||
|
||||
source code:
|
||||
{hello:"world"}.hello;
|
||||
ast:
|
||||
root
|
||||
hash
|
||||
hash_member
|
||||
id: hello
|
||||
str: world
|
||||
call_hash: hello
|
||||
|
||||
source code:
|
||||
1+2*(1-3)/4~'str';
|
||||
ast:
|
||||
root
|
||||
~
|
||||
+
|
||||
num: 1
|
||||
/
|
||||
*
|
||||
num: 2
|
||||
-
|
||||
num: 1
|
||||
num: 3
|
||||
num:4
|
||||
str: str
|
||||
|
||||
source code:
|
||||
var a=cd? 1:0;
|
||||
ast:
|
||||
root
|
||||
definition
|
||||
id: a
|
||||
?
|
||||
id: cd
|
||||
num: 1
|
||||
num: 0
|
||||
|
||||
source code:
|
||||
var h={a:1,b:2,c:'3',};
|
||||
ast:
|
||||
root
|
||||
definition
|
||||
id: h
|
||||
hash
|
||||
hash_member
|
||||
id: a
|
||||
num: 1
|
||||
hash_member
|
||||
id: b
|
||||
num: 2
|
||||
hash_member
|
||||
id: c
|
||||
str: 3
|
||||
|
||||
source code:
|
||||
var id=1;
|
||||
ast:
|
||||
root
|
||||
definition
|
||||
id: id
|
||||
num: 1
|
||||
|
||||
source code:
|
||||
var (id1,id2,id3)=(1,2,3);
|
||||
(var id1,id2,id3)=(1,2,3);
|
||||
ast:
|
||||
root
|
||||
definition
|
||||
identifiers
|
||||
id: id1
|
||||
id: id2
|
||||
id: id3
|
||||
scalars
|
||||
num: 1
|
||||
num: 2
|
||||
num: 3
|
||||
|
||||
source code:
|
||||
var (id1,id2,id3)=[1,2,3];
|
||||
(var id1,id2,id3)=[1,2,3];
|
||||
ast:
|
||||
root
|
||||
definition
|
||||
identifiers
|
||||
id: id1
|
||||
id: id2
|
||||
id: id3
|
||||
vector
|
||||
num: 1
|
||||
num: 2
|
||||
num: 3
|
||||
|
||||
source code:
|
||||
(id1,id2,id3)=(1,2,3);
|
||||
ast:
|
||||
root
|
||||
=
|
||||
scalars
|
||||
id: id1
|
||||
id: id2
|
||||
id: id3
|
||||
scalars
|
||||
num: 1
|
||||
num: 2
|
||||
num: 3
|
||||
|
||||
source code:
|
||||
(id1[0],id2,id3)=[1,2,3];
|
||||
ast:
|
||||
root
|
||||
=
|
||||
scalars
|
||||
id: id1
|
||||
call_vector
|
||||
num: 0
|
||||
id: id2
|
||||
id: id3
|
||||
vector
|
||||
num: 1
|
||||
num: 2
|
||||
num: 3
|
||||
|
||||
source code:
|
||||
id.call_hs(call_f)[call_vec][subvec1:subvec2,subvec3];
|
||||
ast:
|
||||
root
|
||||
id: id
|
||||
call_hash: call_hs
|
||||
call_function
|
||||
id: call_f
|
||||
call_vector
|
||||
id: call_vec
|
||||
call_vector
|
||||
sub_vector
|
||||
id: subvec1
|
||||
id: subvec2
|
||||
id: subvec3
|
||||
|
||||
source code:
|
||||
id.id.id.id.id.id.id.id;
|
||||
ast:
|
||||
root
|
||||
id: id
|
||||
call_hash: id
|
||||
call_hash: id
|
||||
call_hash: id
|
||||
call_hash: id
|
||||
call_hash: id
|
||||
call_hash: id
|
||||
call_hash: id
|
||||
|
||||
source code:
|
||||
function(a,b,c,d,e);
|
||||
function(func a);
|
||||
function(func a());
|
||||
ast:
|
||||
root
|
||||
id: function
|
||||
call_function
|
||||
id: a
|
||||
id: b
|
||||
id: c
|
||||
id: d
|
||||
id: e
|
||||
id: function
|
||||
call_function
|
||||
id: a
|
||||
id: function
|
||||
call_function
|
||||
id: a
|
||||
call_function
|
||||
|
||||
source code:
|
||||
function(
|
||||
a,
|
||||
b,
|
||||
func{print("hello");}
|
||||
);
|
||||
ast:
|
||||
id: function
|
||||
call_function
|
||||
id: a
|
||||
id: b
|
||||
function
|
||||
parameters
|
||||
block
|
||||
id: print
|
||||
call_function
|
||||
str: hello
|
||||
|
||||
source code:
|
||||
function(a:1,b:2,c:3,);
|
||||
ast:
|
||||
root
|
||||
id: function
|
||||
call_function
|
||||
special_parameter
|
||||
id: a
|
||||
num: 1
|
||||
special_parameter
|
||||
id: b
|
||||
num: 2
|
||||
special_parameter
|
||||
id: c
|
||||
num: 3
|
||||
|
||||
source code:
|
||||
(func{print(1);})();
|
||||
ast:
|
||||
root
|
||||
function
|
||||
parameters
|
||||
block
|
||||
id: print
|
||||
call_function
|
||||
num: 1
|
||||
call_function
|
||||
|
||||
source code:
|
||||
while(id)
|
||||
{
|
||||
fun();
|
||||
var a=1;
|
||||
var b=2;
|
||||
}
|
||||
ast:
|
||||
root
|
||||
while
|
||||
id: id
|
||||
block
|
||||
id: func
|
||||
call_function
|
||||
definition
|
||||
id: 1
|
||||
num: 1
|
||||
definition
|
||||
id: b
|
||||
num: 2
|
||||
|
||||
source code:
|
||||
for(;;){}
|
||||
ast:
|
||||
root
|
||||
for
|
||||
null_type
|
||||
null_type
|
||||
null_type
|
||||
block
|
||||
|
||||
source code:
|
||||
for(var i=1;i<100;i+=1){}
|
||||
ast:
|
||||
root
|
||||
for
|
||||
definition
|
||||
id: i
|
||||
num: 1
|
||||
<
|
||||
id: i
|
||||
num: 100
|
||||
+=
|
||||
id: i
|
||||
num: 1
|
||||
block
|
||||
|
||||
source code:
|
||||
foreach(var i;[0,1,2]){}
|
||||
forindex(var i;[0,1,2]){}
|
||||
ast:
|
||||
root
|
||||
foreach
|
||||
id: i
|
||||
vector
|
||||
num: 0
|
||||
num: 1
|
||||
num: 2
|
||||
block
|
||||
forindex
|
||||
id: i
|
||||
vector
|
||||
num: 0
|
||||
num: 1
|
||||
num: 2
|
||||
block
|
||||
|
||||
source code:
|
||||
if(condition_1)
|
||||
{
|
||||
}
|
||||
else if(condition_2)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
ast:
|
||||
root
|
||||
conditional
|
||||
if
|
||||
id: condition_1
|
||||
block
|
||||
else
|
||||
block
|
||||
if
|
||||
id: condition_2
|
||||
block
|
||||
else
|
||||
block
|
||||
|
||||
source code:
|
||||
if(condition_1)
|
||||
{
|
||||
}
|
||||
elsif(condition_2)
|
||||
{
|
||||
}
|
||||
elsif(condition_3)
|
||||
{
|
||||
}
|
||||
ast:
|
||||
root
|
||||
conditional
|
||||
if
|
||||
id: condition_1
|
||||
block
|
||||
elsif
|
||||
id: condition_2
|
||||
block
|
||||
elsif
|
||||
id: condition_3
|
||||
block
|
||||
|
||||
source code:
|
||||
var function=func{};
|
||||
ast:
|
||||
root
|
||||
definition
|
||||
id: function
|
||||
function
|
||||
parameters
|
||||
block
|
||||
|
||||
source code:
|
||||
var function=func(x,y,dyn...){};
|
||||
ast:
|
||||
root
|
||||
definition
|
||||
id: function
|
||||
function
|
||||
parameters
|
||||
id: x
|
||||
id: y
|
||||
id...: dyn
|
||||
block
|
||||
|
||||
source code:
|
||||
var function=func(x=2,y=1){};
|
||||
ast:
|
||||
root
|
||||
definition
|
||||
id: function
|
||||
function
|
||||
parameters
|
||||
default_parameter
|
||||
id: x
|
||||
num: 2
|
||||
default_parameter
|
||||
id: y
|
||||
num: 1
|
||||
block
|
||||
|
||||
source code:
|
||||
var function=func(args...)
|
||||
{
|
||||
if(size(args)<3)
|
||||
{
|
||||
print("error");
|
||||
return 0;
|
||||
}
|
||||
if(args[0]==args[1] or args[1]==args[2])
|
||||
{
|
||||
return args[0]*args[1]*args[2];
|
||||
}
|
||||
elsif(args[2]>args[1])
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
for(var i=0;i<size(args);i+=1)
|
||||
{
|
||||
if(args[i]>100)
|
||||
break;
|
||||
else if(args[i]<0)
|
||||
return args[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
ast:
|
||||
root
|
||||
definition
|
||||
id: function
|
||||
function
|
||||
parameters
|
||||
id...: args
|
||||
block
|
||||
conditional
|
||||
if
|
||||
<
|
||||
id: size
|
||||
call_function
|
||||
id: args
|
||||
num: 3
|
||||
block
|
||||
id: print
|
||||
call_function
|
||||
str: error
|
||||
return
|
||||
num: 0
|
||||
conditional
|
||||
if
|
||||
or
|
||||
==
|
||||
id: args
|
||||
call_vector
|
||||
num: 0
|
||||
id: args
|
||||
call_vector
|
||||
num: 1
|
||||
==
|
||||
id: args
|
||||
call_vector
|
||||
num: 1
|
||||
id: args
|
||||
call_vector
|
||||
num: 2
|
||||
block
|
||||
return
|
||||
*
|
||||
*
|
||||
id: args
|
||||
call_vector
|
||||
num: 0
|
||||
id: args
|
||||
call_vector
|
||||
num: 1
|
||||
id: args
|
||||
call_vector
|
||||
num: 2
|
||||
elsif
|
||||
>
|
||||
id: args
|
||||
call_vector
|
||||
num: 2
|
||||
id: args
|
||||
call_vector
|
||||
num: 1
|
||||
block
|
||||
return
|
||||
-
|
||||
num: 0
|
||||
num: 1
|
||||
for
|
||||
definition
|
||||
id: i
|
||||
num: 0
|
||||
<
|
||||
id: i
|
||||
id: size
|
||||
call_function
|
||||
id: args
|
||||
+=
|
||||
id: i
|
||||
num: 1
|
||||
block
|
||||
conditional
|
||||
if
|
||||
>
|
||||
id: args
|
||||
call_vector
|
||||
id: i
|
||||
num: 100
|
||||
block
|
||||
break
|
||||
else
|
||||
block
|
||||
conditional
|
||||
if
|
||||
<
|
||||
id: args
|
||||
call_vector
|
||||
id: i
|
||||
num: 0
|
||||
block
|
||||
return
|
||||
id: args
|
||||
call_vector
|
||||
id: i
|
||||
return
|
||||
num: 0
|
||||
*/
|
|
@ -1,362 +0,0 @@
|
|||
#ifndef __NASAL_BUILTINFUNC_H__
|
||||
#define __NASAL_BUILTINFUNC_H__
|
||||
|
||||
int append(std::list<std::map<std::string,int> >& local_scope)
|
||||
{
|
||||
int vector_addr=-1,elements_addr=-1;
|
||||
for(std::list<std::map<std::string,int> >::iterator i=local_scope.begin();i!=local_scope.end();++i)
|
||||
{
|
||||
if(i->find("vector")!=i->end())
|
||||
vector_addr=(*i)["vector"];
|
||||
if(i->find("elements")!=i->end())
|
||||
elements_addr=(*i)["elements"];
|
||||
}
|
||||
if(vector_addr<0 || elements_addr<0)
|
||||
return -1;
|
||||
if(nasal_gc.get_scalar(vector_addr).get_type()!=scalar_vector)
|
||||
{
|
||||
std::cout<<">> [Runtime] append gets a value that is not a vector."<<std::endl;
|
||||
return -1;
|
||||
}
|
||||
for(int i=0;i<nasal_gc.get_scalar(elements_addr).get_vector().get_size();++i)
|
||||
{
|
||||
int data_addr=nasal_gc.get_scalar(elements_addr).get_vector().get_elem(i);
|
||||
if(data_addr<0)
|
||||
return -1;
|
||||
int new_addr=-1;
|
||||
switch(nasal_gc.get_scalar(data_addr).get_type())
|
||||
{
|
||||
case scalar_nil:
|
||||
new_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(new_addr).set_type(scalar_nil);
|
||||
break;
|
||||
case scalar_number:
|
||||
new_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(new_addr).set_type(scalar_number);
|
||||
nasal_gc.get_scalar(new_addr).get_number().deep_copy(nasal_gc.get_scalar(data_addr).get_number());
|
||||
break;
|
||||
case scalar_string:
|
||||
new_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(new_addr).set_type(scalar_string);
|
||||
nasal_gc.get_scalar(new_addr).get_string().deep_copy(nasal_gc.get_scalar(data_addr).get_string());
|
||||
break;
|
||||
case scalar_function:
|
||||
new_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(new_addr).set_type(scalar_function);
|
||||
nasal_gc.get_scalar(new_addr).get_function().deep_copy(nasal_gc.get_scalar(data_addr).get_function());
|
||||
break;
|
||||
case scalar_vector:
|
||||
case scalar_hash:
|
||||
new_addr=data_addr;
|
||||
nasal_gc.reference_add(new_addr);
|
||||
break;
|
||||
}
|
||||
nasal_gc.get_scalar(vector_addr).get_vector().vec_push(new_addr);
|
||||
}
|
||||
int ret_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(ret_addr).set_type(scalar_nil);
|
||||
return ret_addr;
|
||||
}
|
||||
|
||||
int setsize(std::list<std::map<std::string,int> >& local_scope)
|
||||
{
|
||||
int vector_addr=-1,size_addr=-1;
|
||||
for(std::list<std::map<std::string,int> >::iterator i=local_scope.begin();i!=local_scope.end();++i)
|
||||
{
|
||||
if(i->find("vector")!=i->end())
|
||||
vector_addr=(*i)["vector"];
|
||||
if(i->find("__size")!=i->end())
|
||||
size_addr=(*i)["__size"];
|
||||
}
|
||||
if(vector_addr<0 || size_addr<0)
|
||||
return -1;
|
||||
int vector_size=-1;
|
||||
int aim_size=-1;
|
||||
if(nasal_gc.get_scalar(vector_addr).get_type()!=scalar_vector)
|
||||
{
|
||||
std::cout<<">> [Runtime] setsize gets a variable that is not a vector."<<std::endl;
|
||||
return -1;
|
||||
}
|
||||
vector_size=nasal_gc.get_scalar(vector_addr).get_vector().get_size();
|
||||
if(nasal_gc.get_scalar(size_addr).get_type()==scalar_string &&
|
||||
!check_numerable_string(nasal_gc.get_scalar(size_addr).get_string().get_string()))
|
||||
{
|
||||
std::cout<<">> [Runtime] __size is not a numerable string."<<std::endl;
|
||||
return -1;
|
||||
}
|
||||
if(nasal_gc.get_scalar(size_addr).get_type()!=scalar_string &&
|
||||
nasal_gc.get_scalar(size_addr).get_type()!=scalar_number)
|
||||
{
|
||||
std::cout<<">> [Runtime] __size must be a number or numerable string."<<std::endl;
|
||||
return -1;
|
||||
}
|
||||
if(nasal_gc.get_scalar(size_addr).get_type()==scalar_string &&
|
||||
check_numerable_string(nasal_gc.get_scalar(size_addr).get_string().get_string()))
|
||||
aim_size=(int)trans_string_to_number(nasal_gc.get_scalar(size_addr).get_string().get_string());
|
||||
else if(nasal_gc.get_scalar(size_addr).get_type()==scalar_number)
|
||||
aim_size=(int)nasal_gc.get_scalar(size_addr).get_number().get_number();
|
||||
if(aim_size<0)
|
||||
{
|
||||
std::cout<<">> [Runtime] __size must be greater than 0."<<std::endl;
|
||||
return -1;
|
||||
}
|
||||
if(vector_size<aim_size)
|
||||
{
|
||||
for(int i=vector_size;i<aim_size;++i)
|
||||
{
|
||||
int new_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(new_addr).set_type(scalar_nil);
|
||||
nasal_gc.get_scalar(vector_addr).get_vector().vec_push(new_addr);
|
||||
}
|
||||
}
|
||||
else if(vector_size>aim_size)
|
||||
for(int i=aim_size;i<vector_size;++i)
|
||||
{
|
||||
int pop_addr=nasal_gc.get_scalar(vector_addr).get_vector().vec_pop();
|
||||
nasal_gc.reference_delete(pop_addr);
|
||||
}
|
||||
int ret_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(ret_addr).set_type(scalar_nil);
|
||||
return ret_addr;
|
||||
}
|
||||
|
||||
int subvec(std::list<std::map<std::string,int> >& local_scope)
|
||||
{
|
||||
int vector_addr=-1,start=-1,length=-1,type=-1;
|
||||
int begin_iter=0,len_iter=0;
|
||||
for(std::list<std::map<std::string,int> >::iterator i=local_scope.begin();i!=local_scope.end();++i)
|
||||
{
|
||||
if(i->find("vector")!=i->end())
|
||||
vector_addr=(*i)["vector"];
|
||||
if(i->find("start")!=i->end())
|
||||
start=(*i)["start"];
|
||||
if(i->find("length")!=i->end())
|
||||
length=(*i)["length"];
|
||||
}
|
||||
if(vector_addr<0 || start<0 || length<0)
|
||||
return -1;
|
||||
if(nasal_gc.get_scalar(vector_addr).get_type()!=scalar_vector)
|
||||
{
|
||||
std::cout<<">> subvec gets a value that is not a vector."<<std::endl;
|
||||
return -1;
|
||||
}
|
||||
type=nasal_gc.get_scalar(start).get_type();
|
||||
if(type!=scalar_number && type!=scalar_string)
|
||||
{
|
||||
std::cout<<">> [Runtime] \'start\' is not a number or numerable string."<<std::endl;
|
||||
return -1;
|
||||
}
|
||||
if(type==scalar_string && !check_numerable_string(nasal_gc.get_scalar(start).get_string().get_string()))
|
||||
{
|
||||
std::cout<<">> [Runtime] \'start\' is not a numerable string."<<std::endl;
|
||||
return -1;
|
||||
}
|
||||
if(type==scalar_number)
|
||||
begin_iter=(int)nasal_gc.get_scalar(start).get_number().get_number();
|
||||
else if(type==scalar_string)
|
||||
begin_iter=(int)trans_string_to_number(nasal_gc.get_scalar(start).get_string().get_string());
|
||||
type=nasal_gc.get_scalar(length).get_type();
|
||||
if(type!=scalar_nil && type!=scalar_number && type!=scalar_string)
|
||||
{
|
||||
std::cout<<">> [Runtime] \'length\' is not a nil type,number or numerable string."<<std::endl;
|
||||
return -1;
|
||||
}
|
||||
if(type==scalar_string && !check_numerable_string(nasal_gc.get_scalar(length).get_string().get_string()))
|
||||
{
|
||||
std::cout<<">> [Runtime] \'length\' is not a numerable string."<<std::endl;
|
||||
return -1;
|
||||
}
|
||||
if(type==scalar_nil)
|
||||
len_iter=nasal_gc.get_scalar(vector_addr).get_vector().get_size()-begin_iter;
|
||||
else if(type==scalar_number)
|
||||
len_iter=(int)nasal_gc.get_scalar(length).get_number().get_number();
|
||||
else if(type==scalar_string)
|
||||
len_iter=(int)trans_string_to_number(nasal_gc.get_scalar(length).get_string().get_string());
|
||||
int ret_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(ret_addr).set_type(scalar_vector);
|
||||
if(type==scalar_nil)
|
||||
for(int i=begin_iter;i<nasal_gc.get_scalar(vector_addr).get_vector().get_size();++i)
|
||||
{
|
||||
int tmp=nasal_gc.get_scalar(vector_addr).get_vector().get_elem(i);
|
||||
if(tmp<0)
|
||||
{
|
||||
std::cout<<">> [Runtime] subvec out of memory boundary."<<std::endl;
|
||||
return -1;
|
||||
}
|
||||
int new_addr=-1;
|
||||
switch(nasal_gc.get_scalar(tmp).get_type())
|
||||
{
|
||||
case scalar_nil:
|
||||
new_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(new_addr).set_type(scalar_nil);
|
||||
break;
|
||||
case scalar_number:
|
||||
new_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(new_addr).set_type(scalar_number);
|
||||
nasal_gc.get_scalar(new_addr).get_number().deep_copy(nasal_gc.get_scalar(tmp).get_number());
|
||||
break;
|
||||
case scalar_string:
|
||||
new_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(new_addr).set_type(scalar_string);
|
||||
nasal_gc.get_scalar(new_addr).get_string().deep_copy(nasal_gc.get_scalar(tmp).get_string());
|
||||
break;
|
||||
case scalar_function:
|
||||
new_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(new_addr).set_type(scalar_function);
|
||||
nasal_gc.get_scalar(new_addr).get_function().deep_copy(nasal_gc.get_scalar(tmp).get_function());
|
||||
break;
|
||||
case scalar_vector:
|
||||
case scalar_hash:
|
||||
new_addr=tmp;
|
||||
nasal_gc.reference_add(new_addr);
|
||||
break;
|
||||
}
|
||||
nasal_gc.get_scalar(ret_addr).get_vector().vec_push(new_addr);
|
||||
}
|
||||
else
|
||||
for(int i=0;i<len_iter;++i)
|
||||
{
|
||||
int tmp=nasal_gc.get_scalar(vector_addr).get_vector().get_elem(begin_iter+i);
|
||||
if(tmp<0)
|
||||
{
|
||||
std::cout<<">> [Runtime] subvec out of memory boundary."<<std::endl;
|
||||
return -1;
|
||||
}
|
||||
int new_addr=-1;
|
||||
switch(nasal_gc.get_scalar(tmp).get_type())
|
||||
{
|
||||
case scalar_nil:
|
||||
new_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(new_addr).set_type(scalar_nil);
|
||||
break;
|
||||
case scalar_number:
|
||||
new_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(new_addr).set_type(scalar_number);
|
||||
nasal_gc.get_scalar(new_addr).get_number().deep_copy(nasal_gc.get_scalar(tmp).get_number());
|
||||
break;
|
||||
case scalar_string:
|
||||
new_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(new_addr).set_type(scalar_string);
|
||||
nasal_gc.get_scalar(new_addr).get_string().deep_copy(nasal_gc.get_scalar(tmp).get_string());
|
||||
break;
|
||||
case scalar_function:
|
||||
new_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(new_addr).set_type(scalar_function);
|
||||
nasal_gc.get_scalar(new_addr).get_function().deep_copy(nasal_gc.get_scalar(tmp).get_function());
|
||||
break;
|
||||
case scalar_vector:
|
||||
case scalar_hash:
|
||||
new_addr=tmp;
|
||||
nasal_gc.reference_add(new_addr);
|
||||
break;
|
||||
}
|
||||
nasal_gc.get_scalar(ret_addr).get_vector().vec_push(new_addr);
|
||||
}
|
||||
return ret_addr;
|
||||
}
|
||||
|
||||
int print(std::list<std::map<std::string,int> >& local_scope)
|
||||
{
|
||||
int vector_addr=-1;
|
||||
for(std::list<std::map<std::string,int> >::iterator i=local_scope.begin();i!=local_scope.end();++i)
|
||||
if(i->find("dyn")!=i->end())
|
||||
vector_addr=(*i)["dyn"];
|
||||
if(vector_addr<0) return -1;
|
||||
for(int i=0;i<nasal_gc.get_scalar(vector_addr).get_vector().get_size();++i)
|
||||
{
|
||||
int data_addr=nasal_gc.get_scalar(vector_addr).get_vector().get_elem(i);
|
||||
if(data_addr<0) return -1;
|
||||
switch(nasal_gc.get_scalar(data_addr).get_type())
|
||||
{
|
||||
case scalar_nil:break;
|
||||
case scalar_number:std::cout<<nasal_gc.get_scalar(data_addr).get_number().get_number();break;
|
||||
case scalar_string:std::cout<<nasal_gc.get_scalar(data_addr).get_string().get_string();break;
|
||||
case scalar_vector:std::cout<<"[...]";break;
|
||||
case scalar_hash: std::cout<<"{...}";break;
|
||||
case scalar_function:std::cout<<"func(...){...}";break;
|
||||
}
|
||||
}
|
||||
int ret_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(ret_addr).set_type(scalar_nil);
|
||||
return ret_addr;
|
||||
}
|
||||
|
||||
int system_type(std::list<std::map<std::string,int> >& local_scope)
|
||||
{
|
||||
int data=-1;
|
||||
for(std::list<std::map<std::string,int> >::iterator i=local_scope.begin();i!=local_scope.end();++i)
|
||||
if(i->find("thing")!=i->end())
|
||||
data=(*i)["thing"];
|
||||
if(data<0) return -1;
|
||||
print_scalar_type(nasal_gc.get_scalar(data).get_type());
|
||||
std::cout<<std::endl;
|
||||
int ret_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(ret_addr).set_type(scalar_nil);
|
||||
return ret_addr;
|
||||
}
|
||||
|
||||
int nas_trigfunc(std::list<std::map<std::string,int> >& local_scope,int func_type)
|
||||
{
|
||||
int data=-1;
|
||||
double num=0;
|
||||
int type=-1;
|
||||
for(std::list<std::map<std::string,int> >::iterator i=local_scope.begin();i!=local_scope.end();++i)
|
||||
if(i->find("x")!=i->end())
|
||||
data=(*i)["x"];
|
||||
if(data<0) return -1;
|
||||
type=nasal_gc.get_scalar(data).get_type();
|
||||
if(type!=scalar_number && type!=scalar_string)
|
||||
{
|
||||
std::cout<<">> [Runtime] x must be a number or numerable string."<<std::endl;
|
||||
return -1;
|
||||
}
|
||||
if(type==scalar_string && !check_numerable_string(nasal_gc.get_scalar(data).get_string().get_string()))
|
||||
{
|
||||
std::cout<<">> [Runtime] x is not a numerable string."<<std::endl;
|
||||
return -1;
|
||||
}
|
||||
if(type==scalar_number)
|
||||
num=nasal_gc.get_scalar(data).get_number().get_number();
|
||||
else if(type==scalar_string)
|
||||
num=trans_string_to_number(nasal_gc.get_scalar(data).get_string().get_string());
|
||||
int ret_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(ret_addr).set_type(scalar_number);
|
||||
switch(func_type)
|
||||
{
|
||||
case 0:nasal_gc.get_scalar(ret_addr).get_number().set_number(std::sin(num));break;
|
||||
case 1:nasal_gc.get_scalar(ret_addr).get_number().set_number(std::cos(num));break;
|
||||
case 2:nasal_gc.get_scalar(ret_addr).get_number().set_number(std::tan(num));break;
|
||||
}
|
||||
return ret_addr;
|
||||
}
|
||||
|
||||
int nas_exp(std::list<std::map<std::string,int> >& local_scope)
|
||||
{
|
||||
int data=-1,type=-1;
|
||||
double num=0;
|
||||
for(std::list<std::map<std::string,int> >::iterator i=local_scope.begin();i!=local_scope.end();++i)
|
||||
if(i->find("x")!=i->end())
|
||||
data=(*i)["x"];
|
||||
if(data<0)
|
||||
return -1;
|
||||
type=nasal_gc.get_scalar(data).get_type();
|
||||
if(type!=scalar_number && type!=scalar_string)
|
||||
{
|
||||
std::cout<<">> [Runtime] x must be a number or numerable string."<<std::endl;
|
||||
return -1;
|
||||
}
|
||||
if(type==scalar_string && !check_numerable_string(nasal_gc.get_scalar(data).get_string().get_string()))
|
||||
{
|
||||
std::cout<<">> [Runtime] x is not a numerable string."<<std::endl;
|
||||
return -1;
|
||||
}
|
||||
if(type==scalar_number)
|
||||
num=nasal_gc.get_scalar(data).get_number().get_number();
|
||||
else if(type==scalar_string)
|
||||
num=trans_string_to_number(nasal_gc.get_scalar(data).get_string().get_string());
|
||||
int ret_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(ret_addr).set_type(scalar_number);
|
||||
nasal_gc.get_scalar(ret_addr).get_number().set_number(std::exp(num));
|
||||
return ret_addr;
|
||||
}
|
||||
#endif
|
|
@ -1,282 +0,0 @@
|
|||
#ifndef __NASAL_ENUM_H__
|
||||
#define __NASAL_ENUM_H__
|
||||
|
||||
// lexer token type is only used in nasal_lexer
|
||||
/*
|
||||
__token_reserve_word:
|
||||
for,foreach,forindex,while : loop head
|
||||
var,func : definition
|
||||
break,continue : in loop
|
||||
return : in function
|
||||
if,else,elsif : conditional expr
|
||||
and,or : calculation
|
||||
nil : special type
|
||||
__token_identifier:
|
||||
must begin with '_' or 'a'~'z' or 'A'~'Z'
|
||||
can include '_' or 'a'~'z' or 'A'~'Z' or '0'~'9'
|
||||
__token_string:
|
||||
example:
|
||||
"string"
|
||||
'string'
|
||||
if a string does not end with " or ' then lexer will throw an error
|
||||
__token_number:
|
||||
example:
|
||||
2147483647 (integer)
|
||||
2.71828 (float)
|
||||
0xdeadbeef (hex) or 0xDEADBEEF (hex)
|
||||
0o170001 (oct)
|
||||
1e-1234 (dec) or 10E2 (dec)
|
||||
__token_operator:
|
||||
! + - * / ~
|
||||
= += -= *= /= ~=
|
||||
== != > >= < <=
|
||||
('and' 'or' are operators too but they are recognized as operator in generate_detail_token())
|
||||
() [] {} ; , . : ?
|
||||
others: __unknown_operator
|
||||
*/
|
||||
enum lexer_token_type
|
||||
{
|
||||
__token_reserve_word=1,
|
||||
__token_identifier,
|
||||
__token_number,
|
||||
__token_string,
|
||||
__token_operator,
|
||||
};
|
||||
void print_lexer_token(int type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case __token_reserve_word:std::cout<<"reserve word";break;
|
||||
case __token_identifier: std::cout<<"identifier ";break;
|
||||
case __token_number: std::cout<<"number ";break;
|
||||
case __token_string: std::cout<<"string ";break;
|
||||
case __token_operator: std::cout<<"operator ";break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// parse_gen_type include enums for parser and ast
|
||||
enum parse_gen_type
|
||||
{
|
||||
/*
|
||||
stack end is an important flag for parse token stack to
|
||||
check if it's stack is at end/empty
|
||||
if stack is empty,the parser will get a wrong memory space and cause SIGSEGV
|
||||
*/
|
||||
__stack_end=1,
|
||||
|
||||
__cmp_equal,
|
||||
__cmp_not_equal,
|
||||
__cmp_less,__cmp_less_or_equal,
|
||||
__cmp_more,__cmp_more_or_equal, // operators == != < <= > >=
|
||||
|
||||
__and_operator, __or_operator,__nor_operator,
|
||||
__add_operator,__sub_operator,
|
||||
__mul_operator,__div_operator,__link_operator, // operators and or ! + - * / ~
|
||||
|
||||
__equal,
|
||||
__add_equal,__sub_equal,
|
||||
__mul_equal,__div_equal,__link_equal, // operators = += -= *= /= ~=
|
||||
|
||||
__left_brace,__right_brace, // {}
|
||||
__left_bracket,__right_bracket, // []
|
||||
__left_curve,__right_curve, // ()
|
||||
__semi,__comma,__colon,__dot,__ques_mark, // ; , : . ?
|
||||
__unknown_operator,
|
||||
|
||||
__var,
|
||||
__func,__return,__nil,
|
||||
__if,__elsif,__else,
|
||||
__continue,__break,
|
||||
__for,__forindex,__foreach,__while, // reserve words
|
||||
|
||||
__number,__string, // basic scalar type: number string
|
||||
|
||||
__id,__dynamic_id, // basic identifier type: identifier dynamic_identifier
|
||||
|
||||
// abstract_syntax_tree type below
|
||||
// abstract_syntax_tree also uses the types above, such as operators
|
||||
__root,
|
||||
__null_type,
|
||||
__multi_id,__multi_scalar,
|
||||
__parameters,__special_parameter,__default_parameter,
|
||||
__vector,__sub_vector,__call_vector,
|
||||
__hash,__hash_member,__call_hash,
|
||||
__function,__call_function,
|
||||
__normal_statement_block,
|
||||
__definition,
|
||||
__conditional
|
||||
};
|
||||
// print tokens that used in nasal_parse
|
||||
void print_parse_token(int type)
|
||||
{
|
||||
std::string context="";
|
||||
switch(type)
|
||||
{
|
||||
case __stack_end: context=" # "; break;
|
||||
case __cmp_equal: context=" == "; break;
|
||||
case __cmp_not_equal: context=" != "; break;
|
||||
case __cmp_less: context=" < "; break;
|
||||
case __cmp_less_or_equal: context=" <= "; break;
|
||||
case __cmp_more: context=" > "; break;
|
||||
case __cmp_more_or_equal: context=" >= "; break;
|
||||
|
||||
case __and_operator: context=" and ";break;
|
||||
case __or_operator: context=" or "; break;
|
||||
case __nor_operator: context=" ! "; break;
|
||||
case __add_operator: context=" + "; break;
|
||||
case __sub_operator: context=" - "; break;
|
||||
case __mul_operator: context=" * "; break;
|
||||
case __div_operator: context=" / "; break;
|
||||
case __link_operator: context=" ~ "; break;
|
||||
|
||||
case __equal: context=" = "; break;
|
||||
case __add_equal: context=" += "; break;
|
||||
case __sub_equal: context=" -= "; break;
|
||||
case __mul_equal: context=" *= "; break;
|
||||
case __div_equal: context=" /= "; break;
|
||||
case __link_equal: context=" ~= "; break;
|
||||
|
||||
case __left_brace: context="{"; break;
|
||||
case __right_brace: context="}"; break;
|
||||
case __left_bracket: context="["; break;
|
||||
case __right_bracket: context="]"; break;
|
||||
case __left_curve: context="("; break;
|
||||
case __right_curve: context=")"; break;
|
||||
|
||||
case __semi: context=";"; break;
|
||||
case __comma: context=","; break;
|
||||
case __colon: context=":"; break;
|
||||
case __dot: context="."; break;
|
||||
case __ques_mark: context="?"; break;
|
||||
|
||||
case __unknown_operator: context="unknown_operator";break;
|
||||
|
||||
case __var: context="var "; break;
|
||||
case __func: context="func "; break;
|
||||
case __continue: context="continue"; break;
|
||||
case __break: context="break"; break;
|
||||
case __for: context="for"; break;
|
||||
case __forindex: context="forindex"; break;
|
||||
case __foreach: context="foreach "; break;
|
||||
case __while: context="while"; break;
|
||||
case __if: context="if "; break;
|
||||
case __elsif: context="elsif "; break;
|
||||
case __else: context="else "; break;
|
||||
case __return: context="return "; break;
|
||||
case __nil: context="nil"; break;
|
||||
|
||||
case __id: context="id"; break;
|
||||
case __dynamic_id: context="id..."; break;
|
||||
case __number: context="num"; break;
|
||||
case __string: context="str"; break;
|
||||
|
||||
default: context="undefined"; break;
|
||||
}
|
||||
std::cout<<context;
|
||||
return;
|
||||
}
|
||||
// print node types that used in abstract_syntax_tree
|
||||
void print_ast_type(int type)
|
||||
{
|
||||
std::string context="";
|
||||
switch(type)
|
||||
{
|
||||
case __cmp_equal: context=" == "; break;
|
||||
case __cmp_not_equal: context=" != "; break;
|
||||
case __cmp_less: context=" < "; break;
|
||||
case __cmp_less_or_equal: context=" <= "; break;
|
||||
case __cmp_more: context=" > "; break;
|
||||
case __cmp_more_or_equal: context=" >= "; break;
|
||||
|
||||
case __and_operator: context=" and ";break;
|
||||
case __or_operator: context=" or "; break;
|
||||
case __nor_operator: context=" ! "; break;
|
||||
case __add_operator: context=" + "; break;
|
||||
case __sub_operator: context=" - "; break;
|
||||
case __mul_operator: context=" * "; break;
|
||||
case __div_operator: context=" / "; break;
|
||||
case __link_operator: context=" ~ "; break;
|
||||
|
||||
case __equal: context=" = "; break;
|
||||
case __add_equal: context=" += "; break;
|
||||
case __sub_equal: context=" -= "; break;
|
||||
case __mul_equal: context=" *= "; break;
|
||||
case __div_equal: context=" /= "; break;
|
||||
case __link_equal: context=" ~= "; break;
|
||||
|
||||
case __ques_mark: context="?"; break;
|
||||
|
||||
case __var: context="var "; break;
|
||||
case __func: context="func "; break;
|
||||
case __continue: context="continue"; break;
|
||||
case __break: context="break"; break;
|
||||
case __for: context="for"; break;
|
||||
case __forindex: context="forindex"; break;
|
||||
case __foreach: context="foreach "; break;
|
||||
case __while: context="while"; break;
|
||||
case __if: context="if "; break;
|
||||
case __elsif: context="elsif "; break;
|
||||
case __else: context="else "; break;
|
||||
case __return: context="return "; break;
|
||||
case __nil: context="nil"; break;
|
||||
|
||||
case __id: context="id"; break;
|
||||
case __dynamic_id: context="id..."; break;
|
||||
case __number: context="num"; break;
|
||||
case __string: context="str"; break;
|
||||
|
||||
case __root: context="root"; break; // root of the ast that parser generates
|
||||
case __null_type: context="null_type"; break; // type of the node of the tree is unknown
|
||||
case __multi_id: context="identifiers"; break; // id,id,id,id |often used in multi-definition or multi-assignment
|
||||
case __multi_scalar: context="scalars"; break; // scalar,scalar,scalar,scalar|often used in multi-definition or multi-assignment
|
||||
case __parameters: context="parameters"; break; // parameter list
|
||||
case __special_parameter: context="special_parameter"; break; // identifier:scalar |special way of calling a function
|
||||
case __default_parameter: context="default_parameter"; break; // identifier=scalar |default parameter when generating a new function
|
||||
case __vector: context="vector"; break; // vector
|
||||
case __sub_vector: context="sub_vector"; break; // the same as subvec() but more flexible to use
|
||||
case __call_vector: context="call_vector"; break; // call vector member
|
||||
case __hash: context="hash"; break; // hash
|
||||
case __hash_member: context="hash_member"; break; // hash member
|
||||
case __call_hash: context="call_hash"; break; // call hash member
|
||||
case __function: context="function"; break; // function
|
||||
case __call_function: context="call_function"; break; // call function
|
||||
case __normal_statement_block:context="block"; break; // block
|
||||
case __definition: context="definition"; break; // definition
|
||||
case __conditional: context="conditional"; break; // if-else
|
||||
|
||||
default: context="undefined"; break;
|
||||
}
|
||||
std::cout<<context;
|
||||
return;
|
||||
}
|
||||
|
||||
// basic scalar type used in nasal_runtime and nasal_gc
|
||||
enum scalar_type
|
||||
{
|
||||
scalar_nil=0,
|
||||
scalar_number,
|
||||
scalar_string,
|
||||
scalar_vector,
|
||||
scalar_hash,
|
||||
scalar_function,
|
||||
scalar_closure
|
||||
};
|
||||
// print types that used in nasal_runtime and nasal_gc
|
||||
void print_scalar_type(const int type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case scalar_nil: std::cout<<"nil";break;
|
||||
case scalar_number:
|
||||
case scalar_string: std::cout<<"scalar";break;
|
||||
case scalar_vector: std::cout<<"vector";break;
|
||||
case scalar_hash: std::cout<<"hash";break;
|
||||
case scalar_function: std::cout<<"function";break;
|
||||
case scalar_closure: std::cout<<"closure";break;
|
||||
default: std::cout<<"nil";break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,729 +0,0 @@
|
|||
#ifndef __NASAL_GC_H__
|
||||
#define __NASAL_GC_H__
|
||||
|
||||
// all identifiers in nasal points to a memory space in nasal_gc.
|
||||
// memory space uses std::vector<gc_unit>.
|
||||
// gc_unit is a struct which has nasal_scalar and refcnt in it.(more details please see the definition of gc_unit bellow)
|
||||
// when an identifier needs to be assigned,but the type of value is not the same as the identifier's value
|
||||
// the identifier will get a new memory space in nasal_gc and do deep_copy()
|
||||
// and the memory space that is not used ,its ref_cnt-=1.
|
||||
|
||||
class nasal_closure
|
||||
{
|
||||
private:
|
||||
std::list<std::map<std::string,int> > closure;
|
||||
public:
|
||||
void set_clear();
|
||||
void set_local_scope(std::list<std::map<std::string,int> >&);
|
||||
std::list<std::map<std::string,int> >& get_local_scope();
|
||||
void print_closure_ids();
|
||||
};
|
||||
|
||||
class nasal_function
|
||||
{
|
||||
private:
|
||||
// closure_updated flag is used to mark if this function's closure is updated.
|
||||
// to avoid some unexpected errors,closure of each function must be updated before blocks popping back the last scope
|
||||
bool closure_updated;
|
||||
int closure_addr;
|
||||
abstract_syntax_tree parameter_list;
|
||||
abstract_syntax_tree function_root;
|
||||
public:
|
||||
nasal_function();
|
||||
void set_clear();
|
||||
void set_local_scope(int);
|
||||
bool get_closure_update_state();
|
||||
void set_closure_update_state(bool);
|
||||
void set_paramemter_list(abstract_syntax_tree&);
|
||||
void set_statement_block(abstract_syntax_tree&);
|
||||
int get_local_scope();
|
||||
abstract_syntax_tree& get_parameter_list();
|
||||
abstract_syntax_tree& get_statement_block();
|
||||
void deep_copy(nasal_function&);
|
||||
};
|
||||
|
||||
class nasal_number
|
||||
{
|
||||
private:
|
||||
double nas_number;
|
||||
public:
|
||||
void set_clear();
|
||||
void set_number(double);
|
||||
double get_number();
|
||||
void deep_copy(nasal_number&);
|
||||
};
|
||||
|
||||
class nasal_string
|
||||
{
|
||||
private:
|
||||
std::string nas_string;
|
||||
public:
|
||||
void set_clear();
|
||||
void set_string(std::string);
|
||||
std::string get_string();
|
||||
void deep_copy(nasal_string&);
|
||||
};
|
||||
|
||||
class nasal_vector
|
||||
{
|
||||
private:
|
||||
std::vector<int> nas_array;
|
||||
public:
|
||||
void set_clear();
|
||||
void vec_push(int);
|
||||
int* get_elem_addr(int);
|
||||
int get_elem(int);
|
||||
int vec_pop();
|
||||
int get_size();
|
||||
int* get_parent_hash_member_addr(std::string);
|
||||
int get_parent_hash_member(std::string);
|
||||
void generate_new_hash();
|
||||
void deep_copy(nasal_vector&);
|
||||
};
|
||||
|
||||
class nasal_hash
|
||||
{
|
||||
private:
|
||||
std::map<std::string,int> nas_hash;
|
||||
public:
|
||||
void set_clear();
|
||||
int* get_hash_member_addr(std::string);
|
||||
int get_hash_member(std::string);
|
||||
std::vector<int> get_elem();
|
||||
void hash_push(std::string,int);
|
||||
void hash_pop(std::string);
|
||||
void deep_copy(nasal_hash&);
|
||||
};
|
||||
|
||||
class nasal_scalar
|
||||
{
|
||||
private:
|
||||
int type;
|
||||
nasal_string var_string;
|
||||
nasal_number var_number;
|
||||
nasal_vector var_vector;
|
||||
nasal_hash var_hash;
|
||||
nasal_function var_func;
|
||||
nasal_closure var_cls;
|
||||
public:
|
||||
nasal_scalar();
|
||||
void set_type(int);
|
||||
int get_type();
|
||||
nasal_number& get_number();
|
||||
nasal_string& get_string();
|
||||
nasal_vector& get_vector();
|
||||
nasal_hash& get_hash();
|
||||
nasal_function& get_function();
|
||||
nasal_closure& get_closure();
|
||||
};
|
||||
|
||||
struct gc_unit
|
||||
{
|
||||
// collected: If gc collected this item,it'll be set to true.Otherwise it is false.
|
||||
// elem: Item that this unit stores
|
||||
// refcnt: Reference counter
|
||||
bool collected;
|
||||
bool is_const;
|
||||
nasal_scalar elem;
|
||||
int refcnt;
|
||||
gc_unit()
|
||||
{
|
||||
collected=true;
|
||||
refcnt=0;
|
||||
return;
|
||||
}
|
||||
};
|
||||
#ifndef NAS_POOL_SIZE
|
||||
#define NAS_POOL_SIZE 128
|
||||
struct memory_block
|
||||
{
|
||||
gc_unit space[NAS_POOL_SIZE];
|
||||
};
|
||||
|
||||
class memory_block_base
|
||||
{
|
||||
private:
|
||||
std::vector<memory_block*> mem_page;
|
||||
int mem_size;
|
||||
public:
|
||||
memory_block_base()
|
||||
{
|
||||
mem_size=0;
|
||||
memory_block* tmp=new memory_block;
|
||||
mem_page.push_back(tmp);
|
||||
return;
|
||||
}
|
||||
~memory_block_base()
|
||||
{
|
||||
mem_size=0;
|
||||
int page_size=mem_page.size();
|
||||
for(int i=0;i<page_size;++i)
|
||||
delete mem_page[i];
|
||||
return;
|
||||
}
|
||||
void clear()
|
||||
{
|
||||
int page_size=mem_page.size();
|
||||
for(int i=0;i<page_size;++i)
|
||||
delete mem_page[i];
|
||||
mem_page.clear();
|
||||
mem_size=0;
|
||||
memory_block* tmp=new memory_block;
|
||||
mem_page.push_back(tmp);
|
||||
return;
|
||||
}
|
||||
gc_unit& operator[](int address)
|
||||
{
|
||||
int page_num=address/NAS_POOL_SIZE;
|
||||
int block_plc=address%NAS_POOL_SIZE;
|
||||
return mem_page[page_num]->space[block_plc];
|
||||
}
|
||||
void push_back()
|
||||
{
|
||||
++mem_size;
|
||||
if(mem_size>mem_page.size()*NAS_POOL_SIZE)
|
||||
{
|
||||
memory_block* tmp=new memory_block;
|
||||
mem_page.push_back(tmp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
int size()
|
||||
{
|
||||
return mem_size;
|
||||
}
|
||||
int capacity()
|
||||
{
|
||||
return NAS_POOL_SIZE*mem_page.size();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
class gc_manager
|
||||
{
|
||||
private:
|
||||
// free_space list is used to store space that is not in use.
|
||||
std::list<int> free_space;
|
||||
/*
|
||||
cannot use std::vector to simulate memory
|
||||
because if vector memory is not enough,vector will use another larger memory as it's main memory
|
||||
then all the things will be moved to a new space,
|
||||
at this time if you reference a member in it,this will cause segmentation error.
|
||||
*/
|
||||
memory_block_base memory;
|
||||
bool error_occurred;
|
||||
public:
|
||||
void gc_init()
|
||||
{
|
||||
// this function must be called in class nasal_runtime before running any codes
|
||||
memory.clear();
|
||||
free_space.clear();
|
||||
error_occurred=false;
|
||||
return;
|
||||
}
|
||||
int gc_alloc()
|
||||
{
|
||||
// add a new space for a new value
|
||||
// if list free_space is not empty,it will get the address at the front and give it to the new value
|
||||
// if list free_space is empty,it will add new space in memory vector and give it to the new value
|
||||
// by this way it can manage memory efficiently.
|
||||
if(free_space.empty())
|
||||
{
|
||||
memory.push_back();
|
||||
free_space.push_back(memory.size()-1);
|
||||
}
|
||||
int alloc_plc=free_space.front();
|
||||
free_space.pop_front();
|
||||
memory[alloc_plc].collected=false;
|
||||
memory[alloc_plc].refcnt=1;
|
||||
return alloc_plc;
|
||||
}
|
||||
int get_reference(int addr)
|
||||
{
|
||||
// get the reference counts of the scalar
|
||||
if(addr>=memory.size())
|
||||
return -1;
|
||||
return memory[addr].refcnt;
|
||||
}
|
||||
nasal_scalar& get_scalar(int addr)
|
||||
{
|
||||
// get the reference of the scalar
|
||||
return memory[addr].elem;
|
||||
}
|
||||
bool place_check(const int addr)
|
||||
{
|
||||
// check if this place is in memory
|
||||
// and this place is uncollected
|
||||
// this function is often used when an identifier is calling a space in memory
|
||||
return (0<=addr) && (addr<memory.size()) && (!memory[addr].collected);
|
||||
}
|
||||
bool reference_add(const int addr)
|
||||
{
|
||||
if((0<=addr) && (addr<memory.size()) && (!memory[addr].collected))
|
||||
++memory[addr].refcnt;
|
||||
else
|
||||
{
|
||||
std::cout<<">> [Gc] fatal error: reference unexpected memory place ";
|
||||
prt_hex(addr);
|
||||
std::cout<<" ."<<std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool reference_delete(const int addr)
|
||||
{
|
||||
if((0<=addr) && (addr<memory.size()) && (!memory[addr].collected))
|
||||
{
|
||||
--memory[addr].refcnt;
|
||||
if(!memory[addr].refcnt)
|
||||
{
|
||||
// if refcnt is 0,then starting the destructor
|
||||
// std::cout<<">> [Gc] collected ";prt_hex(addr);std::cout<<std::endl;
|
||||
memory[addr].collected=true;
|
||||
switch(memory[addr].elem.get_type())
|
||||
{
|
||||
case scalar_number: memory[addr].elem.get_number().set_clear(); break;
|
||||
case scalar_string: memory[addr].elem.get_string().set_clear(); break;
|
||||
case scalar_vector: memory[addr].elem.get_vector().set_clear(); break;
|
||||
case scalar_hash: memory[addr].elem.get_hash().set_clear(); break;
|
||||
case scalar_function:memory[addr].elem.get_function().set_clear();break;
|
||||
case scalar_closure: memory[addr].elem.get_closure().set_clear(); break;
|
||||
default:break;
|
||||
}
|
||||
memory[addr].elem.set_type(scalar_nil);
|
||||
free_space.push_back(addr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout<<">> [Gc] fatal error: delete unexpected memory address: ";
|
||||
prt_hex(addr);
|
||||
std::cout<<" ."<<std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void info_print()
|
||||
{
|
||||
std::cout<<">> [Gc] memory size:"<<memory.size()*sizeof(gc_unit)<<" byte."<<std::endl;
|
||||
std::cout<<">> [Gc] memory capacity:"<<memory.capacity()*sizeof(gc_unit)<<" byte."<<std::endl;
|
||||
std::cout<<">> [Gc] memory usage: "<<std::endl;
|
||||
int cnt=0;
|
||||
for(int i=0;i<memory.size();++i)
|
||||
if(!memory[i].collected)
|
||||
{
|
||||
prt_hex(i);
|
||||
std::cout<<"["<<memory[i].refcnt<<"]";
|
||||
// cnt is used to check if it is the right time to output in the next line
|
||||
++cnt;
|
||||
if(!(cnt%8))
|
||||
std::cout<<std::endl;
|
||||
else
|
||||
std::cout<<" ";
|
||||
}
|
||||
if(cnt%8)
|
||||
std::cout<<std::endl;
|
||||
return;
|
||||
}
|
||||
bool check_error()
|
||||
{
|
||||
return error_occurred;
|
||||
}
|
||||
};
|
||||
gc_manager nasal_gc;
|
||||
// this object is used in "nasal_runtime.h"
|
||||
// because there must be only one gc when running a program(one process)
|
||||
|
||||
void nasal_closure::set_clear()
|
||||
{
|
||||
if(!closure.size())
|
||||
return;
|
||||
for(std::list<std::map<std::string,int> >::iterator iter=closure.begin();iter!=closure.end();++iter)
|
||||
for(std::map<std::string,int>::iterator i=iter->begin();i!=iter->end();++i)
|
||||
nasal_gc.reference_delete(i->second);
|
||||
closure.clear();
|
||||
return;
|
||||
}
|
||||
void nasal_closure::set_local_scope(std::list<std::map<std::string,int> >& tmp_scope)
|
||||
{
|
||||
if(closure.size())
|
||||
for(std::list<std::map<std::string,int> >::iterator iter=closure.begin();iter!=closure.end();++iter)
|
||||
for(std::map<std::string,int>::iterator i=iter->begin();i!=iter->end();++i)
|
||||
nasal_gc.reference_delete(i->second);
|
||||
closure.clear();
|
||||
closure=tmp_scope;
|
||||
for(std::list<std::map<std::string,int> >::iterator iter=closure.begin();iter!=closure.end();++iter)
|
||||
for(std::map<std::string,int>::iterator i=iter->begin();i!=iter->end();++i)
|
||||
nasal_gc.reference_add(i->second);
|
||||
return;
|
||||
}
|
||||
std::list<std::map<std::string,int> >& nasal_closure::get_local_scope()
|
||||
{
|
||||
return closure;
|
||||
}
|
||||
void nasal_closure::print_closure_ids()
|
||||
{
|
||||
for(std::list<std::map<std::string,int> >::iterator iter=closure.begin();iter!=closure.end();++iter)
|
||||
for(std::map<std::string,int>::iterator i=iter->begin();i!=iter->end();++i)
|
||||
{
|
||||
std::cout<<i->first<<": ";
|
||||
prt_hex(i->second);
|
||||
std::cout<<std::endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
nasal_function::nasal_function()
|
||||
{
|
||||
closure_updated=false;
|
||||
closure_addr=-1;
|
||||
return;
|
||||
}
|
||||
void nasal_function::set_clear()
|
||||
{
|
||||
closure_updated=false;
|
||||
if(closure_addr>=0)
|
||||
nasal_gc.reference_delete(closure_addr);
|
||||
closure_addr=-1;
|
||||
function_root.set_clear();
|
||||
return;
|
||||
}
|
||||
void nasal_function::set_local_scope(int tmp_addr)
|
||||
{
|
||||
if(closure_addr>=0)
|
||||
nasal_gc.reference_delete(closure_addr);
|
||||
closure_addr=tmp_addr;
|
||||
return;
|
||||
}
|
||||
bool nasal_function::get_closure_update_state()
|
||||
{
|
||||
return closure_updated;
|
||||
}
|
||||
void nasal_function::set_closure_update_state(bool _state)
|
||||
{
|
||||
closure_updated=_state;
|
||||
return;
|
||||
}
|
||||
void nasal_function::set_paramemter_list(abstract_syntax_tree& para_list)
|
||||
{
|
||||
parameter_list=para_list;
|
||||
return;
|
||||
}
|
||||
void nasal_function::set_statement_block(abstract_syntax_tree& func_block)
|
||||
{
|
||||
function_root=func_block;
|
||||
return;
|
||||
}
|
||||
int nasal_function::get_local_scope()
|
||||
{
|
||||
return closure_addr;
|
||||
}
|
||||
abstract_syntax_tree& nasal_function::get_parameter_list()
|
||||
{
|
||||
return parameter_list;
|
||||
}
|
||||
abstract_syntax_tree& nasal_function::get_statement_block()
|
||||
{
|
||||
return function_root;
|
||||
}
|
||||
void nasal_function::deep_copy(nasal_function& tmp)
|
||||
{
|
||||
if(closure_addr>=0)
|
||||
nasal_gc.reference_delete(closure_addr);
|
||||
closure_addr=tmp.closure_addr;
|
||||
nasal_gc.reference_add(closure_addr);
|
||||
// copy abstract_syntax_tree
|
||||
parameter_list=tmp.parameter_list;
|
||||
function_root=tmp.function_root;
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_number::set_clear()
|
||||
{
|
||||
nas_number=0;
|
||||
return;
|
||||
}
|
||||
void nasal_number::set_number(double num)
|
||||
{
|
||||
nas_number=num;
|
||||
return;
|
||||
}
|
||||
double nasal_number::get_number()
|
||||
{
|
||||
return nas_number;
|
||||
}
|
||||
void nasal_number::deep_copy(nasal_number& tmp)
|
||||
{
|
||||
nas_number=tmp.nas_number;
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_string::set_clear()
|
||||
{
|
||||
nas_string="";
|
||||
return;
|
||||
}
|
||||
void nasal_string::set_string(std::string str)
|
||||
{
|
||||
nas_string=str;
|
||||
return;
|
||||
}
|
||||
std::string nasal_string::get_string()
|
||||
{
|
||||
return nas_string;
|
||||
}
|
||||
void nasal_string::deep_copy(nasal_string& tmp)
|
||||
{
|
||||
nas_string=tmp.nas_string;
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_vector::set_clear()
|
||||
{
|
||||
for(int i=0;i<nas_array.size();++i)
|
||||
nasal_gc.reference_delete(nas_array[i]);
|
||||
std::vector<int> vec_for_swap;
|
||||
nas_array.swap(vec_for_swap);
|
||||
return;
|
||||
}
|
||||
void nasal_vector::vec_push(int addr)
|
||||
{
|
||||
nas_array.push_back(addr);
|
||||
return;
|
||||
}
|
||||
int* nasal_vector::get_elem_addr(int addr)
|
||||
{
|
||||
// 0 ~ size-1 -size ~ -1
|
||||
int bound=nas_array.size();
|
||||
if(-bound<=addr && addr<0)
|
||||
return &nas_array[bound+addr];
|
||||
else if(0<=addr && addr<bound)
|
||||
return &nas_array[addr];
|
||||
return NULL;
|
||||
}
|
||||
int nasal_vector::get_elem(int addr)
|
||||
{
|
||||
// 0 ~ size-1 -size ~ -1
|
||||
int bound=nas_array.size();
|
||||
if(-bound<=addr && addr<0)
|
||||
return nas_array[bound+addr];
|
||||
else if(0<=addr && addr<bound)
|
||||
return nas_array[addr];
|
||||
return -1;
|
||||
}
|
||||
int nasal_vector::vec_pop()
|
||||
{
|
||||
int ret=nas_array.back();
|
||||
nas_array.pop_back();
|
||||
return ret;
|
||||
}
|
||||
int nasal_vector::get_size()
|
||||
{
|
||||
return nas_array.size();
|
||||
}
|
||||
int* nasal_vector::get_parent_hash_member_addr(std::string member_name)
|
||||
{
|
||||
int* ret_addr=NULL;
|
||||
for(int i=0;i<nas_array.size();++i)
|
||||
if(nasal_gc.get_scalar(nas_array[i]).get_type()==scalar_hash)
|
||||
{
|
||||
ret_addr=nasal_gc.get_scalar(nas_array[i]).get_hash().get_hash_member_addr(member_name);
|
||||
if(ret_addr)
|
||||
break;
|
||||
}
|
||||
return ret_addr;
|
||||
}
|
||||
int nasal_vector::get_parent_hash_member(std::string member_name)
|
||||
{
|
||||
int ret_addr=-1;
|
||||
for(int i=0;i<nas_array.size();++i)
|
||||
if(nasal_gc.get_scalar(nas_array[i]).get_type()==scalar_hash)
|
||||
{
|
||||
ret_addr=nasal_gc.get_scalar(nas_array[i]).get_hash().get_hash_member(member_name);
|
||||
if(ret_addr>=0)
|
||||
break;
|
||||
}
|
||||
return ret_addr;
|
||||
}
|
||||
void nasal_vector::generate_new_hash()
|
||||
{
|
||||
for(int i=0;i<nas_array.size();++i)
|
||||
if(nas_array[i]>=0 && nasal_gc.get_scalar(nas_array[i]).get_type()==scalar_hash)
|
||||
{
|
||||
int tmp_addr=nas_array[i];
|
||||
nas_array[i]=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(nas_array[i]).set_type(scalar_hash);
|
||||
nasal_gc.get_scalar(nas_array[i]).get_hash().deep_copy(nasal_gc.get_scalar(tmp_addr).get_hash());
|
||||
nasal_gc.reference_delete(tmp_addr);;
|
||||
}
|
||||
return;
|
||||
}
|
||||
void nasal_vector::deep_copy(nasal_vector& tmp)
|
||||
{
|
||||
// before deep copy,nasal_vector needs to delete all values in it.
|
||||
for(int i=0;i<nas_array.size();++i)
|
||||
nasal_gc.reference_delete(nas_array[i]);
|
||||
// copy process
|
||||
for(int i=0;i<tmp.nas_array.size();++i)
|
||||
{
|
||||
int tmp_type=nasal_gc.get_scalar(tmp.nas_array[i]).get_type();
|
||||
int new_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(new_addr).set_type(tmp_type);
|
||||
if(tmp_type==scalar_nil)
|
||||
;
|
||||
else if(tmp_type==scalar_number)
|
||||
nasal_gc.get_scalar(new_addr).get_number().deep_copy(nasal_gc.get_scalar(tmp.nas_array[i]).get_number());
|
||||
else if(tmp_type==scalar_string)
|
||||
nasal_gc.get_scalar(new_addr).get_string().deep_copy(nasal_gc.get_scalar(tmp.nas_array[i]).get_string());
|
||||
else if(tmp_type==scalar_vector)
|
||||
nasal_gc.get_scalar(new_addr).get_vector().deep_copy(nasal_gc.get_scalar(tmp.nas_array[i]).get_vector());
|
||||
else if(tmp_type==scalar_hash)
|
||||
nasal_gc.get_scalar(new_addr).get_hash().deep_copy(nasal_gc.get_scalar(tmp.nas_array[i]).get_hash());
|
||||
else if(tmp_type==scalar_function)
|
||||
nasal_gc.get_scalar(new_addr).get_function().deep_copy(nasal_gc.get_scalar(tmp.nas_array[i]).get_function());
|
||||
nas_array.push_back(new_addr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_hash::set_clear()
|
||||
{
|
||||
for(std::map<std::string,int>::iterator i=nas_hash.begin();i!=nas_hash.end();++i)
|
||||
nasal_gc.reference_delete(i->second);
|
||||
return;
|
||||
}
|
||||
int* nasal_hash::get_hash_member_addr(std::string member_name)
|
||||
{
|
||||
if(nas_hash.find(member_name)!=nas_hash.end())
|
||||
return &nas_hash[member_name];
|
||||
else if(nas_hash.find("parents")!=nas_hash.end())
|
||||
return nasal_gc.get_scalar(nas_hash["parents"]).get_vector().get_parent_hash_member_addr(member_name);
|
||||
return NULL;
|
||||
}
|
||||
int nasal_hash::get_hash_member(std::string member_name)
|
||||
{
|
||||
if(nas_hash.find(member_name)!=nas_hash.end())
|
||||
return nas_hash[member_name];
|
||||
else if(nas_hash.find("parents")!=nas_hash.end())
|
||||
return nasal_gc.get_scalar(nas_hash["parents"]).get_vector().get_parent_hash_member(member_name);
|
||||
return -1;
|
||||
}
|
||||
std::vector<int> nasal_hash::get_elem()
|
||||
{
|
||||
std::vector<int> vec;
|
||||
for(std::map<std::string,int>::iterator i=nas_hash.begin();i!=nas_hash.end();++i)
|
||||
vec.push_back(i->second);
|
||||
return vec;
|
||||
}
|
||||
void nasal_hash::hash_push(std::string member_name,int addr)
|
||||
{
|
||||
nas_hash[member_name]=addr;
|
||||
return;
|
||||
}
|
||||
void nasal_hash::hash_pop(std::string member_name)
|
||||
{
|
||||
if(nas_hash.find(member_name)!=nas_hash.end())
|
||||
{
|
||||
nasal_gc.reference_delete(nas_hash[member_name]);
|
||||
nas_hash.erase(member_name);
|
||||
}
|
||||
return;
|
||||
}
|
||||
void nasal_hash::deep_copy(nasal_hash& tmp)
|
||||
{
|
||||
// defore deep copy,nasal_hash needs to delete all members in it
|
||||
for(std::map<std::string,int>::iterator i=nas_hash.begin();i!=nas_hash.end();++i)
|
||||
nasal_gc.reference_delete(i->second);
|
||||
// copy process
|
||||
for(std::map<std::string,int>::iterator i=tmp.nas_hash.begin();i!=tmp.nas_hash.end();++i)
|
||||
{
|
||||
int tmp_type=nasal_gc.get_scalar(i->second).get_type();
|
||||
int new_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(new_addr).set_type(tmp_type);
|
||||
switch(tmp_type)
|
||||
{
|
||||
case scalar_nil :break;
|
||||
case scalar_number :nasal_gc.get_scalar(new_addr).get_number().deep_copy(nasal_gc.get_scalar(i->second).get_number());break;
|
||||
case scalar_string :nasal_gc.get_scalar(new_addr).get_string().deep_copy(nasal_gc.get_scalar(i->second).get_string());break;
|
||||
case scalar_vector :nasal_gc.get_scalar(new_addr).get_vector().deep_copy(nasal_gc.get_scalar(i->second).get_vector());break;
|
||||
case scalar_hash :nasal_gc.get_scalar(new_addr).get_hash().deep_copy(nasal_gc.get_scalar(i->second).get_hash());break;
|
||||
case scalar_function:nasal_gc.get_scalar(new_addr).get_function().deep_copy(nasal_gc.get_scalar(i->second).get_function());break;
|
||||
}
|
||||
nas_hash[i->first]=new_addr;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
nasal_scalar::nasal_scalar()
|
||||
{
|
||||
type=scalar_nil;
|
||||
return;
|
||||
}
|
||||
void nasal_scalar::set_type(int tmp_type)
|
||||
{
|
||||
// scalar_function is the last enum in enum::scalar_type
|
||||
type=tmp_type>scalar_closure? scalar_nil:tmp_type;
|
||||
return;
|
||||
}
|
||||
int nasal_scalar::get_type()
|
||||
{
|
||||
// get scalar type
|
||||
return type;
|
||||
}
|
||||
nasal_number& nasal_scalar::get_number()
|
||||
{
|
||||
// get nasal_number
|
||||
return var_number;
|
||||
}
|
||||
nasal_string& nasal_scalar::get_string()
|
||||
{
|
||||
// get nasal_string
|
||||
return var_string;
|
||||
}
|
||||
nasal_vector& nasal_scalar::get_vector()
|
||||
{
|
||||
// get nasal_vector
|
||||
return var_vector;
|
||||
}
|
||||
nasal_hash& nasal_scalar::get_hash()
|
||||
{
|
||||
// get nasal_hash
|
||||
return var_hash;
|
||||
}
|
||||
nasal_function& nasal_scalar::get_function()
|
||||
{
|
||||
// get nasal_function
|
||||
return var_func;
|
||||
}
|
||||
nasal_closure& nasal_scalar::get_closure()
|
||||
{
|
||||
// get nasal_closure
|
||||
return var_cls;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
code: var i=1;
|
||||
int addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(addr).set_type(scalar_number);
|
||||
nasal_gc.get_scalar(addr).set_number(1);
|
||||
|
||||
code: var i='hello';
|
||||
int addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(addr).set_type(scalar_string);
|
||||
nasal_gc.get_scalar(addr).set_string("hello");
|
||||
|
||||
code: var i=[];
|
||||
int addr=vector_generation();
|
||||
nasal_gc.get_scalar(addr).set_type(scalar_vector);
|
||||
|
||||
code: var i={};
|
||||
int addr=hash_generation();
|
||||
nasal_gc.get_scalar(addr).set_type(scalar_hash);
|
||||
nasal_gc.get_scalar(addr).get_hash().set_self_addr(addr);
|
||||
|
||||
code: var i=func{return 0;}
|
||||
// copy local_scope if needed
|
||||
// copy abstract_syntax_tree
|
||||
*/
|
|
@ -1,528 +0,0 @@
|
|||
#ifndef __NASAL_LEXER_H__
|
||||
#define __NASAL_LEXER_H__
|
||||
|
||||
#define IS_IDENTIFIER_HEAD(c) (c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z')
|
||||
#define IS_IDENTIFIER_BODY(c) (c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z')||('0'<=c&&c<='9')
|
||||
#define IS_NUMBER_HEAD(c) ('0'<=c&&c<='9')
|
||||
#define IS_NUMBER_BODY(c) ('0'<=c&&c<='9')||('a'<=c&&c<='f')||('A'<=c&&c<='F')||(c=='e'||c=='E'||c=='.'||c=='x'||c=='o')
|
||||
#define IS_STRING_HEAD(c) (c=='\''||c=='\"')
|
||||
// single operators have only one character
|
||||
#define IS_SINGLE_OPRATOR(c) (c=='('||c==')'||c=='['||c==']'||c=='{'||c=='}'||c==','||c==';'||c=='|'||c==':'||\
|
||||
c=='?'||c=='.'||c=='`'||c=='&'||c=='@'||c=='%'||c=='$'||c=='^'||c=='\\')
|
||||
// calculation operators may have two chars, for example: += -= *= /= ~= != == >= <=
|
||||
#define IS_CALC_OPERATOR(c) (c=='='||c=='+'||c=='-'||c=='*'||c=='!'||c=='/'||c=='<'||c=='>'||c=='~')
|
||||
#define IS_NOTE_HEAD(c) (c=='#')
|
||||
|
||||
/* filenames of lib files */
|
||||
#ifndef LIB_FILE_NUM
|
||||
#define LIB_FILE_NUM 11
|
||||
const std::string lib_filename[LIB_FILE_NUM]=
|
||||
{
|
||||
"lib/base.nas",
|
||||
"lib/bits.nas",
|
||||
"lib/io.nas",
|
||||
"lib/math.nas",
|
||||
"lib/readline.nas",
|
||||
"lib/regex.nas",
|
||||
"lib/sqlite.nas",
|
||||
"lib/system.nas",
|
||||
"lib/thread.nas",
|
||||
"lib/unix.nas",
|
||||
"lib/utf8.nas"
|
||||
};
|
||||
#endif
|
||||
|
||||
/* reserve words */
|
||||
#ifndef RESERVE_WORD_NUM
|
||||
#define RESERVE_WORD_NUM 15
|
||||
std::string reserve_word[RESERVE_WORD_NUM]=
|
||||
{
|
||||
"for","foreach","forindex","while",
|
||||
"var","func","break","continue","return",
|
||||
"if","else","elsif","and","or","nil"
|
||||
};
|
||||
/* check if an identifier is a reserve word */
|
||||
int is_reserve_word(std::string str)
|
||||
{
|
||||
for(int i=0;i<RESERVE_WORD_NUM;++i)
|
||||
if(reserve_word[i]==str)
|
||||
return __token_reserve_word;
|
||||
return __token_identifier;
|
||||
}
|
||||
#endif
|
||||
|
||||
class resource_file
|
||||
{
|
||||
private:
|
||||
std::vector<char> source_code;
|
||||
public:
|
||||
/*
|
||||
delete_all_source: clear all the source codes in std::list<char> resource
|
||||
input_file : input source codes by filenames
|
||||
load_lib_file : input lib source codes
|
||||
get_source : get the std::vector<char> source_code
|
||||
print_resource : print source codes
|
||||
*/
|
||||
void delete_all_source();
|
||||
void input_file(std::string);
|
||||
void load_lib_file();
|
||||
std::vector<char>& get_source();
|
||||
void print_resource();
|
||||
};
|
||||
|
||||
/* struct token: mainly used in nasal_lexer and nasal_parse*/
|
||||
struct token
|
||||
{
|
||||
int line;
|
||||
int type;
|
||||
std::string str;
|
||||
token& operator=(const token& tmp)
|
||||
{
|
||||
line=tmp.line;
|
||||
type=tmp.type;
|
||||
str =tmp.str;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
class nasal_lexer
|
||||
{
|
||||
private:
|
||||
std::list<token> token_list;
|
||||
std::list<token> detail_token_list;
|
||||
int error;
|
||||
std::string identifier_gen(std::vector<char>&,int&,int&);
|
||||
std::string number_gen (std::vector<char>&,int&,int&);
|
||||
std::string string_gen (std::vector<char>&,int&,int&);
|
||||
public:
|
||||
/*
|
||||
identifier_gen : scan the source codes and generate identifiers
|
||||
number_gen : scan the source codes and generate numbers
|
||||
string_gen : scan the source codes and generate strings
|
||||
print_token_list : print generated token list
|
||||
scanner : scan the source codes and generate tokens
|
||||
generate_detail_token: recognize and change token types to detailed types that can be processed by nasal_parse
|
||||
get_error : get the number of errors that occurred when generating tokens
|
||||
get_detail_token : output the detailed tokens,must be used after generate_detail_token()
|
||||
*/
|
||||
nasal_lexer();
|
||||
~nasal_lexer();
|
||||
void delete_all_tokens();
|
||||
void print_token_list();
|
||||
void scanner(std::vector<char>&);
|
||||
void generate_detail_token();
|
||||
int get_error();
|
||||
std::list<token>& get_detail_token_list();
|
||||
};
|
||||
|
||||
|
||||
void resource_file::delete_all_source()
|
||||
{
|
||||
std::vector<char> tmp;
|
||||
source_code.clear();
|
||||
source_code.swap(tmp);
|
||||
// use tmp's destructor to delete the memory space that source_code used before
|
||||
return;
|
||||
}
|
||||
void resource_file::input_file(std::string filename)
|
||||
{
|
||||
char c=0;
|
||||
std::ifstream fin(filename,std::ios::binary);
|
||||
if(fin.fail())
|
||||
{
|
||||
std::cout<<">> [Resource] cannot open file \'"<<filename<<"\' ."<<std::endl;
|
||||
fin.close();
|
||||
return;
|
||||
}
|
||||
while(!fin.eof())
|
||||
{
|
||||
c=fin.get();
|
||||
if(fin.eof()) break;
|
||||
source_code.push_back(c);
|
||||
}
|
||||
fin.close();
|
||||
return;
|
||||
}
|
||||
void resource_file::load_lib_file()
|
||||
{
|
||||
source_code.clear();
|
||||
for(int i=0;i<LIB_FILE_NUM;++i)
|
||||
{
|
||||
std::ifstream fin(lib_filename[i],std::ios::binary);
|
||||
if(fin.fail())
|
||||
std::cout<<">> [Resource] fatal error: lack \'"<<lib_filename[i]<<"\'"<<std::endl;
|
||||
else
|
||||
{
|
||||
char c=0;
|
||||
while(!fin.eof())
|
||||
{
|
||||
c=fin.get();
|
||||
if(fin.eof()) break;
|
||||
source_code.push_back(c);
|
||||
}
|
||||
}
|
||||
fin.close();
|
||||
}
|
||||
return;
|
||||
}
|
||||
std::vector<char>& resource_file::get_source()
|
||||
{
|
||||
return source_code;
|
||||
}
|
||||
void resource_file::print_resource()
|
||||
{
|
||||
int size=source_code.size();
|
||||
int line=1;
|
||||
std::cout<<line<<"\t";
|
||||
std::string unicode_str="";
|
||||
for(int i=0;i<size;++i)
|
||||
{
|
||||
if(source_code[i]>=0 && unicode_str.length())
|
||||
{
|
||||
std::cout<<unicode_str;
|
||||
unicode_str="";
|
||||
}
|
||||
if(32<=source_code[i]) std::cout<<source_code[i];
|
||||
else if(source_code[i]<0) unicode_str+=source_code[i];
|
||||
else std::cout<<" ";
|
||||
if(source_code[i]=='\n')
|
||||
{
|
||||
++line;
|
||||
std::cout<<std::endl<<line<<"\t";
|
||||
}
|
||||
}
|
||||
if(unicode_str.length())
|
||||
std::cout<<unicode_str;
|
||||
std::cout<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string nasal_lexer::identifier_gen(std::vector<char>& res,int& ptr,int& line)
|
||||
{
|
||||
int res_size=res.size();
|
||||
std::string token_str="";
|
||||
while(ptr<res_size && IS_IDENTIFIER_BODY(res[ptr]))
|
||||
{
|
||||
token_str+=res[ptr];
|
||||
++ptr;
|
||||
}
|
||||
// check dynamic identifier "..."
|
||||
if(ptr+2<res_size && res[ptr]=='.' && res[ptr+1]=='.' && res[ptr+2]=='.')
|
||||
{
|
||||
token_str+="...";
|
||||
ptr+=3;
|
||||
}
|
||||
return token_str;
|
||||
// after running this process, ptr will point to the next token's beginning character
|
||||
}
|
||||
|
||||
std::string nasal_lexer::number_gen(std::vector<char>& res,int& ptr,int& line)
|
||||
{
|
||||
int res_size=res.size();
|
||||
bool scientific_notation=false;// numbers like 1e8 are scientific_notation
|
||||
std::string token_str="";
|
||||
while(ptr<res_size && IS_NUMBER_BODY(res[ptr]))
|
||||
{
|
||||
token_str+=res[ptr];
|
||||
if(res[ptr]=='e' || res[ptr]=='E')
|
||||
{
|
||||
scientific_notation=true;
|
||||
++ptr;
|
||||
break;
|
||||
}
|
||||
++ptr;
|
||||
}
|
||||
if(scientific_notation && ptr<res_size)
|
||||
{
|
||||
if(res[ptr]=='-')
|
||||
{
|
||||
token_str+='-';
|
||||
++ptr;
|
||||
}
|
||||
while(ptr<res_size && '0'<=res[ptr] && res[ptr]<='9')
|
||||
{
|
||||
token_str+=res[ptr];
|
||||
++ptr;
|
||||
}
|
||||
}
|
||||
if(!check_numerable_string(token_str))
|
||||
{
|
||||
++error;
|
||||
std::cout<<">> [Lexer] line "<<line<<": "<<token_str<<" is not a numerable string."<<std::endl;
|
||||
token_str="0";
|
||||
}
|
||||
return token_str;
|
||||
}
|
||||
std::string nasal_lexer::string_gen(std::vector<char>& res,int& ptr,int& line)
|
||||
{
|
||||
int res_size=res.size();
|
||||
std::string token_str="";
|
||||
char str_begin=res[ptr];
|
||||
++ptr;
|
||||
if(ptr>=res_size) return token_str;
|
||||
while(ptr<res_size && res[ptr]!=str_begin)
|
||||
{
|
||||
token_str+=res[ptr];
|
||||
if(res[ptr]=='\n') ++line;
|
||||
if(res[ptr]=='\\' && ptr+1<res.size())
|
||||
{
|
||||
++ptr;
|
||||
switch(res[ptr])
|
||||
{
|
||||
case '\\':token_str.pop_back();token_str.push_back('\\');break;
|
||||
case 'r': token_str.pop_back();token_str.push_back('\r');break;
|
||||
case 't': token_str.pop_back();token_str.push_back('\t');break;
|
||||
case 'n': token_str.pop_back();token_str.push_back('\n');break;
|
||||
case '\'':token_str.pop_back();token_str.push_back('\'');break;
|
||||
case '\"':token_str.pop_back();token_str.push_back('\"');break;
|
||||
default: token_str.push_back(res[ptr]);break;
|
||||
}
|
||||
}
|
||||
++ptr;
|
||||
}
|
||||
// check if this string ends with a " or '
|
||||
if(ptr>=res_size)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">> [Lexer] line "<<line<<": this string must have a \' "<<str_begin<<" \' as its end."<<std::endl;
|
||||
}
|
||||
++ptr;
|
||||
return token_str;
|
||||
}
|
||||
nasal_lexer::nasal_lexer()
|
||||
{
|
||||
token_list.clear();
|
||||
detail_token_list.clear();
|
||||
error=0;
|
||||
return;
|
||||
}
|
||||
nasal_lexer::~nasal_lexer()
|
||||
{
|
||||
token_list.clear();
|
||||
detail_token_list.clear();
|
||||
return;
|
||||
}
|
||||
void nasal_lexer::delete_all_tokens()
|
||||
{
|
||||
token_list.clear();
|
||||
detail_token_list.clear();
|
||||
error=0;
|
||||
return;
|
||||
}
|
||||
void nasal_lexer::print_token_list()
|
||||
{
|
||||
for(std::list<token>::iterator i=token_list.begin();i!=token_list.end();++i)
|
||||
{
|
||||
std::cout<<"line "<<i->line<<" ( ";
|
||||
print_lexer_token(i->type);
|
||||
std::cout<<" | "<<i->str<<" )"<<std::endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
void nasal_lexer::scanner(std::vector<char>& res)
|
||||
{
|
||||
token_list.clear();
|
||||
detail_token_list.clear();
|
||||
error=0;
|
||||
|
||||
int line=1,ptr=0,res_size=res.size();
|
||||
std::string token_str;
|
||||
while(ptr<res_size)
|
||||
{
|
||||
while(ptr<res_size && (res[ptr]==' ' || res[ptr]=='\n' || res[ptr]=='\t' || res[ptr]=='\r' || res[ptr]<0))
|
||||
{
|
||||
// these characters will be ignored, and '\n' will cause ++line
|
||||
if(res[ptr]=='\n') ++line;
|
||||
++ptr;
|
||||
}
|
||||
if(ptr>=res_size) break;
|
||||
if(IS_IDENTIFIER_HEAD(res[ptr]))
|
||||
{
|
||||
token_str=identifier_gen(res,ptr,line);
|
||||
token new_token;
|
||||
new_token.line=line;
|
||||
new_token.type=is_reserve_word(token_str);
|
||||
new_token.str=token_str;
|
||||
token_list.push_back(new_token);
|
||||
}
|
||||
else if(IS_NUMBER_HEAD(res[ptr]))
|
||||
{
|
||||
token_str=number_gen(res,ptr,line);
|
||||
token new_token;
|
||||
new_token.line=line;
|
||||
new_token.type=__token_number;
|
||||
new_token.str=token_str;
|
||||
token_list.push_back(new_token);
|
||||
}
|
||||
else if(IS_STRING_HEAD(res[ptr]))
|
||||
{
|
||||
token_str=string_gen(res,ptr,line);
|
||||
token new_token;
|
||||
new_token.line=line;
|
||||
new_token.type=__token_string;
|
||||
new_token.str=token_str;
|
||||
token_list.push_back(new_token);
|
||||
}
|
||||
else if(IS_SINGLE_OPRATOR(res[ptr]))
|
||||
{
|
||||
token_str="";
|
||||
token_str+=res[ptr];
|
||||
token new_token;
|
||||
new_token.line=line;
|
||||
new_token.type=__token_operator;
|
||||
new_token.str=token_str;
|
||||
token_list.push_back(new_token);
|
||||
++ptr;
|
||||
}
|
||||
else if(IS_CALC_OPERATOR(res[ptr]))
|
||||
{
|
||||
// get calculation operator
|
||||
token_str="";
|
||||
token_str+=res[ptr];
|
||||
++ptr;
|
||||
if(ptr<res.size() && res[ptr]=='=')
|
||||
{
|
||||
token_str+=res[ptr];
|
||||
++ptr;
|
||||
}
|
||||
token new_token;
|
||||
new_token.line=line;
|
||||
new_token.type=__token_operator;
|
||||
new_token.str=token_str;
|
||||
token_list.push_back(new_token);
|
||||
}
|
||||
else if(IS_NOTE_HEAD(res[ptr]))
|
||||
{
|
||||
// avoid note
|
||||
while(ptr<res_size && res[ptr]!='\n')
|
||||
++ptr;
|
||||
// after this process ptr will point to a '\n'
|
||||
// don't ++ptr then the counter for line can work correctly
|
||||
}
|
||||
else
|
||||
{
|
||||
++error;
|
||||
std::cout<<">> [Lexer] line "<<line<<": unknown char."<<std::endl;
|
||||
++ptr;
|
||||
}
|
||||
}
|
||||
std::cout<<">> [Lexer] complete scanning. "<<error<<" error(s)."<<std::endl;
|
||||
return;
|
||||
}
|
||||
void nasal_lexer::generate_detail_token()
|
||||
{
|
||||
token detail_token;
|
||||
detail_token_list.clear();
|
||||
for(std::list<token>::iterator i=token_list.begin();i!=token_list.end();++i)
|
||||
{
|
||||
if(i->type==__token_number)
|
||||
{
|
||||
detail_token.line=i->line;
|
||||
detail_token.str =i->str;
|
||||
detail_token.type=__number;
|
||||
detail_token_list.push_back(detail_token);
|
||||
}
|
||||
else if(i->type==__token_string)
|
||||
{
|
||||
detail_token.line=i->line;
|
||||
detail_token.str =i->str;
|
||||
detail_token.type=__string;
|
||||
detail_token_list.push_back(detail_token);
|
||||
}
|
||||
else if(i->type==__token_reserve_word)
|
||||
{
|
||||
detail_token.line=i->line;
|
||||
detail_token.str ="";
|
||||
if (i->str=="for" ) detail_token.type=__for;
|
||||
else if(i->str=="foreach" ) detail_token.type=__foreach;
|
||||
else if(i->str=="forindex") detail_token.type=__forindex;
|
||||
else if(i->str=="while" ) detail_token.type=__while;
|
||||
else if(i->str=="var" ) detail_token.type=__var;
|
||||
else if(i->str=="func" ) detail_token.type=__func;
|
||||
else if(i->str=="break" ) detail_token.type=__break;
|
||||
else if(i->str=="continue") detail_token.type=__continue;
|
||||
else if(i->str=="return" ) detail_token.type=__return;
|
||||
else if(i->str=="if" ) detail_token.type=__if;
|
||||
else if(i->str=="else" ) detail_token.type=__else;
|
||||
else if(i->str=="elsif" ) detail_token.type=__elsif;
|
||||
else if(i->str=="nil" ) detail_token.type=__nil;
|
||||
else if(i->str=="and" ) detail_token.type=__and_operator;
|
||||
else if(i->str=="or" ) detail_token.type=__or_operator;
|
||||
detail_token_list.push_back(detail_token);
|
||||
}
|
||||
else if(i->type==__token_identifier)
|
||||
{
|
||||
detail_token.line=i->line;
|
||||
detail_token.str =i->str;
|
||||
if(i->str.length()<=3)
|
||||
detail_token.type=__id;
|
||||
else
|
||||
{
|
||||
std::string tempstr=i->str;
|
||||
int len=tempstr.length(),strback=tempstr.length()-1;
|
||||
if(tempstr[strback]=='.' && tempstr[strback-1]=='.' && tempstr[strback-2]=='.')
|
||||
{
|
||||
detail_token.str="";
|
||||
for(int j=0;j<len-3;++j)
|
||||
detail_token.str+=tempstr[j];
|
||||
detail_token.type=__dynamic_id;
|
||||
}
|
||||
else
|
||||
detail_token.type=__id;
|
||||
}
|
||||
detail_token_list.push_back(detail_token);
|
||||
}
|
||||
else if(i->type==__token_operator)
|
||||
{
|
||||
detail_token.line=i->line;
|
||||
detail_token.str ="";
|
||||
if (i->str=="+" ) detail_token.type=__add_operator;
|
||||
else if(i->str=="-" ) detail_token.type=__sub_operator;
|
||||
else if(i->str=="*" ) detail_token.type=__mul_operator;
|
||||
else if(i->str=="/" ) detail_token.type=__div_operator;
|
||||
else if(i->str=="~" ) detail_token.type=__link_operator;
|
||||
else if(i->str=="+=") detail_token.type=__add_equal;
|
||||
else if(i->str=="-=") detail_token.type=__sub_equal;
|
||||
else if(i->str=="*=") detail_token.type=__mul_equal;
|
||||
else if(i->str=="/=") detail_token.type=__div_equal;
|
||||
else if(i->str=="~=") detail_token.type=__link_equal;
|
||||
else if(i->str=="=" ) detail_token.type=__equal;
|
||||
else if(i->str=="==") detail_token.type=__cmp_equal;
|
||||
else if(i->str=="!=") detail_token.type=__cmp_not_equal;
|
||||
else if(i->str=="<" ) detail_token.type=__cmp_less;
|
||||
else if(i->str=="<=") detail_token.type=__cmp_less_or_equal;
|
||||
else if(i->str==">" ) detail_token.type=__cmp_more;
|
||||
else if(i->str==">=") detail_token.type=__cmp_more_or_equal;
|
||||
else if(i->str==";" ) detail_token.type=__semi;
|
||||
else if(i->str=="." ) detail_token.type=__dot;
|
||||
else if(i->str==":" ) detail_token.type=__colon;
|
||||
else if(i->str=="," ) detail_token.type=__comma;
|
||||
else if(i->str=="?" ) detail_token.type=__ques_mark;
|
||||
else if(i->str=="!" ) detail_token.type=__nor_operator;
|
||||
else if(i->str=="[" ) detail_token.type=__left_bracket;
|
||||
else if(i->str=="]" ) detail_token.type=__right_bracket;
|
||||
else if(i->str=="(" ) detail_token.type=__left_curve;
|
||||
else if(i->str==")" ) detail_token.type=__right_curve;
|
||||
else if(i->str=="{" ) detail_token.type=__left_brace;
|
||||
else if(i->str=="}" ) detail_token.type=__right_brace;
|
||||
else
|
||||
{
|
||||
++error;
|
||||
std::cout<<">> [Lexer] line "<<detail_token.line<<": unknown operator \'"<<i->str<<"\'."<<std::endl;
|
||||
detail_token.type=__unknown_operator;
|
||||
}
|
||||
detail_token_list.push_back(detail_token);
|
||||
}
|
||||
}
|
||||
std::cout<<">> [Lexer] complete generating. "<<error<<" error(s)."<<std::endl;
|
||||
return;
|
||||
}
|
||||
int nasal_lexer::get_error()
|
||||
{
|
||||
return error;
|
||||
}
|
||||
std::list<token>& nasal_lexer::get_detail_token_list()
|
||||
{
|
||||
return detail_token_list;
|
||||
}
|
||||
#endif
|
|
@ -1,266 +0,0 @@
|
|||
#ifndef __NASAL_MISC_H__
|
||||
#define __NASAL_MISC_H__
|
||||
|
||||
/*
|
||||
check_numerable_string:
|
||||
check if a string can be converted to a number
|
||||
|
||||
strings like these below is correct:
|
||||
'0.00012'
|
||||
'12314.234'
|
||||
'1234'
|
||||
'0xdeadbeef'
|
||||
'0xDEADBEEF'
|
||||
'0o71230'
|
||||
'1e23'
|
||||
'1E-123'
|
||||
'1.34E10'
|
||||
*/
|
||||
inline bool check_hex_string(std::string str,int len)
|
||||
{
|
||||
for(int i=2;i<len;++i)
|
||||
if(!(('0'<=str[i] && str[i]<='9') || ('a'<=str[i] && str[i]<='f') || ('A'<=str[i] && str[i]<='F')))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
inline bool check_oct_string(std::string str,int len)
|
||||
{
|
||||
for(int i=2;i<len;++i)
|
||||
if(str[i]<'0' || str[i]>'7')
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
inline bool check_dec_string(std::string str,int len)
|
||||
{
|
||||
int dot_cnt=0;
|
||||
if(str[0]=='.') return false;
|
||||
if(str[0]=='0' && ('0'<=str[1] && str[1]<='9')) return false;
|
||||
int i=0;
|
||||
for(;i<len;++i)
|
||||
{
|
||||
if(str[i]=='.')
|
||||
{
|
||||
if(i==len-1 || str[i+1]=='e' || str[i+1]=='E') return false;
|
||||
++dot_cnt;
|
||||
}
|
||||
else if(str[i]=='e' || str[i]=='E') break;
|
||||
else if(str[i]<'0' || str[i]>'9' ) return false;
|
||||
}
|
||||
if(str[i]=='e' || str[i]=='E')
|
||||
{
|
||||
++i;
|
||||
if(i==len) return false;
|
||||
if(str[i]=='-')
|
||||
{
|
||||
++i;
|
||||
if(i==len) return false;
|
||||
}
|
||||
for(;i<len;++i)
|
||||
if(str[i]<'0' || str[i]>'9')
|
||||
return false;
|
||||
}
|
||||
if(dot_cnt>1) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool check_numerable_string(std::string str)
|
||||
{
|
||||
int len=str.length();
|
||||
if(!len) return false;
|
||||
if(str[0]=='-' && len>1)
|
||||
{
|
||||
std::string tmp="";
|
||||
for(int i=1;i<len;++i)
|
||||
tmp.push_back(str[i]);
|
||||
str=tmp;
|
||||
}
|
||||
else if(str[0]=='-' && len==1)
|
||||
return false;
|
||||
if(len==1 && '0'<=str[0] && str[0]<='9')
|
||||
return true;
|
||||
else if(len>2 && str[0]=='0' && str[1]=='x')
|
||||
return check_hex_string(str,len);
|
||||
else if(len>2 && str[0]=='0' && str[1]=='o')
|
||||
return check_oct_string(str,len);
|
||||
else if('0'<=str[0] && str[0]<='9')
|
||||
return check_dec_string(str,len);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
trans_string_to_number:
|
||||
convert string to number
|
||||
*/
|
||||
inline double hex_to_double(std::string str,int len)
|
||||
{
|
||||
double ret=0;
|
||||
double num_pow=1;
|
||||
for(int i=len-1;i>1;--i)
|
||||
{
|
||||
if('0'<=str[i] && str[i]<='9')
|
||||
ret+=num_pow*(str[i]-'0');
|
||||
else if('a'<=str[i] && str[i]<='f')
|
||||
ret+=num_pow*(str[i]-'a'+10);
|
||||
else if('A'<=str[i] && str[i]<='F')
|
||||
ret+=num_pow*(str[i]-'A'+10);
|
||||
num_pow*=16;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
inline double oct_to_double(std::string str,int len)
|
||||
{
|
||||
double ret=0;
|
||||
double num_pow=1;
|
||||
for(int i=len-1;i>1;--i)
|
||||
{
|
||||
ret+=num_pow*(str[i]-'0');
|
||||
num_pow*=8;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
inline double dec_to_double(std::string str,int len)
|
||||
{
|
||||
double ret=0;
|
||||
int i=0;
|
||||
for(;i<len;++i)
|
||||
{
|
||||
if('0'<=str[i] && str[i]<='9')
|
||||
ret=ret*10+(str[i]-'0');
|
||||
else if(str[i]=='.' || str[i]=='e' || str[i]=='E')
|
||||
break;
|
||||
}
|
||||
if(str[i]=='.')
|
||||
{
|
||||
++i;
|
||||
double num_pow=0.1;
|
||||
for(;i<len;++i)
|
||||
{
|
||||
if('0'<=str[i] && str[i]<='9')
|
||||
{
|
||||
ret+=num_pow*(str[i]-'0');
|
||||
num_pow*=0.1;
|
||||
}
|
||||
else if(str[i]=='e' || str[i]=='E')
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(str[i]=='e' || str[i]=='E')
|
||||
{
|
||||
|
||||
++i;
|
||||
bool is_negative=(str[i]=='-');
|
||||
if(is_negative) ++i;
|
||||
double num_pow=0;
|
||||
for(;i<len;++i) num_pow=num_pow*10+(str[i]-'0');
|
||||
num_pow=std::pow(10,is_negative?-num_pow:num_pow);
|
||||
ret*=num_pow;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
double trans_string_to_number(std::string str)
|
||||
{
|
||||
bool is_negative=false;
|
||||
int len=str.length();
|
||||
double ret_num=0;
|
||||
if(!len) return 0;
|
||||
if(str[0]=='-' && len>1)
|
||||
{
|
||||
is_negative=true;
|
||||
std::string tmp="";
|
||||
for(int i=1;i<len;++i)
|
||||
tmp.push_back(str[i]);
|
||||
str=tmp;
|
||||
}
|
||||
else if(str[0]=='-' && len==1)
|
||||
return 0;
|
||||
if(len==1 && '0'<=str[0] && str[0]<='9')
|
||||
ret_num=(double)(str[0]-'0');
|
||||
else if(len>2 && str[0]=='0' && str[1]=='x')
|
||||
ret_num=hex_to_double(str,len);
|
||||
else if(len>2 && str[0]=='0' && str[1]=='o')
|
||||
ret_num=oct_to_double(str,len);
|
||||
else if('0'<=str[0] && str[0]<='9')
|
||||
ret_num=dec_to_double(str,len);
|
||||
return is_negative?-ret_num:ret_num;
|
||||
}
|
||||
|
||||
/*
|
||||
trans_number_to_string:
|
||||
convert number to string
|
||||
*/
|
||||
std::string trans_number_to_string(double number)
|
||||
{
|
||||
std::string trans_num_string="";
|
||||
if(number<0)
|
||||
{
|
||||
trans_num_string+='-';
|
||||
number=-number;
|
||||
}
|
||||
double integer_bit=1;
|
||||
while(number>=integer_bit)
|
||||
integer_bit*=10;
|
||||
integer_bit/=10;
|
||||
while(integer_bit!=0.1)
|
||||
{
|
||||
trans_num_string+=(char)('0'+(int(number/integer_bit)));
|
||||
number-=(double)(int(number/integer_bit))*integer_bit;
|
||||
integer_bit/=10;
|
||||
}
|
||||
if(number!=0)
|
||||
trans_num_string+='.';
|
||||
while(number!=0)
|
||||
{
|
||||
trans_num_string+=(char)('0'+int(number*10));
|
||||
number*=10;
|
||||
number-=(double)(int(number));
|
||||
}
|
||||
return trans_num_string;
|
||||
}
|
||||
|
||||
/*
|
||||
prt_hex:
|
||||
transform int to hex format and print it out (std::cout)
|
||||
*/
|
||||
void prt_hex(const int ptr)
|
||||
{
|
||||
char hex[9];
|
||||
hex[8]=0;
|
||||
int tmp_plc=ptr;
|
||||
if(tmp_plc<0)
|
||||
{
|
||||
tmp_plc=-tmp_plc;
|
||||
std::cout<<"-0x";
|
||||
}
|
||||
else
|
||||
std::cout<<"0x";
|
||||
/*
|
||||
int: 00000000 00000000 00000000 00000000
|
||||
int: 0x00 00 00 00
|
||||
example:
|
||||
a=0x13 57 9b df
|
||||
a=00010011 01010111 10011011 11011111
|
||||
a & 0x00 00 00 0f:
|
||||
00010011 01010111 10011011 11011111
|
||||
and 00000000 00000000 00000000 00001111
|
||||
---------------------------------------
|
||||
00000000 00000000 00000000 00001111
|
||||
a>>=4:
|
||||
00000001 00110101 01111001 10111101
|
||||
a & 0x00 00 00 0f
|
||||
00000001 00110101 01111001 10111101
|
||||
and 00000000 00000000 00000000 00001111
|
||||
---------------------------------------
|
||||
00000000 00000000 00000000 00001101
|
||||
then convert 0~15 to 0~9 a~f
|
||||
*/
|
||||
for(int j=7;j>=0;--j)
|
||||
{
|
||||
int tmp=(tmp_plc & 0x0000000f);
|
||||
hex[j]=tmp<10? (char)('0'+tmp):(char)('a'+tmp-10);
|
||||
tmp_plc>>=4;
|
||||
}
|
||||
std::cout<<hex;
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,116 +0,0 @@
|
|||
(*
|
||||
<> must choose
|
||||
[] can choose
|
||||
{} can repeat 0 to infinite time(s)
|
||||
| or
|
||||
::= is defined as
|
||||
*)
|
||||
<var> = <token_var_reserve_word> ;
|
||||
<func> = <token_func_reserve_word> ;
|
||||
<and> = <token_and_operator> ;
|
||||
<or> = <token_or_operator> ;
|
||||
<number> = <token_number> ;
|
||||
<string> = <token_string> ;
|
||||
<nil> = <token_reserve_word_nil> ;
|
||||
<id> = <token_identifier> ;
|
||||
<dynamic_id> = <token_dynamic_id> ;
|
||||
|
||||
<vector> = '[' { <calculation> ',' } ']' ;
|
||||
<hash> = '{' {(<id> | <string>) ':' <scalar> ','} '}' ;
|
||||
<scalar> =
|
||||
<number>
|
||||
| <nil>
|
||||
| <string>
|
||||
| <id>
|
||||
| <hash>
|
||||
| <vector>
|
||||
| <func> <id>
|
||||
| <function>
|
||||
| '(' <calculation> ')'
|
||||
| <scalar> { ('[' {<calculation> ','} ']') | ('[' <calculation> ':' [<calculation>] ']') | ('.' <id>) | ('(' {<calculation> ','} ')') | ('(' {<id> ':' <calculation> ','} ')') }
|
||||
;
|
||||
|
||||
<function> =
|
||||
<func> ['(' ')'] <statement>
|
||||
| <func> ['(' ')'] '{' {<statement> ';'} '}'
|
||||
| <func> '(' {<id> ','} {<id> '=' <calculation> ','} {<dynamic_id>} ')' <statement>
|
||||
| <func> '(' {<id> ','} {<id> '=' <calculation> ','} {<dynamic_id>} ')' '{' {<statement> ';'} '}'
|
||||
;
|
||||
|
||||
<calculation> =
|
||||
<and_calc>
|
||||
| <or_calc>
|
||||
| <additive_calc>
|
||||
| <multive_calc>
|
||||
| [('-' | '!')] <scalar>
|
||||
| <calculation> '?' <calculation> ':' <calculation>
|
||||
;
|
||||
<and_calc> = <or_calc> {<and> <or_calc>} ;
|
||||
<or_calc> = <additive_calc> {<or> <additive_calc>} ;
|
||||
<additive_calc> = <multive_calc> {('+' | '-' | '~') <multive_calc>} ;
|
||||
<multive_calc> = [('-' | '!')] <scalar> {('*' | '/') [('-' | '!')] <scalar>};
|
||||
|
||||
(* this definition is also used in for loop*)
|
||||
<definition> =
|
||||
<var> <id> '=' <scalar>
|
||||
| <var> '(' {<id> ','} ')' '=' (<scalar> | '(' {<scalar> ','} ')')
|
||||
| '(' <var> {<id> ','} ')' '=' (<scalar> | '(' {<scalar> ','} ')')
|
||||
;
|
||||
|
||||
<assignment> =
|
||||
<scalar> ('=' | '+=' | '-=' | '*=' | '/=' | '~=') <calculation>
|
||||
| '(' {<scalar> ','} ')' ('=' | '+=' | '-=' | '*=' | '/=' | '~=') (<calculation> | '(' {<calculation> ','} ')')
|
||||
;
|
||||
<loop_expr> =
|
||||
<for_loop>
|
||||
| <while_loop>
|
||||
| <forindex_loop>
|
||||
| <foreach_loop>
|
||||
;
|
||||
<for_loop> =
|
||||
<for> '(' [<statement>] ';' [<calculation>] ';' [<statement>] ')' <statement> [';']
|
||||
| <for> '(' [<statement>] ';' [<calculation>] ';' [<statement>] ')' '{' {<statement> ';'} '}'
|
||||
;
|
||||
<while_loop> =
|
||||
<while> '(' <calculation> ')' <statement> [';']
|
||||
| <while> '(' <calculation> ')' '{' {<statement> ';'} '}'
|
||||
;
|
||||
(* in forindex and foreach the scalar and definition cannot be lacked*)
|
||||
<forindex_loop> =
|
||||
<forindex> '(' (<var> <id>)|(<id>) ';' <scalar> ')' <statement> [';']
|
||||
| <forindex> '(' (<var> <id>)|(<id>) ';' <scalar> ')' '{' {<statement> ';'} '}'
|
||||
;
|
||||
<foreach_loop> =
|
||||
<foreach> '(' (<var> <id>)|(<id>) ';' <scalar> ')' <statement> [';']
|
||||
| <foreach> '(' (<var> <id>)|(<id>) ';' <scalar> ')' '{' {<statement> ';'} '}'
|
||||
;
|
||||
|
||||
<conditional_expr> = <conditional_expr_if> {<conditional_expr_elsif>} [<conditional_expr_else>]
|
||||
;
|
||||
<conditional_expr_if> =
|
||||
<if> '(' <calculation> ')' <statement> [';']
|
||||
| <if> '(' <calculation> ')' '{' {<statement> ';'} '}'
|
||||
;
|
||||
<conditional_expr_elsif> =
|
||||
<elsif> '(' <calculation> ')' <statement> [';']
|
||||
| <elsif> '(' <calculation> ')' '{' {<statement> ';'} '}'
|
||||
| <else> <if> '(' <calculation> ')' <statement> [';']
|
||||
| <else> <if> '(' <calculation> ')' '{' {<statement> ';'} '}'
|
||||
;
|
||||
<conditional_expr_else> =
|
||||
<else> <statement> [';']
|
||||
| <else> '{' {<statement> ';'} '}'
|
||||
;
|
||||
|
||||
<continue_expr> = <continue> ;
|
||||
<break_expr> = <break> ;
|
||||
<return_expr> = <return> [<calculation>] ;
|
||||
<statement> =
|
||||
<definition>
|
||||
| <assignment>
|
||||
| <conditional_expr>
|
||||
| <loop_expr>
|
||||
| <continue_expr>
|
||||
| <break_expr>
|
||||
| <return_expr>
|
||||
;
|
|
@ -1,56 +0,0 @@
|
|||
var a=1;
|
||||
var f=func
|
||||
{
|
||||
var a=4;
|
||||
return func{return a;}
|
||||
}
|
||||
var b=f();
|
||||
print(b());
|
||||
# output 4
|
||||
|
||||
var h=func
|
||||
{
|
||||
var a=4;
|
||||
var k=func{return a;};
|
||||
a=0;
|
||||
return k;
|
||||
}
|
||||
b=h();
|
||||
print(b());
|
||||
# output 0
|
||||
|
||||
var c=0;
|
||||
var f2=func
|
||||
{
|
||||
var a=4;
|
||||
var k=func{return a;};
|
||||
a=0;
|
||||
c=func{a=2;};
|
||||
return k;
|
||||
}
|
||||
b=f2();
|
||||
print(b());
|
||||
# output 0
|
||||
c();
|
||||
print(b());
|
||||
# output 2
|
||||
|
||||
var cl_fun=func(x)
|
||||
{
|
||||
var a=x;
|
||||
return func{return a;};
|
||||
}
|
||||
b=cl_fun(1);
|
||||
c=cl_fun(10);
|
||||
print(b());
|
||||
# output 1
|
||||
|
||||
a=3;
|
||||
b=0;
|
||||
if(a==3)
|
||||
{
|
||||
var c=10;
|
||||
b=func{return c;};
|
||||
}
|
||||
print(b());
|
||||
# output 10
|
|
@ -1,8 +0,0 @@
|
|||
var f=func(x)
|
||||
{
|
||||
if(x>9)return;
|
||||
x+=1;
|
||||
f(x);
|
||||
return;
|
||||
}
|
||||
f(0);
|
|
@ -1,4 +0,0 @@
|
|||
var hash={
|
||||
str:1,
|
||||
f:func{print(me.str);}
|
||||
};
|
|
@ -1,29 +0,0 @@
|
|||
|
||||
var condition_true=1;
|
||||
var condition_false=0;
|
||||
if(condition_true)
|
||||
{
|
||||
var a=1;
|
||||
}
|
||||
else if(!condition_false)
|
||||
{
|
||||
var b=1;
|
||||
}
|
||||
elsif(!condition_true and condition_false)
|
||||
{
|
||||
print("impossible");
|
||||
}
|
||||
else
|
||||
{
|
||||
var c=1;
|
||||
var d=1;
|
||||
}
|
||||
|
||||
if(condition_true)
|
||||
var a=1;
|
||||
else if(!condition_false)
|
||||
var b=1;
|
||||
elsif(!condition_true and condition_false)
|
||||
print("impossible");
|
||||
else
|
||||
var c=1;
|
|
@ -1,210 +0,0 @@
|
|||
var smartScreen = canvas.new({
|
||||
"name": "smartScreen", # The name is optional but allow for easier identification
|
||||
"size": [2048, 2048], # Size of the underlying texture (should be a power of 2, required) [Resolution]
|
||||
"view": [768, 768], # Virtual resolution (Defines the coordinate system of the canvas [Dimensions]
|
||||
# which will be stretched the size of the texture, required)
|
||||
"mipmapping": 1 # Enable mipmapping (optional)
|
||||
});
|
||||
|
||||
smartScreen.addPlacement({"node": "screen", "texture": "screen.jpeg"});
|
||||
var group = smartScreen.createGroup();
|
||||
|
||||
# Create a text element and set some values
|
||||
var text = group.createChild("text", "optional-id-for element")
|
||||
.setTranslation(10, 20) # The origin is in the top left corner
|
||||
.setAlignment("left-center") # All values from osgText are supported (see $FG_ROOT/Docs/README.osgtext)
|
||||
.setFont("LiberationFonts/LiberationSans-Regular.ttf") # Fonts are loaded either from $AIRCRAFT_DIR/Fonts or $FG_ROOT/Fonts
|
||||
.setFontSize(14, 1.2) # Set fontsize and optionally character aspect ratio
|
||||
.setColor(1,0,0) # Text color
|
||||
.setText("This is a text element");
|
||||
text.hide();
|
||||
text.setText("SELF TEST NORMAL").show();
|
||||
|
||||
|
||||
|
||||
var ui_root = smartScreen.createGroup();
|
||||
var vbox = canvas.VBoxLayout.new();
|
||||
smartScreen.setLayout(vbox);
|
||||
|
||||
|
||||
var button_onl = canvas.gui.widgets.Button.new(ui_root, canvas.style, {}).setText("Online OSM").listen("clicked", func showOnlineMap());
|
||||
var button_offl = canvas.gui.widgets.Button.new(ui_root, canvas.style, {}).setText("Offline OSM").listen("clicked", func showOfflineMap());
|
||||
button_onl.setSizeHint([32, 128]);
|
||||
button_offl.setSizeHint([32, 128]);
|
||||
|
||||
var label = canvas.gui.widgets.Label.new(ui_root, canvas.style, {});
|
||||
|
||||
var button_box = canvas.HBoxLayout.new();
|
||||
button_box.addItem(button_onl);
|
||||
button_box.addItem(button_offl);
|
||||
button_box.addItem(label);
|
||||
button_box.addStretch(1);
|
||||
|
||||
vbox.addItem(button_box);
|
||||
vbox.addStretch(1);
|
||||
|
||||
|
||||
var showOnlineMap = func(){
|
||||
TestMap.show();
|
||||
g.hide();
|
||||
label.setText("Online Mode");
|
||||
}
|
||||
|
||||
|
||||
var showOfflineMap = func(){
|
||||
TestMap.hide();
|
||||
g.show();
|
||||
label.setText("Offline Mode");
|
||||
}
|
||||
|
||||
|
||||
# Online Map using MapStructure
|
||||
var TestMap = smartScreen.createGroup().createChild("map");
|
||||
TestMap.setTranslation(smartScreen.get("view[0]")/2,smartScreen.get("view[1]")/2);
|
||||
|
||||
|
||||
var ctrl_ns = canvas.Map.Controller.get("Aircraft position");
|
||||
var source = ctrl_ns.SOURCES["map-dialog"];
|
||||
if (source == nil) {
|
||||
# TODO: amend
|
||||
var source = ctrl_ns.SOURCES["map-dialog"] = {
|
||||
getPosition: func subvec(geo.aircraft_position().latlon(), 0, 2),# ? ? ?
|
||||
getAltitude: func getprop('/position/altitude-ft'),
|
||||
getHeading: func {
|
||||
if (me.aircraft_heading)
|
||||
getprop('/orientation/heading-deg');
|
||||
else
|
||||
0;
|
||||
},
|
||||
aircraft_heading: 1,
|
||||
};
|
||||
}
|
||||
setlistener("/sim/gui/dialogs/map-canvas/aircraft-heading-up", func(n){source.aircraft_heading = n.getBoolValue();}, 1);
|
||||
TestMap.setController("Aircraft position", "map-dialog");
|
||||
TestMap.setRange(1);
|
||||
|
||||
var r = func(name,vis=1,zindex=nil){return caller(0)[0];};
|
||||
# TODO: we'll need some z-indexing here, right now it's just random
|
||||
|
||||
foreach(var type; [r('APS')] ){
|
||||
TestMap.addLayer(factory: canvas.SymbolLayer, type_arg: type.name, visible: type.vis, priority: 2);
|
||||
}
|
||||
|
||||
foreach(var type; [ r('OSM')]) {
|
||||
TestMap.addLayer(factory: canvas.OverlayLayer,
|
||||
type_arg: type.name,
|
||||
visible: type.vis,
|
||||
priority: 1);
|
||||
}
|
||||
|
||||
|
||||
TestMap.hide();
|
||||
|
||||
# Offline map
|
||||
|
||||
var g = smartScreen.createGroup();
|
||||
var zoom = 15;
|
||||
var type = "intl";
|
||||
var tile_size = 256;
|
||||
|
||||
|
||||
var changeZoom = func(d)
|
||||
{
|
||||
zoom = math.max(2, math.min(19, zoom + d));
|
||||
updateTiles();
|
||||
}
|
||||
|
||||
# http://polymaps.org/docs/
|
||||
# https://github.com/simplegeo/polymaps
|
||||
# https://github.com/Leaflet/Leaflet
|
||||
|
||||
var maps_base = getprop("/sim/fg-home") ~ '/cache/maps';
|
||||
|
||||
var makePath =
|
||||
string.compileTemplate(maps_base ~ '/osm-{type}/{z}/{x}/{y}.jpg');
|
||||
var num_tiles = [4, 4];
|
||||
|
||||
var center_tile_offset = [(num_tiles[0]-1)/2, (num_tiles[1]-1)/ 2];
|
||||
|
||||
# simple aircraft icon at current position/center of the map
|
||||
g.createChild("path")
|
||||
.moveTo( tile_size*center_tile_offset[0]-10, tile_size*center_tile_offset[1])
|
||||
.horiz(20)
|
||||
.move(-10,-10)
|
||||
.vert(20)
|
||||
.set("stroke", "red")
|
||||
.set("stroke-width", 2)
|
||||
.set("z-index", 1);
|
||||
|
||||
# initialize the map by setting up
|
||||
# a grid of raster images
|
||||
|
||||
var tiles = setsize([], num_tiles[0]);
|
||||
for(var x=0; x<num_tiles[0]; x+=1)
|
||||
{
|
||||
tiles[x] = setsize([], num_tiles[1]);
|
||||
for(var y=0; y<num_tiles[1]; y+=1)
|
||||
tiles[x][y] = g.createChild("image", "map-tile");
|
||||
}
|
||||
|
||||
var last_tile = [-1,-1];
|
||||
var last_type = type;
|
||||
|
||||
# this is the callback that will be regularly called by the timer
|
||||
# to update the map
|
||||
var updateTiles = func()
|
||||
{
|
||||
# get current position
|
||||
var lat = getprop('/position/latitude-deg');
|
||||
var lon = getprop('/position/longitude-deg');
|
||||
|
||||
var n = math.pow(2, zoom);
|
||||
var offset = [n*((lon+180)/360)-center_tile_offset[0], (1-math.ln(math.tan(lat*math.pi/180)+1/math.cos(lat*math.pi/180))/math.pi)/2*n-center_tile_offset[1]];
|
||||
var tile_index = [int(offset[0]), int(offset[1])];
|
||||
|
||||
var ox = tile_index[0] - offset[0];
|
||||
var oy = tile_index[1] - offset[1];
|
||||
|
||||
for(var x = 0; x < num_tiles[0]; x += 1)
|
||||
for(var y = 0; y < num_tiles[1]; y += 1)
|
||||
tiles[x][y].setTranslation(int((ox + x) * tile_size + 0.5), int((oy + y) * tile_size + 0.5));
|
||||
|
||||
if( tile_index[0] != last_tile[0]
|
||||
or tile_index[1] != last_tile[1]
|
||||
or type != last_type )
|
||||
{
|
||||
for(var x = 0; x < num_tiles[0]; x += 1)
|
||||
for(var y = 0; y < num_tiles[1]; y += 1)
|
||||
{
|
||||
var pos = {
|
||||
z: zoom,
|
||||
x: int(offset[0] + x),
|
||||
y: int(offset[1] + y),
|
||||
type: type
|
||||
};
|
||||
|
||||
(func {
|
||||
var img_path = makePath(pos);
|
||||
var tile = tiles[x][y];
|
||||
print('loading ' ~ img_path);
|
||||
tile.set("src", img_path);
|
||||
})();
|
||||
# lambda
|
||||
}
|
||||
|
||||
last_tile = tile_index;
|
||||
last_type = type;
|
||||
}
|
||||
};
|
||||
|
||||
# set up a timer that will invoke updateTiles at 2-second intervals
|
||||
var update_timer = maketimer(2, updateTiles);
|
||||
# actually start the timer
|
||||
update_timer.start();
|
||||
|
||||
# set up default zoom level
|
||||
changeZoom(0);
|
||||
|
||||
#g.hide();
|
||||
|
||||
|
|
@ -1,643 +0,0 @@
|
|||
###############################################################################
|
||||
##
|
||||
## Nasal module for dual control over the multiplayer network.
|
||||
##
|
||||
## Copyright (C) 2007 - 2010 Anders Gidenstam (anders(at)gidenstam.org)
|
||||
## This file is licensed under the GPL license version 2 or later.
|
||||
##
|
||||
###############################################################################
|
||||
## MP properties
|
||||
var lat_mpp = "position/latitude-deg";
|
||||
var lon_mpp = "position/longitude-deg";
|
||||
var alt_mpp = "position/altitude-ft";
|
||||
var heading_mpp = "orientation/true-heading-deg";
|
||||
var pitch_mpp = "orientation/pitch-deg";
|
||||
var roll_mpp = "orientation/roll-deg";
|
||||
|
||||
# Import components from the mp_broadcast module.
|
||||
var Binary = mp_broadcast.Binary;
|
||||
var MessageChannel = mp_broadcast.MessageChannel;
|
||||
|
||||
###############################################################################
|
||||
# Utility classes
|
||||
|
||||
############################################################
|
||||
# Translate a property into another.
|
||||
# Factor and offsets are only used for numeric values.
|
||||
# src - source : property node
|
||||
# dest - destination : property node
|
||||
# factor - : double
|
||||
# offset - : double
|
||||
var Translator = {};
|
||||
Translator.new = func (src = nil, dest = nil, factor = 1, offset = 0) {
|
||||
var obj = { parents : [Translator],
|
||||
src : src,
|
||||
dest : dest,
|
||||
factor : factor,
|
||||
offset : offset };
|
||||
if (obj.src == nil or obj.dest == nil) {
|
||||
print("Translator[");
|
||||
print(" ", debug.string(obj.src));
|
||||
print(" ", debug.string(obj.dest));
|
||||
print("]");
|
||||
fail();
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
Translator.update = func () {
|
||||
var v = me.src.getValue();
|
||||
if (is_num(v)) {
|
||||
me.dest.setValue(me.factor * v + me.offset);
|
||||
} else {
|
||||
if (typeof(v) == "scalar")
|
||||
me.dest.setValue(v);
|
||||
}
|
||||
}
|
||||
|
||||
############################################################
|
||||
# Detects flanks on two insignals encoded in a property.
|
||||
# - positive signal up/down flank
|
||||
# - negative signal up/down flank
|
||||
# n - source : property node
|
||||
# on_positive_flank - action : func (v)
|
||||
# on_negative_flank - action : func (v)
|
||||
var EdgeTrigger = {};
|
||||
EdgeTrigger.new = func (n, on_positive_flank, on_negative_flank) {
|
||||
var obj = { parents : [EdgeTrigger],
|
||||
old : 0,
|
||||
node : n,
|
||||
pos_flank : on_positive_flank,
|
||||
neg_flank : on_negative_flank };
|
||||
if (obj.node == nil) {
|
||||
print("EdgeTrigger[");
|
||||
print(" ", debug.string(obj.node));
|
||||
print("]");
|
||||
fail();
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
EdgeTrigger.update = func {
|
||||
# NOTE: float MP properties get interpolated.
|
||||
# This detector relies on that steady state is reached between
|
||||
# flanks.
|
||||
var val = me.node.getValue();
|
||||
if (!is_num(val)) return;
|
||||
if (me.old == 1) {
|
||||
if (val < me.old) {
|
||||
me.pos_flank(0);
|
||||
}
|
||||
} elsif (me.old == 0) {
|
||||
if (val > me.old) {
|
||||
me.pos_flank(1);
|
||||
} elsif (val < me.old) {
|
||||
me.neg_flank(1);
|
||||
}
|
||||
} elsif (me.old == -1) {
|
||||
if (val > me.old) {
|
||||
me.neg_flank(0);
|
||||
}
|
||||
}
|
||||
me.old = val;
|
||||
}
|
||||
|
||||
############################################################
|
||||
# StableTrigger: Triggers an action when a MPP property
|
||||
# becomes stable (i.e. doesn't change for
|
||||
# MIN_STABLE seconds).
|
||||
# src - MP prop : property node
|
||||
# action - action to take when the value becomes stable : [func(v)]
|
||||
# An action is triggered when value has stabilized.
|
||||
var StableTrigger = {};
|
||||
StableTrigger.new = func (src, action) {
|
||||
var obj = { parents : [StableTrigger],
|
||||
src : src,
|
||||
action : action,
|
||||
old : 0,
|
||||
stable_since : 0,
|
||||
wait : 0,
|
||||
MIN_STABLE : 0.01 };
|
||||
# Error checking.
|
||||
var bad = (obj.src == nil) or (action = nil);
|
||||
|
||||
if (bad) {
|
||||
print("StableTrigger[");
|
||||
print(" ", debug.string(obj.src));
|
||||
print(" ", debug.string(obj.action));
|
||||
print("]");
|
||||
fail();
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
StableTrigger.update = func () {
|
||||
var v = me.src.getValue();
|
||||
if (!is_num(v)) return;
|
||||
var t = getprop("/sim/time/elapsed-sec"); # NOTE: simulated time.
|
||||
|
||||
if ((me.old == v) and
|
||||
((t - me.stable_since) > me.MIN_STABLE) and (me.wait == 1)) {
|
||||
# Trigger action.
|
||||
me.action(v);
|
||||
|
||||
me.wait = 0;
|
||||
} elsif (me.old == v) {
|
||||
# Wait. This is either before the signal is stable or after the action.
|
||||
} else {
|
||||
me.stable_since = t;
|
||||
me.wait = 1;
|
||||
me.old = me.src.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
############################################################
|
||||
# Selects the most recent value of two properties.
|
||||
# src1 - : property node
|
||||
# src2 - : property node
|
||||
# dest - : property node
|
||||
# threshold - : double
|
||||
var MostRecentSelector = {};
|
||||
MostRecentSelector.new = func (src1, src2, dest, threshold) {
|
||||
var obj = { parents : [MostRecentSelector],
|
||||
old1 : 0,
|
||||
old2 : 0,
|
||||
src1 : src1,
|
||||
src2 : src2,
|
||||
dest : dest,
|
||||
thres : threshold };
|
||||
if (obj.src1 == nil or obj.src2 == nil or obj.dest == nil) {
|
||||
print("MostRecentSelector[");
|
||||
print(" ", debug.string(obj.src1));
|
||||
print(" ", debug.string(obj.src2));
|
||||
print(" ", debug.string(obj.dest));
|
||||
print("]");
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
MostRecentSelector.update = func {
|
||||
var v1 = me.src1.getValue();
|
||||
var v2 = me.src2.getValue();
|
||||
if (!is_num(v1) and !is_num(v2)) return;
|
||||
elsif (!is_num(v1)) me.dest.setValue(v2);
|
||||
elsif (!is_num(v2)) me.dest.setValue(v1);
|
||||
else {
|
||||
if (abs (v2 - me.old2) > me.thres) {
|
||||
me.old2 = v2;
|
||||
me.dest.setValue(me.old2);
|
||||
}
|
||||
if (abs (v1 - me.old1) > me.thres) {
|
||||
me.old1 = v1;
|
||||
me.dest.setValue(me.old1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
############################################################
|
||||
# Adds two input properties.
|
||||
# src1 - : property node
|
||||
# src2 - : property node
|
||||
# dest - : property node
|
||||
var Adder = {};
|
||||
Adder.new = func (src1, src2, dest) {
|
||||
var obj = { parents : [DeltaAccumulator],
|
||||
src1 : src1,
|
||||
src2 : src2,
|
||||
dest : dest };
|
||||
if (obj.src1 == nil or obj.src2 == nil or obj.dest == nil) {
|
||||
print("Adder[");
|
||||
print(" ", debug.string(obj.src1));
|
||||
print(" ", debug.string(obj.src2));
|
||||
print(" ", debug.string(obj.dest));
|
||||
print("]");
|
||||
fail();
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
Adder.update = func () {
|
||||
var v1 = me.src1.getValue();
|
||||
var v2 = me.src2.getValue();
|
||||
if (!is_num(v1) or !is_num(v2)) return;
|
||||
me.dest.setValue(v1 + v2);
|
||||
}
|
||||
|
||||
############################################################
|
||||
# Adds the delta of src to dest.
|
||||
# src - : property node
|
||||
# dest - : property node
|
||||
var DeltaAdder = {};
|
||||
DeltaAdder.new = func (src, dest) {
|
||||
var obj = { parents : [DeltaAdder],
|
||||
old : 0,
|
||||
src : src,
|
||||
dest : dest };
|
||||
if (obj.src == nil or obj.dest == nil) {
|
||||
print("DeltaAdder[", debug.string(obj.src), ", ",
|
||||
debug.string(obj.dest), "]");
|
||||
fail();
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
DeltaAdder.update = func () {
|
||||
var v = me.src.getValue();
|
||||
if (!is_num(v)) return;
|
||||
me.dest.setValue((v - me.old) + me.dest.getValue());
|
||||
me.old = v;
|
||||
}
|
||||
|
||||
############################################################
|
||||
# Switch encoder: Encodes upto 32 boolean properties in one
|
||||
# int property.
|
||||
# inputs - list of property nodes
|
||||
# dest - where the bitmask is stored : property node
|
||||
var SwitchEncoder = {};
|
||||
SwitchEncoder.new = func (inputs, dest) {
|
||||
var obj = { parents : [SwitchEncoder],
|
||||
inputs : inputs,
|
||||
dest : dest };
|
||||
# Error checking.
|
||||
var bad = (obj.dest == nil);
|
||||
foreach (var i; inputs) {
|
||||
if (i == nil) { bad = 1; }
|
||||
}
|
||||
|
||||
if (bad) {
|
||||
print("SwitchEncoder[");
|
||||
foreach (var i; inputs) {
|
||||
print(" ", debug.string(i));
|
||||
}
|
||||
print(" ", debug.string(obj.dest));
|
||||
print("]");
|
||||
fail();
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
SwitchEncoder.update = func () {
|
||||
var v = 0;
|
||||
var b = 1;
|
||||
forindex (var i; me.inputs) {
|
||||
if (me.inputs[i].getBoolValue()) {
|
||||
v = v + b;
|
||||
}
|
||||
b *= 2;
|
||||
}
|
||||
me.dest.setIntValue(v);
|
||||
}
|
||||
|
||||
############################################################
|
||||
# Switch decoder: Decodes a bitmask in an int property.
|
||||
# src - : property node
|
||||
# actions - list of actions : [func(b)]
|
||||
# Actions are triggered when their input bit change.
|
||||
# Due to interpolation the decoder needs to wait for a
|
||||
# stable input value.
|
||||
var SwitchDecoder = {};
|
||||
SwitchDecoder.new = func (src, actions) {
|
||||
var obj = { parents : [SwitchDecoder],
|
||||
wait : 0,
|
||||
old : 0,
|
||||
old_stable : 0,
|
||||
stable_since : 0,
|
||||
reset : 1,
|
||||
src : src,
|
||||
actions : actions,
|
||||
MIN_STABLE : 0.1 };
|
||||
# Error checking.
|
||||
var bad = (obj.src == nil);
|
||||
foreach (var a; obj.actions) {
|
||||
if (a == nil) { bad = 1; }
|
||||
}
|
||||
|
||||
if (bad) {
|
||||
print("SwitchDecoder[");
|
||||
print(" ", debug.string(obj.src));
|
||||
foreach (var a; obj.actions) {
|
||||
print(" ", debug.string(a));
|
||||
}
|
||||
print("]");
|
||||
fail();
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
SwitchDecoder.update = func () {
|
||||
var t = getprop("/sim/time/elapsed-sec"); # NOTE: simulated time.
|
||||
var v = me.src.getValue();
|
||||
if (!is_num(v)) return;
|
||||
|
||||
if ((me.old == v) and ((t - me.stable_since) > me.MIN_STABLE) and
|
||||
(me.wait == 1)) {
|
||||
var ov = me.old_stable;
|
||||
# Use this to improve.
|
||||
#<cptf> here's the boring version: var bittest = func(u, b) { while (b) { u = int(u / 2); b -= 1; } u != int(u / 2) * 2; }
|
||||
forindex (var i; me.actions) {
|
||||
var m = math.mod(v, 2);
|
||||
var om = math.mod(ov, 2);
|
||||
if ((m != om or me.reset)) { me.actions[i](m?1:0); }
|
||||
v = (v - m)/2;
|
||||
ov = (ov - om)/2;
|
||||
}
|
||||
me.old_stable = me.src.getValue();
|
||||
me.wait = 0;
|
||||
me.reset = 0;
|
||||
} elsif (me.old == v) {
|
||||
# Wait. This is either before the bitmask is stable or after
|
||||
# it has been processed.
|
||||
} else {
|
||||
me.stable_since = t;
|
||||
me.wait = 1;
|
||||
me.old = me.src.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
############################################################
|
||||
# Time division multiplexing encoder: Transmits a list of
|
||||
# properties over a MP enabled string property.
|
||||
# inputs - input properties : [property node]
|
||||
# dest - MP string prop : property node
|
||||
# Note: TDM can have high latency so it is best used for
|
||||
# non-time critical properties.
|
||||
var TDMEncoder = {};
|
||||
TDMEncoder.new = func (inputs, dest) {
|
||||
var obj = { parents : [TDMEncoder],
|
||||
inputs : inputs,
|
||||
channel : MessageChannel.new(dest,
|
||||
func (msg) {
|
||||
print("This should not happen!");
|
||||
}),
|
||||
MIN_INT : 0.25,
|
||||
last_time : 0,
|
||||
next_item : 0,
|
||||
old : [] };
|
||||
# Error checking.
|
||||
var bad = (dest == nil) or (obj.channel == nil);
|
||||
foreach (var i; inputs) {
|
||||
if (i == nil) { bad = 1; }
|
||||
}
|
||||
|
||||
if (bad) {
|
||||
print("TDMEncoder[");
|
||||
foreach (var i; inputs) {
|
||||
print(" ", debug.string(i));
|
||||
}
|
||||
print(" ", debug.string(dest));
|
||||
print("]");
|
||||
}
|
||||
|
||||
setsize(obj.old, size(obj.inputs));
|
||||
|
||||
return obj;
|
||||
}
|
||||
TDMEncoder.update = func () {
|
||||
var t = getprop("/sim/time/elapsed-sec"); # NOTE: simulated time.
|
||||
if (t > me.last_time + me.MIN_INT) {
|
||||
var n = size(me.inputs);
|
||||
while (1) {
|
||||
var v = me.inputs[me.next_item].getValue();
|
||||
|
||||
if ((n <= 0) or (me.old[me.next_item] != v)) {
|
||||
# Set the MP properties to send the next item.
|
||||
me.channel.send(Binary.encodeByte(me.next_item) ~
|
||||
Binary.encodeDouble(v));
|
||||
|
||||
me.old[me.next_item] = v;
|
||||
|
||||
me.last_time = t;
|
||||
me.next_item += 1;
|
||||
if (me.next_item >= size(me.inputs)) { me.next_item = 0; }
|
||||
return;
|
||||
} else {
|
||||
# Search for changed property.
|
||||
n -= 1;
|
||||
me.next_item += 1;
|
||||
if (me.next_item >= size(me.inputs)) { me.next_item = 0; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
############################################################
|
||||
# Time division multiplexing decoder: Receives a list of
|
||||
# properties over a MP enabled string property.
|
||||
# src - MP string prop : property node
|
||||
# actions - list of actions : [func(v)]
|
||||
# An action is triggered when its value is received.
|
||||
# Note: TDM can have high latency so it is best used for
|
||||
# non-time critical properties.
|
||||
var TDMDecoder = {};
|
||||
TDMDecoder.new = func (src, actions) {
|
||||
var obj = { parents : [TDMDecoder],
|
||||
actions : actions };
|
||||
obj.channel = MessageChannel.new(src,
|
||||
func (msg) {
|
||||
obj.process(msg);
|
||||
});
|
||||
|
||||
# Error checking.
|
||||
var bad = (src == nil) or (obj.channel == nil);
|
||||
foreach (var a; actions) {
|
||||
if (a == nil) { bad = 1; }
|
||||
}
|
||||
|
||||
if (bad) {
|
||||
print("TDMDecoder[");
|
||||
print(" ", debug.string(src));
|
||||
foreach (var a; actions) {
|
||||
print(" ", debug.string(a));
|
||||
}
|
||||
print("]");
|
||||
fail();
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
TDMDecoder.process = func (msg) {
|
||||
var v1 = Binary.decodeByte(msg);
|
||||
var v2 = Binary.decodeDouble(substr(msg, 1));
|
||||
# Trigger action.
|
||||
me.actions[v1](v2);
|
||||
}
|
||||
TDMDecoder.update = func {
|
||||
me.channel.update();
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Internal utility functions
|
||||
|
||||
var is_num = func (v) {
|
||||
return num(v) != nil;
|
||||
}
|
||||
|
||||
# fail causes a Nasal runtime error so we get a backtrace.
|
||||
var fail = func {
|
||||
error_detected_in_calling_context();
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
|
||||
###############################################################################
|
||||
# Copilot selection dialog.
|
||||
#
|
||||
# Usage: dual_control_tools.copilot_dialog.show(<copilot type string>);
|
||||
#
|
||||
var COPILOT_DLG = 0;
|
||||
var copilot_dialog = {};
|
||||
############################################################
|
||||
copilot_dialog.init = func (copilot_type, x = nil, y = nil) {
|
||||
me.x = x;
|
||||
me.y = y;
|
||||
me.bg = [0, 0, 0, 0.3]; # background color
|
||||
me.fg = [[1.0, 1.0, 1.0, 1.0]];
|
||||
#
|
||||
# "private"
|
||||
if (contains(aircraft_dual_control, "copilot_view")) {
|
||||
me.title = "Pilot selection";
|
||||
} else {
|
||||
me.title = "Copilot selection";
|
||||
}
|
||||
me.basenode = props.globals.getNode("sim/remote", 1);
|
||||
me.dialog = nil;
|
||||
me.namenode = props.Node.new({"dialog-name" : me.title });
|
||||
me.listeners = [];
|
||||
me.copilot_type = copilot_type;
|
||||
}
|
||||
############################################################
|
||||
copilot_dialog.create = func {
|
||||
if (me.dialog != nil)
|
||||
me.close();
|
||||
|
||||
me.dialog = gui.Widget.new();
|
||||
me.dialog.set("name", me.title);
|
||||
if (me.x != nil)
|
||||
me.dialog.set("x", me.x);
|
||||
if (me.y != nil)
|
||||
me.dialog.set("y", me.y);
|
||||
|
||||
me.dialog.set("layout", "vbox");
|
||||
me.dialog.set("default-padding", 0);
|
||||
var titlebar = me.dialog.addChild("group");
|
||||
titlebar.set("layout", "hbox");
|
||||
titlebar.addChild("empty").set("stretch", 1);
|
||||
if (contains(aircraft_dual_control, "copilot_view")) {
|
||||
titlebar.addChild("text").set("label", "Book your flight");
|
||||
} else {
|
||||
titlebar.addChild("text").set("label", "Passengers online");
|
||||
}
|
||||
var w = titlebar.addChild("button");
|
||||
w.set("pref-width", 16);
|
||||
w.set("pref-height", 16);
|
||||
w.set("legend", "");
|
||||
w.set("default", 0);
|
||||
w.set("key", "esc");
|
||||
w.setBinding("nasal", "dual_control_tools.copilot_dialog.destroy(); ");
|
||||
w.setBinding("dialog-close");
|
||||
me.dialog.addChild("hrule");
|
||||
|
||||
var content = me.dialog.addChild("group");
|
||||
content.set("layout", "vbox");
|
||||
content.set("halign", "center");
|
||||
content.set("default-padding", 5);
|
||||
|
||||
# Generate the dialog contents.
|
||||
me.players = me.find_copilot_players();
|
||||
var i = 0;
|
||||
var tmpbase = me.basenode.getNode("dialog", 1);
|
||||
var selected = me.basenode.getNode("pilot-callsign").getValue();
|
||||
foreach (var p; me.players) {
|
||||
var tmp = tmpbase.getNode("b[" ~ i ~ "]", 1);
|
||||
tmp.setBoolValue(streq(selected, p));
|
||||
var w = content.addChild("checkbox");
|
||||
w.node.setValues({"label" : p,
|
||||
"halign" : "left",
|
||||
"property" : tmp.getPath()});
|
||||
w.setBinding
|
||||
("nasal",
|
||||
"dual_control_tools.copilot_dialog.select_action(" ~ i ~ ");");
|
||||
i = i + 1;
|
||||
}
|
||||
me.dialog.addChild("hrule");
|
||||
|
||||
# Display the dialog.
|
||||
fgcommand("dialog-new", me.dialog.prop());
|
||||
fgcommand("dialog-show", me.namenode);
|
||||
}
|
||||
############################################################
|
||||
copilot_dialog.close = func {
|
||||
fgcommand("dialog-close", me.namenode);
|
||||
}
|
||||
############################################################
|
||||
copilot_dialog.destroy = func {
|
||||
COPILOT_DLG = 0;
|
||||
me.close();
|
||||
foreach(var l; me.listeners)
|
||||
removelistener(l);
|
||||
delete(gui.dialog, "\"" ~ me.title ~ "\"");
|
||||
}
|
||||
############################################################
|
||||
copilot_dialog.show = func (copilot_type) {
|
||||
# print("Showing MPCopilots dialog!");
|
||||
if (!COPILOT_DLG) {
|
||||
COPILOT_DLG = int(getprop("/sim/time/elapsed-sec"));
|
||||
me.init(copilot_type);
|
||||
me.create();
|
||||
me._update_(COPILOT_DLG);
|
||||
}
|
||||
}
|
||||
############################################################
|
||||
copilot_dialog._redraw_ = func {
|
||||
if (me.dialog != nil) {
|
||||
me.close();
|
||||
me.create();
|
||||
}
|
||||
}
|
||||
############################################################
|
||||
copilot_dialog._update_ = func (id) {
|
||||
if (COPILOT_DLG != id) return;
|
||||
me._redraw_();
|
||||
settimer(func { me._update_(id); }, 4.1);
|
||||
}
|
||||
############################################################
|
||||
copilot_dialog.select_action = func (n) {
|
||||
var selected = me.basenode.getNode("pilot-callsign").getValue();
|
||||
var bs = me.basenode.getNode("dialog").getChildren();
|
||||
# Assumption: There are two true b:s or none. The one not matching selected
|
||||
# is the new selection.
|
||||
var i = 0;
|
||||
me.basenode.getNode("pilot-callsign").setValue("");
|
||||
foreach (var b; bs) {
|
||||
if (!b.getValue() and (i == n)) {
|
||||
b.setValue(1);
|
||||
me.basenode.getNode("pilot-callsign").setValue(me.players[i]);
|
||||
} else {
|
||||
b.setValue(0);
|
||||
}
|
||||
i = i + 1;
|
||||
}
|
||||
dual_control.main.reset();
|
||||
me._redraw_();
|
||||
}
|
||||
############################################################
|
||||
# Return a list containing all nearby copilot players of the right type.
|
||||
copilot_dialog.find_copilot_players = func {
|
||||
var mpplayers =
|
||||
props.globals.getNode("ai/models").getChildren("multiplayer");
|
||||
|
||||
var res = [];
|
||||
foreach (var pilot; mpplayers) {
|
||||
if ((pilot.getNode("valid") != nil) and
|
||||
(pilot.getNode("valid").getValue()) and
|
||||
(pilot.getNode("sim/model/path") != nil)) {
|
||||
var type = pilot.getNode("sim/model/path").getValue();
|
||||
|
||||
if (type == me.copilot_type) {
|
||||
append(res, pilot.getNode("callsign").getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
# debug.dump(res);
|
||||
return res;
|
||||
}
|
||||
###############################################################################
|
|
@ -1,30 +0,0 @@
|
|||
for(;;)break;
|
||||
for(;;)
|
||||
{
|
||||
var a=1;
|
||||
break;
|
||||
}
|
||||
for(var i=1;;)break;
|
||||
for(var i=1;;i+=1)break;
|
||||
for(var i=1;i<10;i+=1)print(i);
|
||||
|
||||
while(1)break;
|
||||
var j=0;
|
||||
while(j<10)
|
||||
{
|
||||
print(j);
|
||||
j+=1;
|
||||
}
|
||||
|
||||
forindex(var j;[0,1,2,3])print(j);
|
||||
forindex(var j;[0,1,2,3])
|
||||
{
|
||||
var a=j;
|
||||
print(a*a);
|
||||
}
|
||||
foreach(var j;[0,1,2,3])print([0,1,2,3][j]);
|
||||
foreach(var j;[0,1,2,3])
|
||||
{
|
||||
var a=[0,1,2,3][j];
|
||||
print(a*a-1);
|
||||
}
|
|
@ -1,124 +0,0 @@
|
|||
# basic type
|
||||
nil;
|
||||
2147483647;
|
||||
0x7fffffff;
|
||||
0xdeadbeef;
|
||||
0o70120327;
|
||||
"hello world!";
|
||||
'hello world!';
|
||||
-12;
|
||||
!0;
|
||||
-((30));
|
||||
[];
|
||||
{};
|
||||
[0,1,2,3,4,5][2]; # 2
|
||||
([0,1,2,3,4])[2]; # 2
|
||||
(([0,1,2,3]))[2]; # 2
|
||||
[0,1,2,3,4,5][5,4,3,2+1][0:2][0]; # 5
|
||||
{str:"hello"}.str; # "hello"
|
||||
{str:"hello"}["str"]; # "hello"
|
||||
{"str":"hello\"\"\n"}["str"]; # "hello"
|
||||
20? 1:0;
|
||||
|
||||
# normal scalar
|
||||
var number_1=1;
|
||||
var number_2=0xdeadbeef;
|
||||
var number_3=0x13702;
|
||||
var number_4=0.12341490239423;
|
||||
var string_1="hello";
|
||||
var string_2='hello';
|
||||
var string_3=number_1? 'yes':'no'; # yes
|
||||
|
||||
# vector
|
||||
var vector_1=[];
|
||||
var vector_2=[0,1,2,"str",number_1,vector_1];
|
||||
var vector_3=vector_2[-3,-1];
|
||||
var vector_4=vector_2[0:3];
|
||||
var vector_5=vector_2[3:];
|
||||
|
||||
# hash
|
||||
var hash_1={};
|
||||
var hash_2={str1:'str1', str2:'str2', num1:0x7fffffff};
|
||||
var hash_3={
|
||||
"member_1":1,
|
||||
"member_2":2,
|
||||
"member_3":3,
|
||||
};
|
||||
var hash_4={
|
||||
mem_1:hash_1,
|
||||
mem_2:hash_2.num1, # also this can be written as hash_2["num1"]
|
||||
mem_3:hash_3["member_1"]
|
||||
};
|
||||
|
||||
# function
|
||||
var func_1=func(){return 1;}
|
||||
var prt=func(x){print(x);return nil;}
|
||||
var func_with_dynamic_id=func(a,b,c,d...){return [a,b,c,d];}
|
||||
var func_with_lack_para=func(a,b,c=1,d=2){return a+b+c+d;}
|
||||
var func_with_func_para=func(a,f){return f(a);}
|
||||
|
||||
func_with_lack_para(a:1, b:2, c:3, d:4);
|
||||
func_with_lack_para(b:1, c:3, a:4, d:1);
|
||||
func_with_func_para(f:func prt,a:1);
|
||||
func_with_func_para(func func_1(),func(x){return x;});
|
||||
func_with_func_para(func_1(),func_1);
|
||||
prt(func func_1());
|
||||
var test_func_ret_number_1=func func_1(); # 1
|
||||
var test_func_ret_number_2=func_1(); # 1
|
||||
|
||||
var source={
|
||||
member_1: func func_1(), # this will get a number
|
||||
member_2: func {return 2.71828;} # this will get a function
|
||||
};
|
||||
print(source['member_2']());
|
||||
print(source.member_2());
|
||||
|
||||
var test_func=func{return 1;}
|
||||
print(func test_func()); # 1
|
||||
print(test_func()); # 1
|
||||
print(func test_func); # nothing
|
||||
print(test_func); # nothing
|
||||
print(([0,1,2,3])[1]); # 1
|
||||
print(({str:"what?"})["str"]); # what?
|
||||
print(({str:"what?"}).str); # what?
|
||||
|
||||
# lambda
|
||||
(func(x){return x>0? x:0;})(12);
|
||||
(func{print("hello world");})();
|
||||
(((func(x){return 1.0/math.exp(x);})))(0);
|
||||
|
||||
# flexible definition & assignment
|
||||
var (r,g,b)=[0x00,0x10,0xff];
|
||||
(var r,g,b)=[0x00,0x10,0xff];
|
||||
var color=[0x00,0x10,0xff];
|
||||
var (r,g,b)=color;
|
||||
(var r,g,b)=color;
|
||||
(r,g,b)=(b,g,r);
|
||||
(number_1,number_2)=(number_2,number_1);
|
||||
var (swap_a,swap_b)=(0x1,0x80);
|
||||
(swap_a,swap_b)=(swap_b,swap_a);
|
||||
# ((swap_a),(swap_b))=(swap_b,swap_a) is wrong
|
||||
# anything that use multi_assignment must not have curve around them
|
||||
var multi_assign_1=[0,1,2,3,4];
|
||||
var multi_assign_2=[10,9,8,7];
|
||||
(multi_assign_1[1],multi_assign_2[0])=(multi_assign_1[2],multi_assign_2[1]);
|
||||
|
||||
# calculation
|
||||
1+1;
|
||||
1+1-2+3-4+5-6;
|
||||
1+1*8-9/3;
|
||||
1*-1;
|
||||
1*(1+2*(3+4*(5+6*(7+8*(9+10/(1+1))))));
|
||||
((-1*2+9))/7-1;
|
||||
((({num:2})))["num"]*2*2*2;
|
||||
((((([0,1,2])[0:2]))[0:2]))[1]-1;
|
||||
(((((((((((((((((((1+1+2+3+5)+8))+13)))+21))))+34)))))+55))))*89;
|
||||
number_1*(number_2+number_3)/90-number_4;
|
||||
(func test_func)()-1;
|
||||
hash_3.member_3+(func {return {what:"i don't tell you.",case_small:80,case_large:100}})["case_large"]/10;
|
||||
-1*10+5 or 10-10;
|
||||
nil and 1+7*8;
|
||||
(number_1 or number_2) and (number_3 or number_4-number_4*1);
|
||||
[0,1,4,3,2][4]*2-4+1*2*2*2*2*2/8;
|
||||
{num:0}.num or {what_is_the_secret_of_universe:42}["what_is_the_secret_of_universe"];
|
||||
"123"~"456"-123456*2/2;
|
|
@ -1,62 +0,0 @@
|
|||
var global_value=0;
|
||||
var global_hash=
|
||||
{
|
||||
var1:1,
|
||||
var2:2,
|
||||
var3:func(){return me.var2;}
|
||||
};
|
||||
print(global_value);
|
||||
print(global_hash.var3());
|
||||
|
||||
var func1=func()
|
||||
{
|
||||
global_value=1;
|
||||
print(global_value);
|
||||
var closure_value=1;
|
||||
var temp_value=1;
|
||||
print(temp_value);
|
||||
return func{return closure_value;};
|
||||
}
|
||||
|
||||
var func2=func()
|
||||
{
|
||||
for(var temp_value=0;temp_value<100;temp_value+=1)
|
||||
{
|
||||
if(temp_value<10)
|
||||
print(temp_value,"< 10");
|
||||
elsif(10<=temp_value and temp_value<50)
|
||||
print(temp_value,"< 50");
|
||||
temp_value=10;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var func3=func()
|
||||
{
|
||||
var fake_closure_value=1;
|
||||
return func()
|
||||
{
|
||||
var fake_closure_value=2;
|
||||
return fake_closure_value;
|
||||
};
|
||||
}
|
||||
|
||||
func1()();
|
||||
func2();
|
||||
func3()();
|
||||
|
||||
if(!global_value)
|
||||
{
|
||||
var temp_value=1;
|
||||
if(temp_value)
|
||||
{
|
||||
var temp_value=2;
|
||||
if(temp_value>=1)
|
||||
{
|
||||
var temp_value=3;
|
||||
print(temp_value);
|
||||
}
|
||||
print(temp_value);
|
||||
}
|
||||
print(temp_value);
|
||||
}
|
|
@ -1,179 +0,0 @@
|
|||
# nasal lib base.nas
|
||||
# 2020/2/4
|
||||
# this file is used to avoid name confliction
|
||||
# and is used to avoid name undefined
|
||||
# before running this file will be translated to abstract syntax tree
|
||||
# and this ast will be linked before main ast as main-ast's beginning
|
||||
|
||||
# print
|
||||
var print=func(elements...)
|
||||
{
|
||||
nasal_call_builtin_std_cout(elements);
|
||||
return nil;
|
||||
};
|
||||
|
||||
# append
|
||||
# The first argument specifies a vector.
|
||||
# Appends the remaining arguments to the end of the vector.
|
||||
var append=func(vector,elements...)
|
||||
{
|
||||
nasal_call_builtin_push_back(vector,elements);
|
||||
return nil;
|
||||
}
|
||||
|
||||
# setsize
|
||||
# Sets the size of a vector.
|
||||
# The first argument specifies a vector, the second a number representing the desired size of that vector.
|
||||
# If the vector is currently larger than the specified size,it is truncated.
|
||||
# If it is smaller, it is padded with nil entries.Returns the vector operated upon.
|
||||
var setsize=func(vector,size)
|
||||
{
|
||||
nasal_call_builtin_set_size(vector,size);
|
||||
return nil;
|
||||
}
|
||||
|
||||
# subvec
|
||||
# Returns a sub-range of a vector.
|
||||
# The first argument specifies a vector, the second a starting index,
|
||||
# and the optional third argument indicates a length (the default is to the end of the vector).
|
||||
var subvec=func(vector,start,length=nil)
|
||||
{
|
||||
return nasal_call_builtin_subvec(vector,start,length);
|
||||
}
|
||||
|
||||
# contains
|
||||
# The first argument specifies a hash, the second must be a scalar.
|
||||
# Returns 1 if the hash contains the scalar as a key, 0 if not.
|
||||
var contains=func(hash,key)
|
||||
{
|
||||
return nasal_call_builtin_contains(hash,key);
|
||||
}
|
||||
|
||||
# delete
|
||||
# The first argument specifies a hash, the second must be a scalar key.
|
||||
# Deletes the key from the hash if it exists.
|
||||
# Operationally, this is identical to setting the hash value specified by the key to nil,
|
||||
# but this variant potentially frees storage by deleting the reference to the key and by shrinking the hash.
|
||||
var delete=func(hash,key)
|
||||
{
|
||||
nasal_call_builtin_delete(hash,key);
|
||||
return;
|
||||
}
|
||||
|
||||
# int
|
||||
# Returns the integer part of the numeric value of the single argument, or nil if none exists.
|
||||
# Truncates towards zero, not negative infinity (i.e. it's implemented in C as a double tointeger typecast).
|
||||
var int=func(value)
|
||||
{
|
||||
return nasal_call_builtin_trans_int(value);
|
||||
}
|
||||
|
||||
# num
|
||||
# Returns the numeric value of the single argument, or nil if none exists.
|
||||
var num=func(value)
|
||||
{
|
||||
return nasal_call_builtin_trans_num(value);
|
||||
}
|
||||
|
||||
# keys
|
||||
# Returns a vector containing the list of keys found in the single hash argument.
|
||||
var keys=func(hash)
|
||||
{
|
||||
return nasal_call_builtin_get_keys(hash);
|
||||
}
|
||||
|
||||
# pop
|
||||
# Removes and returns the last element of the single vector argument.
|
||||
var pop=func(vector)
|
||||
{
|
||||
return nasal_call_builtin_pop_back(vector);
|
||||
}
|
||||
|
||||
# size
|
||||
# Returns the size of the single argument.
|
||||
# For strings, this is the length in bytes.
|
||||
# For vectors, this is the number of elements.
|
||||
# For hashes, it is the number of key/value pairs.
|
||||
# Returns nil for number and nil arguments.
|
||||
var size=func(object)
|
||||
{
|
||||
return nasal_call_builtin_sizeof(object);
|
||||
}
|
||||
|
||||
# streq
|
||||
# Tests the string values of the two arguments for equality.
|
||||
# Needed because the == operator in Nasal tests for numeric equality, as in perl.
|
||||
# So "0" == "0.0" is true,but streq("0", "0.0") is false.
|
||||
# This is rarely required in typical code.
|
||||
var streq=func(__a,__b)
|
||||
{
|
||||
return nasal_call_builtin_str_cmp_equal(__a,__b);
|
||||
}
|
||||
|
||||
# cmp
|
||||
# Compares two strings, returning -1 if a is less than b, 0 if theyare identical, and 1 if a is greater than b.
|
||||
var cmp=func(__a,__b)
|
||||
{
|
||||
return nasal_call_builtin_cmp(__a,__b);
|
||||
}
|
||||
|
||||
# sort
|
||||
# Creates a new vector containing the elements in the input vector sorted in ascending order according to the rule givenby function,
|
||||
# which takes two arguments (elements of the input vector) and should return less than zero, zero, or greater than zero if the first argument is,
|
||||
# respectively, less than, equal to, or greater than the second argument. Despite being implemented with ANSI C qsort(),
|
||||
# the sort is stable; "equal" elements in the output vector will appear in the same relative order as they do in the input.
|
||||
var sort=func(vector,function)
|
||||
{
|
||||
nasal_call_builtin_cpp_sort(vector,function);
|
||||
return;
|
||||
}
|
||||
|
||||
# substr
|
||||
# Computes a substring.
|
||||
# The first argument specifes a string, the second is an integer index of the start of a substring,
|
||||
# the optional third argument specifies a length (the default is to return the remaining string).
|
||||
# Example: substr("abcde", 1, 3) returns "bcd".
|
||||
var substr=func(__string,start,length=nil)
|
||||
{
|
||||
return nasal_call_builtin_substr(__string,start,length);
|
||||
}
|
||||
|
||||
# sprintf
|
||||
# Creates and returns a string formatted as per ANSI C sprintf().
|
||||
var sprintf=func(__format,var_args...)
|
||||
{
|
||||
return nasal_call_builtin_sprintf(__format,var_args);
|
||||
}
|
||||
|
||||
# find
|
||||
# Finds and returns the index of the first occurence of the string needle in the string haystack, or -1 if no such occurence was found.
|
||||
var find=func(needle,haystack)
|
||||
{
|
||||
return nasal_call_builtin_find_first_occur(needle,haystack);
|
||||
}
|
||||
|
||||
# split
|
||||
# Splits the input string into a vector of substrings bounded by occurences of the delimeter substring.
|
||||
var split=func(delimeter,__string)
|
||||
{
|
||||
return nasal_call_builtin_split(delimeter,__string);
|
||||
}
|
||||
|
||||
# rand
|
||||
# Returns a random number in the range [0:1) (that is, 0.0 is a possible return value. 1.0 is not).
|
||||
# If a numeric argument is specified, it is used as a seed instead and the function returns nil.
|
||||
# Implemented in terms of the C library's rand/srand functions;
|
||||
# the result should have a full double-precision number's worth of randomness even on systems with a 15 bit rand().
|
||||
var rand=func(seed=nil)
|
||||
{
|
||||
return nasal_call_builtin_rand(seed);
|
||||
}
|
||||
|
||||
# id
|
||||
# Returns a unique string identifying the object.
|
||||
# Two id strings are equal if and only if the two references point to the same object in memory.
|
||||
# Numbers don't have id's and will cause a runtime error if passed to id().
|
||||
var id=func(thing)
|
||||
{
|
||||
return nasal_call_builtin_get_id(thing);
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
# nasal lib bits.nas
|
||||
# 2020/2/8
|
||||
# this file is used to avoid name confliction
|
||||
# and is used to avoid name undefined
|
||||
# before running this file will be translated to abstract syntax tree
|
||||
# and this ast will be linked before main ast as main-ast's beginning
|
||||
|
||||
var bits=
|
||||
{
|
||||
# Interpreting the string str as bits,
|
||||
# returns the bitfield of the specified length starting at startbit.
|
||||
# Interprets the result as an unsigned integer.
|
||||
# The bit order is bytewise big endian: The 0th bit is the high bit of the first byte.
|
||||
# The last bit is the low bit of the last byte in the string.
|
||||
fld:func(__string,startbit,length)
|
||||
{
|
||||
return nasal_call_builtin_bitcalc(__string,startbit,length);
|
||||
},
|
||||
# As bits.fld(), but interprets the result as a 2's complement signed value.
|
||||
sfld:func(__string,startbit,length)
|
||||
{
|
||||
return nasal_call_builtin_sbitcalc(__string,startbit,length);
|
||||
},
|
||||
# Sets the specified value into the bit string at the specified position.
|
||||
# The string must be mutable: either the result of a runtime concatenation (the ~ operator) or a call to bits.buf()(see below).
|
||||
# Attempts to modify immutable strings (e.g. compile time constants) will produce a runtime error.
|
||||
setfld:func(__string,startbit,length,value)
|
||||
{
|
||||
return nasal_call_builtin_setbit(__string,startbit,length,value);
|
||||
},
|
||||
# Returns a zero-filled mutable string of the specified length.
|
||||
buf:func(length)
|
||||
{
|
||||
return nasal_call_builtin_null_string_gen(length);
|
||||
},
|
||||
};
|
|
@ -1,68 +0,0 @@
|
|||
# nasal lib io.nas
|
||||
# 2020/2/8
|
||||
# this file is used to avoid name confliction
|
||||
# and is used to avoid name undefined
|
||||
# before running this file will be translated to abstract syntax tree
|
||||
# and this ast will be linked before main ast as main-ast's beginning
|
||||
|
||||
var io=
|
||||
{
|
||||
# Opens the file with the specified mode (as per ANSI fopen()) and returns a ghost object representing the filehandle.
|
||||
# Failures are thrown as runtime errors as per die().
|
||||
open:func(filename,mode="r")
|
||||
{
|
||||
return nasal_call_builtin_c_fopen(filename,mode);
|
||||
},
|
||||
# Closes the specified file as per ANSI fclose().
|
||||
close:func(filehandle)
|
||||
{
|
||||
nasal_call_builtin_c_fclose(filehandle);
|
||||
return;
|
||||
},
|
||||
# Attempts to read length bytes from the filehandle into the beginning of the mutable string buf.
|
||||
# Failures (including overruns when length > size(buf)) are thrown as runtime errors as per die().
|
||||
# Returns the number of bytes successfully read.
|
||||
read:func(filehandle,buf,length)
|
||||
{
|
||||
return nasal_call_builtin_c_read(filehandle,buf,length);
|
||||
},
|
||||
# Attempts to write the entirety of the specified string to the filehandle.
|
||||
# Failures are thrown as runtime errors as per die().
|
||||
# Returns the number of bytes successfully written.
|
||||
write:func(filehandle,str)
|
||||
{
|
||||
return nasal_call_builtin_c_write(filehandle,str);
|
||||
},
|
||||
# As ANSI fseek().
|
||||
# Attempts to seek to the specified position based on the whence value
|
||||
# (which must be one of io.SEEK_SET,io.SEEK_END, or io.SEEK_CUR)
|
||||
SEEK_SET:1,
|
||||
SEEK_CUR:2,
|
||||
SEEK_END:3,
|
||||
seek:func(filehandle,position,whence)
|
||||
{
|
||||
nasal_call_builtin_c_seek(filehandle,position,whence);
|
||||
return;
|
||||
},
|
||||
# Returns the current seek position of the filehandle.
|
||||
tell:func(filehandle)
|
||||
{
|
||||
return nasal_call_builtin_c_tell(filehandle);
|
||||
},
|
||||
# Reads and returns a single text line from the filehandle.
|
||||
# Interprets both "\n" and "\r\n" as end of line markers,
|
||||
# and does not include the "\r" or "\n" bytes in the returned string.
|
||||
# End offile or error is signaled by returning nil.
|
||||
readln:func(filehandle)
|
||||
{
|
||||
return nasal_call_builtin_builtin_c_getline(filehandle);
|
||||
},
|
||||
# Calls unix or win32 stat() on the specified file name and
|
||||
# returns a seven element array whose contents are,
|
||||
# in order: dev, ino, mode,nlink, uid, gid, rdef, size, atime, mtime, ctime.
|
||||
# Errors are signaled as exceptions as per die().
|
||||
stat:func(filename)
|
||||
{
|
||||
return nasal_call_builtin_builtin_stat(filename);
|
||||
},
|
||||
};
|
|
@ -1,49 +0,0 @@
|
|||
# nasal lib math.nas
|
||||
# 2020/2/8
|
||||
# this file is used to avoid name confliction
|
||||
# and is used to avoid name undefined
|
||||
# before running this file will be translated to abstract syntax tree
|
||||
# and this ast will be linked before main ast as main-ast's beginning
|
||||
|
||||
var math=
|
||||
{
|
||||
# Euler's constant
|
||||
e:2.7182818284590452354,
|
||||
pi:3.14159265358979323846,
|
||||
# Returns the sine of the single argument
|
||||
sin:func(x)
|
||||
{
|
||||
return nasal_call_builtin_sin(x);
|
||||
},
|
||||
# Returns the cosine of the single argument
|
||||
cos:func(x)
|
||||
{
|
||||
return nasal_call_builtin_cos(x);
|
||||
},
|
||||
# you know what the f*ck this is
|
||||
tan:func(x)
|
||||
{
|
||||
return nasal_call_builtin_tan(x);
|
||||
},
|
||||
# Returns e (Euler's constant) raised to the power specified by the single argument
|
||||
exp:func(x)
|
||||
{
|
||||
return nasal_call_builtin_exp(x);
|
||||
},
|
||||
# Returns the natural logarithm of the single argument.
|
||||
ln:func(x)
|
||||
{
|
||||
return nasal_call_builtin_cpp_math_ln(x);
|
||||
},
|
||||
# Returns the square root of the single argument.
|
||||
sqrt:func(x)
|
||||
{
|
||||
return nasal_call_builtin_cpp_math_sqrt(x);
|
||||
},
|
||||
# Returns the arctangent of y/x, with the correct sign for the quadrant.
|
||||
# Wraps the ANSI C function of the same name.
|
||||
atan2:func(x,y)
|
||||
{
|
||||
return nasal_call_builtin_cpp_atan2(x,y);
|
||||
},
|
||||
};
|
|
@ -1,12 +0,0 @@
|
|||
# nasal lib readline.nas
|
||||
# 2020/2/6
|
||||
# this file is used to avoid name confliction
|
||||
# and is used to avoid name undefined
|
||||
# before running this file will be translated to abstract syntax tree
|
||||
# and this ast will be linked before main ast as main-ast's beginning
|
||||
|
||||
# GNU Readline Library
|
||||
var readline=func(prompt="> ")
|
||||
{
|
||||
return;
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
# nasal lib regex.nas
|
||||
# 2020/2/6
|
||||
# this file is used to avoid name confliction
|
||||
# and is used to avoid name undefined
|
||||
# before running this file will be translated to abstract syntax tree
|
||||
# and this ast will be linked before main ast as main-ast's beginning
|
||||
|
||||
var regex=
|
||||
{
|
||||
comp:func(){},
|
||||
exec:func(){},
|
||||
};
|
|
@ -1,15 +0,0 @@
|
|||
# nasal lib sqlite.nas
|
||||
# 2020/2/6
|
||||
# this file is used to avoid name confliction
|
||||
# and is used to avoid name undefined
|
||||
# before running this file will be translated to abstract syntax tree
|
||||
# and this ast will be linked before main ast as main-ast's beginning
|
||||
|
||||
var sqlite=
|
||||
{
|
||||
open:func(){},
|
||||
close:func(){},
|
||||
prepare:func(){},
|
||||
exec:func(){},
|
||||
finalize:func(){},
|
||||
};
|
|
@ -1,14 +0,0 @@
|
|||
var system=func(str)
|
||||
{
|
||||
nasal_call_builtin_system(str);
|
||||
return;
|
||||
}
|
||||
var sleep=func(duration)
|
||||
{
|
||||
nasal_call_builtin_sleep(duration);
|
||||
return;
|
||||
}
|
||||
var input=func()
|
||||
{
|
||||
return nasal_call_builtin_input();
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
# nasal lib thread.nas
|
||||
# 2020/2/6
|
||||
# this file is used to avoid name confliction
|
||||
# and is used to avoid name undefined
|
||||
# before running this file will be translated to abstract syntax tree
|
||||
# and this ast will be linked before main ast as main-ast's beginning
|
||||
|
||||
var thread=
|
||||
{
|
||||
newthread:func(){},
|
||||
newlock:func(){},
|
||||
lock:func(){},
|
||||
unlock:func(){},
|
||||
newsem:func(){},
|
||||
semdown:func(){},
|
||||
semup:func(){},
|
||||
};
|
|
@ -1,22 +0,0 @@
|
|||
# nasal lib unix.nas
|
||||
# 2020/2/6
|
||||
# this file is used to avoid name confliction
|
||||
# and is used to avoid name undefined
|
||||
# before running this file will be translated to abstract syntax tree
|
||||
# and this ast will be linked before main ast as main-ast's beginning
|
||||
|
||||
var unix=
|
||||
{
|
||||
pipe:func(){},
|
||||
fork:func(){},
|
||||
dup2:func(){},
|
||||
exec:func(){},
|
||||
waitpid:func(){},
|
||||
opendir:func(){},
|
||||
readdir:func(){},
|
||||
closedir:func(){},
|
||||
time:func(){},
|
||||
chdir:func(){},
|
||||
environ:func(){},
|
||||
sleep:func(){},
|
||||
};
|
|
@ -1,15 +0,0 @@
|
|||
# nasal lib utf8.nas
|
||||
# 2020/2/6
|
||||
# this file is used to avoid name confliction
|
||||
# and is used to avoid name undefined
|
||||
# before running this file will be translated to abstract syntax tree
|
||||
# and this ast will be linked before main ast as main-ast's beginning
|
||||
|
||||
var utf8=
|
||||
{
|
||||
chstr:func(){},
|
||||
strc:func(){},
|
||||
substr:func(){},
|
||||
size:func(){},
|
||||
validate:func(){},
|
||||
};
|
Loading…
Reference in New Issue