forked from xxq250/Nasal-Interpreter
Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c4e6a89959 | ||
|
|
f60f674845 | ||
|
|
c21d40c466 | ||
|
|
19b590f3bb | ||
|
|
a421470715 | ||
|
|
79dc13f419 | ||
|
|
2e8208a752 | ||
|
|
1c40cca673 | ||
|
|
b1a5a5f6c0 | ||
|
|
64961877de | ||
|
|
9c9bb52818 | ||
|
|
02148f4766 | ||
|
|
767711c93a | ||
|
|
78ba0641a6 | ||
|
|
80683c381f | ||
|
|
6aac46adaf | ||
|
|
388ef66308 | ||
|
|
8faa4ef2db | ||
|
|
441c02d0fb | ||
|
|
953ad80482 | ||
|
|
e2ee9cff4c | ||
|
|
996ac59c79 | ||
|
|
944f713ee9 | ||
|
|
7329c70492 | ||
|
|
b5514fd269 | ||
|
|
3be50116fa | ||
|
|
125d6d3a7d | ||
|
|
bb746dfbfb | ||
|
|
8069a1b659 | ||
|
|
f0cb8b6ef3 | ||
|
|
9474ac9ef0 | ||
|
|
b862aa91eb | ||
|
|
bc64d530be | ||
|
|
ea5116e963 | ||
|
|
cc4e697246 | ||
|
|
515bef3f5d | ||
|
|
05800fe518 | ||
|
|
33d37771ce | ||
|
|
89540475cf | ||
|
|
e03da2f737 | ||
|
|
4617eb8f17 | ||
|
|
fed1e20085 | ||
|
|
9f30440286 |
337
README.md
337
README.md
@@ -1,48 +1,42 @@
|
||||
# Nasal Interpreter
|
||||
|
||||
[](http://wiki.flightgear.org/File:Nasallogo3.png)
|
||||
|
||||
# Nasal script language
|
||||
# Nasal Script Language
|
||||
|
||||
[Nasal](http://wiki.flightgear.org/Nasal_scripting_language) is a script language that used in [FlightGear](https://www.flightgear.org/).
|
||||
|
||||
There is a Nasal console in FlightGear but sometimes it is not so easy for every developer to use.
|
||||
The interpreter is still in development(now it works well --2021/2/15). We really need your support!
|
||||
|
||||
So this is an interpreter for Nasal written by C++.
|
||||
|
||||
The interpreter is still in development.We really need your support!
|
||||
Also,i am a member of [FGPRC](https://www.fgprc.org/), welcome to join us!
|
||||
|
||||
# Why Writing Nasal Interpreter
|
||||
|
||||
Nasal is a script language first used in Flightgear.
|
||||
|
||||
But in last summer holiday, members in FGPRC told me that it is hard to debug with nasal-console in Flightgear, especially when checking syntax error.
|
||||
But in last summer holiday, members in FGPRC told me that it is hard to debug with nasal-console in Flightgear, especially when checking syntax errors.
|
||||
|
||||
So i tried to write a new interpreter to help them checking syntax error and even, runtime error.
|
||||
|
||||
I wrote the lexer, parser and runtime(nasal virtual machine/ast-runtime virtual machine) to help checking errors.
|
||||
I wrote the lexer, parser and runtime(bytecode virtual machine/ast-runtime virtual machine) to help checking errors.
|
||||
|
||||
They found it easier for them to check errors before copying nasal-codes in nasal-console in Flightgear to test.
|
||||
|
||||
# How to Compile
|
||||
|
||||
> g++ -std=c++11 main.cpp -o main.exe
|
||||
|
||||
# Lexical Analysis
|
||||
|
||||
The flow chart of lexer is here:
|
||||
|
||||
[](https://github.com/ValKmjolnir/Nasal-Interpreter/blob/master/pic/nasal_lexer.png)
|
||||
|
||||
This picture seems ugly. I will re-draw it later(maybe 1000 years later).
|
||||
|
||||
# Parser
|
||||
|
||||
## Version 3.0
|
||||
LL(k) parser.
|
||||
|
||||
I refactored parser and make it easier to maintain.
|
||||
```javascript
|
||||
|
||||
The EBNF is also refactored.
|
||||
(var a,b,c)=[{b:nil},[1,2],func{return 0;}];
|
||||
|
||||
(a.b,b[0],c)=(1,2,3);
|
||||
|
||||
```
|
||||
|
||||
have the same first set,so LL(1) is useless for this language.
|
||||
|
||||
Maybe in the future i can refactor it to LL(1) with special checks.
|
||||
|
||||
# Abstract Syntax Tree
|
||||
|
||||
@@ -64,6 +58,12 @@ Now you can add your own functions as builtin-functions in this interpreter!
|
||||
|
||||
I decide to save the ast interpreter after releasing v4.0. Because it took me a long time to think and write...
|
||||
|
||||
## Version 5.0
|
||||
|
||||
I change my mind.AST interpreter leaves me too much things to do.
|
||||
|
||||
If i continue saving this interpreter,it will be harder for me to make the bytecode vm become more efficient.
|
||||
|
||||
# Byte Code Interpreter
|
||||
|
||||
## Version 4.0
|
||||
@@ -77,21 +77,286 @@ Now i am trying to search hidden bugs in this interpreter.Hope you could help me
|
||||
There's an example of byte code below:
|
||||
|
||||
```javascript
|
||||
var (a,b,c)=(1,2,3);
|
||||
for(var i=0;i<4000000;i+=1);
|
||||
```
|
||||
|
||||
```asm
|
||||
.number 0
|
||||
.number 4e+006
|
||||
.number 1
|
||||
.number 2
|
||||
.number 3
|
||||
.symbol a
|
||||
.symbol b
|
||||
.symbol c
|
||||
0x00000000: pone 0x00000000
|
||||
0x00000001: load 0x00000000 (a)
|
||||
0x00000002: pnum 0x00000001 (2)
|
||||
0x00000003: load 0x00000001 (b)
|
||||
0x00000004: pnum 0x00000002 (3)
|
||||
0x00000005: load 0x00000002 (c)
|
||||
0x00000006: nop 0x00000000
|
||||
```
|
||||
.symbol i
|
||||
0x00000000: pzero 0x00000000
|
||||
0x00000001: load 0x00000000 (i)
|
||||
0x00000002: call 0x00000000 (i)
|
||||
0x00000003: pnum 0x00000001 (4e+006)
|
||||
0x00000004: less 0x00000000
|
||||
0x00000005: jf 0x0000000b
|
||||
0x00000006: pone 0x00000000
|
||||
0x00000007: mcall 0x00000000 (i)
|
||||
0x00000008: addeq 0x00000000
|
||||
0x00000009: pop 0x00000000
|
||||
0x0000000a: jmp 0x00000002
|
||||
0x0000000b: nop 0x00000000
|
||||
```
|
||||
|
||||
## Version 5.0
|
||||
|
||||
I decide to optimize bytecode vm in this version.
|
||||
|
||||
Because it takes more than 1.5s to count i from 0 to 4000000-1.This is not efficient at all!
|
||||
|
||||
2021/1/23 update: Now it can count from 0 to 4000000-1 in 1.5s.
|
||||
|
||||
# How to Use Nasal to Program
|
||||
|
||||
## basic value type
|
||||
|
||||
nasal has 6 value types.Number,string,vector,hash,function,nil.
|
||||
|
||||
Number has 3 formats.Dec,hex and oct;
|
||||
|
||||
String has 3 formats.But the third one is often used to declare a character.
|
||||
|
||||
Vector has unlimited length and can store all types of values.
|
||||
|
||||
Hash is a hashmap that stores values with strings/identifiers as the key.
|
||||
|
||||
Function is also a value type in nasal.
|
||||
|
||||
```javascript
|
||||
var spc=nil;
|
||||
|
||||
var a=1;
|
||||
var a=2.71828;
|
||||
var a=2.147e16;
|
||||
var a=1e-10;
|
||||
var a=0x7fffffff;
|
||||
var a=0xAA55;
|
||||
var a=0o170001;
|
||||
|
||||
var b='str';
|
||||
var b="another string";
|
||||
var b=`c`;
|
||||
|
||||
var c=[];
|
||||
var c=[0,nil,{},[],func(){return 0;}];
|
||||
append(c,0,1,2);
|
||||
|
||||
var d={
|
||||
member1:nil,
|
||||
member2:'str',
|
||||
'member3':'member\'s name can also be a string constant',
|
||||
"member4":"also this",
|
||||
function:func()
|
||||
{
|
||||
var a=me.member2~me.member3;
|
||||
return a;
|
||||
}
|
||||
};
|
||||
|
||||
var f=func(x,y,z)
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
var f=func
|
||||
{
|
||||
return 1024;
|
||||
}
|
||||
var f=func(x,y,z,default_parameter1=1,default_parameter2=2)
|
||||
{
|
||||
return x+y+z+default_parameter1+default_parameter2;
|
||||
}
|
||||
var f=func(x,y,z,dynamic_parameter...)
|
||||
{
|
||||
var sum=0;
|
||||
foreach(var i;dynamic_parameter)
|
||||
sum+=i;
|
||||
return sum+x+y+z;
|
||||
}
|
||||
```
|
||||
|
||||
## operators
|
||||
|
||||
```javascript
|
||||
1+2;
|
||||
1-2;
|
||||
1*2;
|
||||
1/2;
|
||||
'str1'~'str2';
|
||||
(1+2)*(3+4)
|
||||
|
||||
1+1 and 0;
|
||||
1+2*3 or 0;
|
||||
1<0;
|
||||
1>0;
|
||||
1<=0;
|
||||
1>=0;
|
||||
1==0;
|
||||
1!=0;
|
||||
|
||||
-1;
|
||||
!0;
|
||||
|
||||
a=b=c=d=1;
|
||||
a+=1;
|
||||
a-=1;
|
||||
a*=1;
|
||||
a/=1;
|
||||
a~='string';
|
||||
```
|
||||
|
||||
## definition
|
||||
|
||||
```javascript
|
||||
var a=1;
|
||||
var (a,b,c)=[0,1,2];
|
||||
var (a,b,c)=(0,1,2);
|
||||
(var a,b,c)=[0,1,2];
|
||||
(var a,b,c)=(0,1,2);
|
||||
```
|
||||
|
||||
## multi-assignment
|
||||
|
||||
```javascript
|
||||
(a,b[0],c.d)=[0,1,2];
|
||||
(a,b[1],c.e)=(0,1,2);
|
||||
```
|
||||
|
||||
## conditional expression
|
||||
|
||||
```javascript
|
||||
if(1)
|
||||
{
|
||||
;
|
||||
}
|
||||
elsif(2)
|
||||
{
|
||||
;
|
||||
}
|
||||
else if(3)
|
||||
{
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
;
|
||||
}
|
||||
```
|
||||
|
||||
## loop
|
||||
|
||||
```javascript
|
||||
while(condition)
|
||||
continue;
|
||||
|
||||
for(var i=0;i<10;i+=1)
|
||||
break;
|
||||
|
||||
forindex(var i;elem)
|
||||
print(elem[i]);
|
||||
|
||||
foreach(var i;elem)
|
||||
print(i);
|
||||
```
|
||||
|
||||
## subvec
|
||||
|
||||
Use index to search one element in the string will get the ascii number of this character.If you want to get the character,use built-in function chr().
|
||||
|
||||
```javascript
|
||||
a[-1,1,0:2,0:,:3,:,nil:8,3:nil,nil:nil];
|
||||
"hello world"[0];
|
||||
```
|
||||
|
||||
## special function call
|
||||
|
||||
This is of great use but is not very efficient.
|
||||
|
||||
```javascript
|
||||
a(x:0,y:1,z:2);
|
||||
```
|
||||
|
||||
## closure
|
||||
```javascript
|
||||
var f=func()
|
||||
{
|
||||
var a=1;
|
||||
return func(){return a;};
|
||||
}
|
||||
print(f()());
|
||||
```
|
||||
|
||||
## built-in functions
|
||||
|
||||
Must import lib.nas or has these functions' definitions inside your code.
|
||||
|
||||
Also you could add builtin functions of your own(written in C/C++) to help you calculate things more quickly.(Advanced usage)
|
||||
|
||||
Check built-in functions in lib.nas!
|
||||
|
||||
If you want to add your own built-in functions,define the function in nasal_builtin.h.
|
||||
|
||||
Definition:
|
||||
|
||||
```C++
|
||||
nasal_val* builtin_chr(nasal_val*,nasal_gc&);
|
||||
```
|
||||
|
||||
Then complete this function using C++:
|
||||
|
||||
```C++
|
||||
nasal_val* builtin_print(nasal_val* local_scope_addr,nasal_gc& gc)
|
||||
{
|
||||
// get arguments by using in_builtin_find
|
||||
nasal_val* vector_value_addr=in_builtin_find("elements");
|
||||
// main process
|
||||
// also check type here,if get a type error,use builtin_error_occurred and return nullptr
|
||||
nasal_vec& ref_vec=vector_value_addr->get_vector();
|
||||
int size=ref_vec.size();
|
||||
for(int i=0;i<size;++i)
|
||||
{
|
||||
nasal_val* tmp=ref_vec[i];
|
||||
switch(tmp->get_type())
|
||||
{
|
||||
case vm_nil: std::cout<<"nil"; break;
|
||||
case vm_num: std::cout<<tmp->get_number(); break;
|
||||
case vm_str: std::cout<<tmp->get_string(); break;
|
||||
case vm_vec: tmp->get_vector().print(); break;
|
||||
case vm_hash: tmp->get_hash().print(); break;
|
||||
case vm_func: std::cout<<"func(...){...}"; break;
|
||||
}
|
||||
}
|
||||
// if a nasal value is not in use,use gc::del_reference to delete it
|
||||
// if get a new reference of a nasal value,use gc::add_reference
|
||||
// generate return value,use gc::gc_alloc(type) to make a new value
|
||||
return gc.gc_alloc(vm_nil);
|
||||
}
|
||||
```
|
||||
|
||||
After that, write the built-in function's name(in nasal) and the function's pointer in this table:
|
||||
|
||||
```C++
|
||||
struct FUNC_TABLE
|
||||
{
|
||||
std::string func_name;
|
||||
nasal_val* (*func_pointer)(nasal_val* x,nasal_gc& gc);
|
||||
} builtin_func_table[]=
|
||||
{
|
||||
{"nasal_call_builtin_std_cout",builtin_print},
|
||||
{"",NULL}
|
||||
};
|
||||
```
|
||||
|
||||
At last,warp the 'nasal_call_builtin_std_cout' in a nasal file:
|
||||
|
||||
```javascript
|
||||
var print=func(elements...)
|
||||
{
|
||||
nasal_call_builtin_std_cout(elements);
|
||||
return nil;
|
||||
};
|
||||
```
|
||||
|
||||
In version 5.0,if you don't warp built-in function in a normal nasal function,this built-in function may cause a fault when searching arguments,which will cause SIGSEGV segmentation error(maybe).
|
||||
|
||||
Use import("") to get the nasal file including your biult-in functions,then you could use it.
|
||||
90
lib.nas
90
lib.nas
@@ -8,6 +8,12 @@ var print=func(elements...)
|
||||
nasal_call_builtin_std_cout(elements);
|
||||
return nil;
|
||||
};
|
||||
var println=func(elements...)
|
||||
{
|
||||
nasal_call_builtin_std_cout(elements);
|
||||
print('\n');
|
||||
return nil;
|
||||
}
|
||||
var append=func(vector,elements...)
|
||||
{
|
||||
nasal_call_builtin_push_back(vector,elements);
|
||||
@@ -94,6 +100,26 @@ var substr=func(str,begin,length)
|
||||
{
|
||||
return nasal_call_builtin_substr(str,begin,length);
|
||||
}
|
||||
var streq=func(a,b)
|
||||
{
|
||||
return nasal_call_builtin_streq(a,b);
|
||||
}
|
||||
var left=func(string,length)
|
||||
{
|
||||
return nasal_call_builtin_left(string,length);
|
||||
}
|
||||
var right=func(string,length)
|
||||
{
|
||||
return nasal_call_builtin_right(string,length);
|
||||
}
|
||||
var cmp=func(a,b)
|
||||
{
|
||||
return nasal_call_builtin_cmp(a,b);
|
||||
}
|
||||
var chr=func(code) #//Unlike in FG, this chr does not support Extended ASCII
|
||||
{
|
||||
return nasal_call_builtin_chr(code);
|
||||
}
|
||||
|
||||
var io=
|
||||
{
|
||||
@@ -110,58 +136,22 @@ var io=
|
||||
|
||||
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);
|
||||
}
|
||||
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.14159265358979323846264338327950288,
|
||||
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);
|
||||
},
|
||||
e: 2.7182818284590452354,
|
||||
pi: 3.14159265358979323846264338327950288,
|
||||
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); }
|
||||
};
|
||||
|
||||
93
main.cpp
93
main.cpp
@@ -4,51 +4,51 @@ nasal_lexer lexer;
|
||||
nasal_parse parse;
|
||||
nasal_import import;
|
||||
std::string inputfile="null";
|
||||
nasal_runtime runtime;
|
||||
nasal_codegen code_generator;
|
||||
nasal_bytecode_vm bytevm;
|
||||
nasal_vm vm;
|
||||
|
||||
void help()
|
||||
{
|
||||
std::cout<<">> [\"file\"] input a file name.\n";
|
||||
std::cout<<">> [help ] show help.\n";
|
||||
std::cout<<">> [clear ] clear the screen.\n";
|
||||
std::cout<<">> [del ] clear the input filename.\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<<">> [code ] show byte code.\n";
|
||||
std::cout<<">> [exec ] execute program on bytecode vm.\n";
|
||||
std::cout<<">> [logo ] print logo of nasal .\n";
|
||||
std::cout<<">> [exit ] quit nasal interpreter.\n";
|
||||
std::cout
|
||||
<<">> [\"file\"] input a file name.\n"
|
||||
<<">> [help ] show help.\n"
|
||||
<<">> [clear ] clear the screen.\n"
|
||||
<<">> [lex ] use lexer to turn code into tokens.\n"
|
||||
<<">> [ast ] do parsing and check the abstract syntax tree.\n"
|
||||
<<">> [code ] show byte code.\n"
|
||||
<<">> [exec ] execute program on bytecode vm.\n"
|
||||
<<">> [logo ] print logo of nasal .\n"
|
||||
<<">> [exit ] quit nasal interpreter.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
void logo()
|
||||
{
|
||||
std::cout<<" __ _ \n";
|
||||
std::cout<<" /\\ \\ \\__ _ ___ __ _| | \n";
|
||||
std::cout<<" / \\/ / _` / __|/ _` | | \n";
|
||||
std::cout<<" / /\\ / (_| \\__ \\ (_| | | \n";
|
||||
std::cout<<" \\_\\ \\/ \\__,_|___/\\__,_|_|\n";
|
||||
std::cout
|
||||
<<" __ _ \n"
|
||||
<<" /\\ \\ \\__ _ ___ __ _| | \n"
|
||||
<<" / \\/ / _` / __|/ _` | | \n"
|
||||
<<" / /\\ / (_| \\__ \\ (_| | | \n"
|
||||
<<" \\_\\ \\/ \\__,_|___/\\__,_|_|\n";
|
||||
return;
|
||||
}
|
||||
|
||||
void del_func()
|
||||
{
|
||||
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 clear()
|
||||
{
|
||||
// this will clear the data in lexer/parser/import modules
|
||||
// to reduce memory footprint
|
||||
lexer.get_token_list().clear();
|
||||
parse.get_root().clear();
|
||||
import.get_root().clear();
|
||||
return;
|
||||
}
|
||||
|
||||
void lex_func()
|
||||
{
|
||||
lexer.openfile(inputfile);
|
||||
@@ -59,6 +59,7 @@ void lex_func()
|
||||
return;
|
||||
}
|
||||
lexer.print_token();
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -79,33 +80,7 @@ void ast_print()
|
||||
return;
|
||||
}
|
||||
parse.get_root().print_ast(0);
|
||||
return;
|
||||
}
|
||||
|
||||
void runtime_start()
|
||||
{
|
||||
lexer.openfile(inputfile);
|
||||
lexer.scanner();
|
||||
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;
|
||||
}
|
||||
import.link(parse.get_root());
|
||||
if(import.get_error())
|
||||
{
|
||||
die("import",inputfile);
|
||||
return;
|
||||
}
|
||||
runtime.set_root(import.get_root());
|
||||
runtime.run();
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -132,6 +107,7 @@ void show_bytecode()
|
||||
return;
|
||||
}
|
||||
code_generator.main_progress(import.get_root());
|
||||
clear();
|
||||
code_generator.print_byte_code();
|
||||
return;
|
||||
}
|
||||
@@ -159,7 +135,8 @@ void execute()
|
||||
return;
|
||||
}
|
||||
code_generator.main_progress(import.get_root());
|
||||
bytevm.run(
|
||||
clear();
|
||||
vm.run(
|
||||
code_generator.get_string_table(),
|
||||
code_generator.get_number_table(),
|
||||
code_generator.get_exec_code()
|
||||
@@ -176,7 +153,7 @@ int main()
|
||||
system("cls");
|
||||
#endif
|
||||
logo();
|
||||
std::cout<<">> Nasal interpreter ver 3.0 .\n";
|
||||
std::cout<<">> Nasal interpreter ver 5.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";
|
||||
@@ -198,14 +175,10 @@ int main()
|
||||
system("clear");
|
||||
#endif
|
||||
}
|
||||
else if(command=="del")
|
||||
del_func();
|
||||
else if(command=="lex")
|
||||
lex_func();
|
||||
else if(command=="ast")
|
||||
ast_print();
|
||||
else if(command=="run")
|
||||
runtime_start();
|
||||
else if(command=="code")
|
||||
show_bytecode();
|
||||
else if(command=="exec")
|
||||
|
||||
5
nasal.h
5
nasal.h
@@ -19,7 +19,7 @@
|
||||
#include <stack>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
||||
/*
|
||||
check if a string can be converted to a number
|
||||
@@ -133,8 +133,7 @@ std::string trans_number_to_string(double number)
|
||||
#include "nasal_import.h"
|
||||
#include "nasal_gc.h"
|
||||
#include "nasal_builtin.h"
|
||||
#include "nasal_runtime.h"
|
||||
#include "nasal_codegen.h"
|
||||
#include "nasal_bytecode_vm.h"
|
||||
#include "nasal_vm.h"
|
||||
|
||||
#endif
|
||||
|
||||
143
nasal_ast.h
143
nasal_ast.h
@@ -4,17 +4,17 @@
|
||||
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_nil,ast_num,ast_str,ast_id,ast_func,ast_hash,ast_vec,
|
||||
ast_hashmember,ast_call,ast_callh,ast_callv,ast_callf,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_equal,ast_addeq,ast_subeq,ast_multeq,ast_diveq,ast_lnkeq,
|
||||
ast_cmpeq,ast_neq,
|
||||
ast_less,ast_leq,
|
||||
ast_grt,ast_geq,
|
||||
ast_add,ast_sub,ast_mult,ast_div,ast_link,
|
||||
ast_unary_sub,ast_unary_not,
|
||||
ast_trinocular,
|
||||
ast_neg,ast_not,
|
||||
ast_trino,
|
||||
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,
|
||||
@@ -22,70 +22,69 @@ enum ast_node
|
||||
ast_continue,ast_break,ast_return
|
||||
};
|
||||
|
||||
std::string ast_str(int type)
|
||||
std::string ast_name(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;
|
||||
case ast_null: return "null";
|
||||
case ast_root: return "root";
|
||||
case ast_block: return "block";
|
||||
case ast_nil: return "nil";
|
||||
case ast_num: return "number";
|
||||
case ast_str: return "string";
|
||||
case ast_id: return "id";
|
||||
case ast_func: return "function";
|
||||
case ast_hash: return "hash";
|
||||
case ast_vec: return "vector";
|
||||
case ast_hashmember: return "hashmember";
|
||||
case ast_call: return "call";
|
||||
case ast_callh: return "callh";
|
||||
case ast_callv: return "callv";
|
||||
case ast_callf: return "callf";
|
||||
case ast_subvec: return "subvec";
|
||||
case ast_args: return "args";
|
||||
case ast_default_arg: return "deflt_arg";
|
||||
case ast_dynamic_id: return "dyn_id";
|
||||
case ast_and: return "and";
|
||||
case ast_or: return "or";
|
||||
case ast_equal: return "=";
|
||||
case ast_addeq: return "+=";
|
||||
case ast_subeq: return "-=";
|
||||
case ast_multeq: return "*=";
|
||||
case ast_diveq: return "/=";
|
||||
case ast_lnkeq: return "~=";
|
||||
case ast_cmpeq: return "==";
|
||||
case ast_neq: return "!=";
|
||||
case ast_less: return "<";
|
||||
case ast_leq: return "<=";
|
||||
case ast_grt: return ">";
|
||||
case ast_geq: return ">=";
|
||||
case ast_add: return "+";
|
||||
case ast_sub: return "-";
|
||||
case ast_mult: return "*";
|
||||
case ast_div: return "/";
|
||||
case ast_link: return "~";
|
||||
case ast_neg: return "unary-";
|
||||
case ast_not: return "unary!";
|
||||
case ast_trino: return "trino";
|
||||
case ast_for: return "for";
|
||||
case ast_forindex: return "forindex";
|
||||
case ast_foreach: return "foreach";
|
||||
case ast_while: return "while";
|
||||
case ast_new_iter: return "iter";
|
||||
case ast_conditional: return "conditional";
|
||||
case ast_if: return "if";
|
||||
case ast_elsif: return "elsif";
|
||||
case ast_else: return "else";
|
||||
case ast_multi_id: return "multi_id";
|
||||
case ast_multi_scalar: return "multi_scalar";
|
||||
case ast_definition: return "def";
|
||||
case ast_multi_assign: return "multi_assign";
|
||||
case ast_continue: return "continue";
|
||||
case ast_break: return "break";
|
||||
case ast_return: return "return";
|
||||
}
|
||||
return str;
|
||||
return "null";
|
||||
}
|
||||
|
||||
class nasal_ast
|
||||
@@ -217,13 +216,13 @@ void nasal_ast::print_ast(int depth)
|
||||
{
|
||||
std::string indentation="";
|
||||
for(int i=0;i<depth;++i) indentation+="| ";
|
||||
indentation+=ast_str(this->type);
|
||||
indentation+=ast_name(this->type);
|
||||
std::cout<<indentation;
|
||||
if(this->type==ast_string || this->type==ast_identifier || this->type==ast_dynamic_id || this->type==ast_call_hash)
|
||||
if(this->type==ast_str || this->type==ast_id || this->type==ast_dynamic_id || this->type==ast_callh)
|
||||
std::cout<<":"<<this->str;
|
||||
else if(this->type==ast_number)
|
||||
else if(this->type==ast_num)
|
||||
std::cout<<":"<<this->num;
|
||||
std::cout<<std::endl;
|
||||
std::cout<<'\n';
|
||||
int child_size=this->children.size();
|
||||
for(int i=0;i<child_size;++i)
|
||||
this->children[i].print_ast(depth+1);
|
||||
|
||||
995
nasal_builtin.h
995
nasal_builtin.h
File diff suppressed because it is too large
Load Diff
1466
nasal_bytecode_vm.h
1466
nasal_bytecode_vm.h
File diff suppressed because it is too large
Load Diff
753
nasal_codegen.h
753
nasal_codegen.h
File diff suppressed because it is too large
Load Diff
787
nasal_gc.h
787
nasal_gc.h
File diff suppressed because it is too large
Load Diff
@@ -10,28 +10,17 @@ private:
|
||||
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 link(nasal_ast&);
|
||||
nasal_ast& get_root();
|
||||
};
|
||||
|
||||
nasal_import::nasal_import()
|
||||
{
|
||||
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;
|
||||
@@ -39,13 +28,6 @@ void nasal_import::die(std::string filename,std::string error_stage)
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_import::init()
|
||||
{
|
||||
import_lex.clear();
|
||||
import_par.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
bool nasal_import::check_import(nasal_ast& node)
|
||||
{
|
||||
/*
|
||||
@@ -63,9 +45,9 @@ bool nasal_import::check_import(nasal_ast& node)
|
||||
return false;
|
||||
if(ref_vec[0].get_str()!="import")
|
||||
return false;
|
||||
if(ref_vec[1].get_type()!=ast_call_func)
|
||||
if(ref_vec[1].get_type()!=ast_callf)
|
||||
return false;
|
||||
if(ref_vec[1].get_children().size()!=1 || ref_vec[1].get_children()[0].get_type()!=ast_string)
|
||||
if(ref_vec[1].get_children().size()!=1 || ref_vec[1].get_children()[0].get_type()!=ast_str)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@@ -94,15 +76,11 @@ void nasal_import::linker(nasal_ast& root,nasal_ast& add_root)
|
||||
nasal_ast nasal_import::file_import(nasal_ast& node)
|
||||
{
|
||||
// initializing
|
||||
nasal_ast tmp;
|
||||
tmp.set_line(0);
|
||||
tmp.set_type(ast_root);
|
||||
init();
|
||||
nasal_ast tmp(0,ast_root);
|
||||
|
||||
// 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))
|
||||
@@ -131,9 +109,7 @@ nasal_ast nasal_import::file_import(nasal_ast& node)
|
||||
|
||||
nasal_ast nasal_import::load(nasal_ast& root)
|
||||
{
|
||||
nasal_ast new_root;
|
||||
new_root.set_line(0);
|
||||
new_root.set_type(ast_root);
|
||||
nasal_ast new_root(0,ast_root);
|
||||
|
||||
std::vector<nasal_ast>& ref_vec=root.get_children();
|
||||
int size=ref_vec.size();
|
||||
@@ -148,7 +124,6 @@ nasal_ast nasal_import::load(nasal_ast& root)
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
|
||||
271
nasal_lexer.h
271
nasal_lexer.h
@@ -7,7 +7,7 @@
|
||||
#define IS_DIGIT(c) ('0'<=c&&c<='9')
|
||||
#define IS_STRING(c) (c=='\''||c=='\"'||c=='`')
|
||||
// single operators have only one character
|
||||
#define IS_SINGLE_OPRATOR(c) (c=='('||c==')'||c=='['||c==']'||c=='{'||c=='}'||c==','||c==';'||c=='|'||c==':'||\
|
||||
#define IS_SINGLE_OPERATOR(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=='~')
|
||||
@@ -16,18 +16,19 @@
|
||||
enum token_type
|
||||
{
|
||||
tok_null=0,
|
||||
tok_number,tok_string,tok_identifier,
|
||||
tok_num,tok_str,tok_id,
|
||||
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_ret,tok_if,tok_elsif,tok_else,tok_nil,
|
||||
tok_lcurve,tok_rcurve,
|
||||
tok_lbracket,tok_rbracket,
|
||||
tok_lbrace,tok_rbrace,
|
||||
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_less_equal,tok_greater_than,tok_greater_equal
|
||||
tok_eq,
|
||||
tok_addeq,tok_subeq,tok_multeq,tok_diveq,tok_lnkeq,
|
||||
tok_cmpeq,tok_neq,tok_less,tok_leq,tok_grt,tok_geq,
|
||||
tok_eof
|
||||
};
|
||||
|
||||
struct
|
||||
@@ -36,52 +37,52 @@ struct
|
||||
int tok_type;
|
||||
}token_table[]=
|
||||
{
|
||||
{"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_less_equal },
|
||||
{">" ,tok_greater_than },
|
||||
{">=" ,tok_greater_equal},
|
||||
{NULL ,-1 }
|
||||
{"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_ret },
|
||||
{"if" ,tok_if },
|
||||
{"elsif" ,tok_elsif },
|
||||
{"else" ,tok_else },
|
||||
{"nil" ,tok_nil },
|
||||
{"(" ,tok_lcurve },
|
||||
{")" ,tok_rcurve },
|
||||
{"[" ,tok_lbracket },
|
||||
{"]" ,tok_rbracket },
|
||||
{"{" ,tok_lbrace },
|
||||
{"}" ,tok_rbrace },
|
||||
{";" ,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_eq },
|
||||
{"+=" ,tok_addeq },
|
||||
{"-=" ,tok_subeq },
|
||||
{"*=" ,tok_multeq },
|
||||
{"/=" ,tok_diveq },
|
||||
{"~=" ,tok_lnkeq },
|
||||
{"==" ,tok_cmpeq },
|
||||
{"!=" ,tok_neq },
|
||||
{"<" ,tok_less },
|
||||
{"<=" ,tok_leq },
|
||||
{">" ,tok_grt },
|
||||
{">=" ,tok_geq },
|
||||
{NULL ,-1 }
|
||||
};
|
||||
|
||||
struct token
|
||||
@@ -89,6 +90,7 @@ struct token
|
||||
int line;
|
||||
int type;
|
||||
std::string str;
|
||||
token(int l=0,int t=tok_null,std::string s=""){line=l;type=t;str=s;return;}
|
||||
};
|
||||
|
||||
class nasal_lexer
|
||||
@@ -101,31 +103,19 @@ private:
|
||||
std::string line_code;
|
||||
std::vector<char> res;
|
||||
std::vector<token> token_list;
|
||||
int get_token_type(std::string);
|
||||
void die(std::string,std::string,int,int);
|
||||
std::string identifier_gen();
|
||||
std::string number_gen();
|
||||
std::string string_gen();
|
||||
public:
|
||||
void clear();
|
||||
void openfile(std::string);
|
||||
void die(std::string,int,int);
|
||||
void scanner();
|
||||
void print_token();
|
||||
int get_error();
|
||||
std::vector<token>& get_token_list();
|
||||
};
|
||||
|
||||
void nasal_lexer::clear()
|
||||
{
|
||||
error=0;
|
||||
res_size=0;
|
||||
line=0;
|
||||
ptr=0;
|
||||
line_code="";
|
||||
res.clear();
|
||||
token_list.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_lexer::openfile(std::string filename)
|
||||
{
|
||||
error=0;
|
||||
@@ -150,10 +140,21 @@ void nasal_lexer::openfile(std::string filename)
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_lexer::die(std::string error_info,int line=-1,int column=-1)
|
||||
int nasal_lexer::get_token_type(std::string tk_str)
|
||||
{
|
||||
for(int i=0;token_table[i].str;++i)
|
||||
if(tk_str==token_table[i].str)
|
||||
return token_table[i].tok_type;
|
||||
return tok_null;
|
||||
}
|
||||
|
||||
void nasal_lexer::die(std::string code,std::string error_info,int line=-1,int column=-1)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">> [lexer] line "<<line<<" column "<<column<<": "<<error_info<<"\n";
|
||||
std::cout<<">> [lexer] line "<<line<<" column "<<column<<": \n"<<code<<"\n";
|
||||
for(int i=0;i<column-1;++i)
|
||||
std::cout<<(code[i]=='\t'?'\t':' ');
|
||||
std::cout<<"^ "<<error_info<<'\n';
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -172,7 +173,7 @@ std::string nasal_lexer::number_gen()
|
||||
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')
|
||||
if(ptr+1<res_size && res[ptr]=='0' && res[ptr+1]=='x')
|
||||
{
|
||||
token_str="0x";
|
||||
ptr+=2;
|
||||
@@ -181,13 +182,13 @@ std::string nasal_lexer::number_gen()
|
||||
line_code+=token_str;
|
||||
if(token_str=="0x")
|
||||
{
|
||||
die("["+line_code+"_] incorrect number.",line,line_code.length());
|
||||
die(line_code,"incorrect number.",line,line_code.length());
|
||||
return "0";
|
||||
}
|
||||
return token_str;
|
||||
}
|
||||
// generate oct number
|
||||
else if(res[ptr]=='0' && ptr+1<res_size && res[ptr+1]=='o')
|
||||
else if(ptr+1<res_size && res[ptr]=='0' && res[ptr+1]=='o')
|
||||
{
|
||||
token_str="0o";
|
||||
ptr+=2;
|
||||
@@ -196,7 +197,7 @@ std::string nasal_lexer::number_gen()
|
||||
line_code+=token_str;
|
||||
if(token_str=="0o")
|
||||
{
|
||||
die("["+line_code+"_] incorrect number.",line,line_code.length());
|
||||
die(line_code,"incorrect number.",line,line_code.length());
|
||||
return "0";
|
||||
}
|
||||
return token_str;
|
||||
@@ -212,7 +213,7 @@ std::string nasal_lexer::number_gen()
|
||||
if(ptr>=res_size)
|
||||
{
|
||||
line_code+=token_str;
|
||||
die("["+line_code+"_] incorrect number.",line,line_code.length());
|
||||
die(line_code,"incorrect number.",line,line_code.length());
|
||||
return "0";
|
||||
}
|
||||
while(ptr<res_size && IS_DIGIT(res[ptr]))
|
||||
@@ -221,7 +222,7 @@ std::string nasal_lexer::number_gen()
|
||||
if(token_str.back()=='.')
|
||||
{
|
||||
line_code+=token_str;
|
||||
die("["+line_code+"_] incorrect number.",line,line_code.length());
|
||||
die(line_code,"incorrect number.",line,line_code.length());
|
||||
return "0";
|
||||
}
|
||||
}
|
||||
@@ -232,7 +233,7 @@ std::string nasal_lexer::number_gen()
|
||||
if(ptr>=res_size)
|
||||
{
|
||||
line_code+=token_str;
|
||||
die("["+line_code+"_] incorrect number.",line,line_code.length());
|
||||
die(line_code,"incorrect number.",line,line_code.length());
|
||||
return "0";
|
||||
}
|
||||
if(ptr<res_size && (res[ptr]=='-' || res[ptr]=='+'))
|
||||
@@ -240,18 +241,16 @@ std::string nasal_lexer::number_gen()
|
||||
if(ptr>=res_size)
|
||||
{
|
||||
line_code+=token_str;
|
||||
die("["+line_code+"_] incorrect number.",line,line_code.length());
|
||||
die(line_code,"incorrect number.",line,line_code.length());
|
||||
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()=='+')
|
||||
{
|
||||
line_code+=token_str;
|
||||
die("["+line_code+"_] incorrect number.",line,line_code.length());
|
||||
die(line_code,"incorrect number.",line,line_code.length());
|
||||
return "0";
|
||||
}
|
||||
}
|
||||
@@ -262,9 +261,9 @@ std::string nasal_lexer::number_gen()
|
||||
std::string nasal_lexer::string_gen()
|
||||
{
|
||||
std::string token_str="";
|
||||
line_code+=res[ptr];
|
||||
char str_begin=res[ptr++];
|
||||
while(ptr<res_size && res[ptr]!=str_begin)
|
||||
char str_begin=res[ptr];
|
||||
line_code+=str_begin;
|
||||
while(++ptr<res_size && res[ptr]!=str_begin)
|
||||
{
|
||||
line_code+=res[ptr];
|
||||
if(res[ptr]=='\n')
|
||||
@@ -274,8 +273,7 @@ std::string nasal_lexer::string_gen()
|
||||
}
|
||||
if(res[ptr]=='\\' && ptr+1<res_size)
|
||||
{
|
||||
++ptr;
|
||||
line_code+=res[ptr];
|
||||
line_code+=res[++ptr];
|
||||
switch(res[ptr])
|
||||
{
|
||||
case 'a':token_str.push_back('\a');break;
|
||||
@@ -292,15 +290,13 @@ std::string nasal_lexer::string_gen()
|
||||
case '\"':token_str.push_back('\"');break;
|
||||
default: token_str.push_back(res[ptr]);break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
token_str+=res[ptr];
|
||||
++ptr;
|
||||
token_str+=res[ptr];
|
||||
}
|
||||
// check if this string ends with a " or '
|
||||
if(ptr>=res_size)
|
||||
die("["+line_code+"_] get EOF when generating string.",line,line_code.length());
|
||||
++ptr;
|
||||
if(ptr++>=res_size)
|
||||
die(line_code,"get EOF when generating string.",line,line_code.length());
|
||||
return token_str;
|
||||
}
|
||||
|
||||
@@ -318,66 +314,41 @@ void nasal_lexer::scanner()
|
||||
{
|
||||
// these characters will be ignored, and '\n' will cause ++line
|
||||
line_code+=res[ptr];
|
||||
if(res[ptr]=='\n')
|
||||
if(res[ptr++]=='\n')
|
||||
{
|
||||
++line;
|
||||
line_code="";
|
||||
}
|
||||
++ptr;
|
||||
}
|
||||
if(ptr>=res_size) break;
|
||||
if(IS_IDENTIFIER(res[ptr]))
|
||||
{
|
||||
token_str=identifier_gen();
|
||||
token new_token;
|
||||
new_token.line=line;
|
||||
new_token.str=token_str;
|
||||
new_token.type=0;
|
||||
for(int i=0;token_table[i].str;++i)
|
||||
if(token_str==token_table[i].str)
|
||||
{
|
||||
new_token.type=token_table[i].tok_type;
|
||||
break;
|
||||
}
|
||||
token new_token(line,get_token_type(token_str),token_str);
|
||||
if(!new_token.type)
|
||||
new_token.type=tok_identifier;
|
||||
new_token.type=tok_id;
|
||||
token_list.push_back(new_token);
|
||||
}
|
||||
else if(IS_DIGIT(res[ptr]))
|
||||
{
|
||||
token_str=number_gen();
|
||||
token new_token;
|
||||
new_token.line=line;
|
||||
new_token.str=token_str;
|
||||
new_token.type=tok_number;
|
||||
token new_token(line,tok_num,token_str);
|
||||
token_list.push_back(new_token);
|
||||
}
|
||||
else if(IS_STRING(res[ptr]))
|
||||
{
|
||||
token_str=string_gen();
|
||||
token new_token;
|
||||
new_token.line=line;
|
||||
new_token.type=tok_string;
|
||||
new_token.str=token_str;
|
||||
token new_token(line,tok_str,token_str);
|
||||
token_list.push_back(new_token);
|
||||
}
|
||||
else if(IS_SINGLE_OPRATOR(res[ptr]))
|
||||
else if(IS_SINGLE_OPERATOR(res[ptr]))
|
||||
{
|
||||
token_str="";
|
||||
token_str+=res[ptr];
|
||||
line_code+=res[ptr];
|
||||
token new_token;
|
||||
new_token.line=line;
|
||||
new_token.str=token_str;
|
||||
new_token.type=-1;
|
||||
for(int i=0;token_table[i].str;++i)
|
||||
if(token_str==token_table[i].str)
|
||||
{
|
||||
new_token.type=token_table[i].tok_type;
|
||||
break;
|
||||
}
|
||||
if(new_token.type<0)
|
||||
die("["+line_code+"_] incorrect operator.",line,line_code.length());
|
||||
token new_token(line,get_token_type(token_str),token_str);
|
||||
if(!new_token.type)
|
||||
die(line_code,"incorrect operator.",line,line_code.length());
|
||||
token_list.push_back(new_token);
|
||||
++ptr;
|
||||
}
|
||||
@@ -394,53 +365,29 @@ void nasal_lexer::scanner()
|
||||
++ptr;
|
||||
}
|
||||
line_code+=token_str;
|
||||
token new_token;
|
||||
new_token.line=line;
|
||||
new_token.str=token_str;
|
||||
for(int i=0;token_table[i].str;++i)
|
||||
if(token_str==token_table[i].str)
|
||||
{
|
||||
new_token.type=token_table[i].tok_type;
|
||||
break;
|
||||
}
|
||||
token new_token(line,get_token_type(token_str),token_str);
|
||||
token_list.push_back(new_token);
|
||||
}
|
||||
else if(IS_CALC_OPERATOR(res[ptr]))
|
||||
{
|
||||
// get calculation operator
|
||||
token_str=res[ptr];
|
||||
++ptr;
|
||||
if(ptr<res.size() && res[ptr]=='=')
|
||||
{
|
||||
token_str+=res[ptr];
|
||||
++ptr;
|
||||
}
|
||||
token_str=res[ptr++];
|
||||
if(ptr<res_size && res[ptr]=='=')
|
||||
token_str+=res[ptr++];
|
||||
line_code+=token_str;
|
||||
token new_token;
|
||||
new_token.line=line;
|
||||
new_token.str=token_str;
|
||||
for(int i=0;token_table[i].str;++i)
|
||||
if(token_str==token_table[i].str)
|
||||
{
|
||||
new_token.type=token_table[i].tok_type;
|
||||
break;
|
||||
}
|
||||
token new_token(line,get_token_type(token_str),token_str);
|
||||
token_list.push_back(new_token);
|
||||
}
|
||||
else if(IS_NOTE(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 if(IS_NOTE(res[ptr]))// avoid note, after this process ptr will point to a '\n', so next loop line counter+1
|
||||
while(++ptr<res_size && res[ptr]!='\n');
|
||||
else
|
||||
{
|
||||
line_code+=res[ptr];
|
||||
die("["+line_code+"_] unknown character.",line,line_code.length());
|
||||
++ptr;
|
||||
line_code+=res[ptr++];
|
||||
die(line_code,"unknown character.",line,line_code.length());
|
||||
}
|
||||
}
|
||||
token tk(line,tok_eof,"");
|
||||
token_list.push_back(tk);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
1377
nasal_parse.h
1377
nasal_parse.h
File diff suppressed because it is too large
Load Diff
1896
nasal_runtime.h
1896
nasal_runtime.h
File diff suppressed because it is too large
Load Diff
1183
nasal_vm.h
Normal file
1183
nasal_vm.h
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 62 KiB |
152
props.nas
Normal file
152
props.nas
Normal file
@@ -0,0 +1,152 @@
|
||||
import("lib.nas");
|
||||
|
||||
var props=
|
||||
{
|
||||
globals:nil,
|
||||
Node:nil,
|
||||
getNode:func(path,index)
|
||||
{
|
||||
path=split('/',path);
|
||||
var tmp=me.globals;
|
||||
var path_size=size(path);
|
||||
for(var i=0;i<path_size-1;i+=1)
|
||||
tmp=tmp.val[path[i]];
|
||||
if(path_size>0)
|
||||
{
|
||||
if(contains(tmp.val,path[i]~'['~index~']'))
|
||||
return tmp.val[path[i]~'['~index~']'];
|
||||
else
|
||||
return tmp.val[path[i]];
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
};
|
||||
|
||||
props.Node=
|
||||
{
|
||||
new:func(values=nil)
|
||||
{
|
||||
var result={
|
||||
parents:[props.Node],
|
||||
val:{},
|
||||
type:'GHOST',
|
||||
parent:nil
|
||||
};
|
||||
if(typeof(values)=="hash")
|
||||
result.val=values;
|
||||
return result;
|
||||
},
|
||||
addChild:func(name)
|
||||
{
|
||||
if(!contains(me.val,name))
|
||||
{
|
||||
me.val[name]=props.Node.new();
|
||||
me.val[name].parent=me;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
addChildren:func(name,cnt=0)
|
||||
{
|
||||
for(var i=0;i<cnt;i+=1)
|
||||
{
|
||||
var label=name~'['~i~']';
|
||||
me.val[label]=props.Node.new();
|
||||
me.val[label].parent=me;
|
||||
}
|
||||
return;
|
||||
},
|
||||
setValue:func(path,val)
|
||||
{
|
||||
path=split('/',path);
|
||||
var tmp=me;
|
||||
foreach(var label;path)
|
||||
tmp=tmp.val[label];
|
||||
tmp.val=val;
|
||||
if(typeof(val)=='string')
|
||||
{
|
||||
if(val=='true' or val=='false')
|
||||
tmp.type='BOOL';
|
||||
else
|
||||
tmp.type='STRING';
|
||||
}
|
||||
elsif(typeof(val)=='number')
|
||||
tmp.type='DOUBLE';
|
||||
return;
|
||||
},
|
||||
setIntValue:func(num)
|
||||
{
|
||||
me.val=num;
|
||||
me.type='INT';
|
||||
return;
|
||||
},
|
||||
setBoolValue:func(state)
|
||||
{
|
||||
me.val=state;
|
||||
me.type='BOOL';
|
||||
return;
|
||||
},
|
||||
setDoubleValue:func(num)
|
||||
{
|
||||
me.val=num;
|
||||
me.type='DOUBLE';
|
||||
return;
|
||||
},
|
||||
getValue:func(){return me.val;},
|
||||
getName:func()
|
||||
{
|
||||
var val=me.parent.val;
|
||||
var key=keys(val);
|
||||
foreach(var k;key)
|
||||
if(val[k]==me)
|
||||
return k;
|
||||
return '';
|
||||
},
|
||||
getParent:func()
|
||||
{
|
||||
return me.parent;
|
||||
},
|
||||
getPath:func()
|
||||
{
|
||||
if(me.parent==nil) return '';
|
||||
return me.parent.getPath()~'/'~me.getName();
|
||||
},
|
||||
equals:func(node){return me==node;},
|
||||
debug:func(s='')
|
||||
{
|
||||
if(typeof(me.val)=='hash')
|
||||
{
|
||||
var key=keys(me.val);
|
||||
println('{');
|
||||
foreach(var k;key)
|
||||
{
|
||||
print(s~' ',k,':');
|
||||
me.val[k].debug(s~' ');
|
||||
}
|
||||
println(s,'}');
|
||||
}
|
||||
else
|
||||
println(me.val,' (',me.type,')');
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
props.globals=props.Node.new();
|
||||
var c=['aircraft','ai','models','position','orientation','controls','sim'];
|
||||
foreach(var i;c)
|
||||
props.getNode('/',1).addChild(i);
|
||||
props.getNode('/ai',1).addChildren('ai',4);
|
||||
props.getNode('/aircraft',1).setValue('/','IDG MD-11');
|
||||
for(var i=0;i<4;i+=1)
|
||||
props.getNode('/ai/ai['~i~']',1).setBoolValue('true');
|
||||
props.getNode('/models',1).addChildren('building',4);
|
||||
for(var i=0;i<4;i+=1)
|
||||
props.getNode('/models/building['~i~']',1).setIntValue(i);
|
||||
props.getNode('/',1).addChild('test');
|
||||
props.getNode('/test',1).addChildren('in',4);
|
||||
props.getNode('/test/in',0).setValue('/','true');
|
||||
props.getNode('/test/in',1).setValue('/','false');
|
||||
props.getNode('/test/in',2).setValue('/','welcome aboard,need help? use help->tutorial');
|
||||
props.getNode('/test/in',3).setValue('/',2147483648);
|
||||
props.globals.debug();
|
||||
println(props.getNode('/test/in',3).getPath());
|
||||
@@ -1,96 +0,0 @@
|
||||
# NasNeuron lib written by ValKmjolnir
|
||||
|
||||
# Basic Class NasMatrix
|
||||
# NasMatGen : generate a new matrix
|
||||
# NasMatAdd : add two matrixes
|
||||
# NasMatSub : sub two matrixes
|
||||
# NasMatMul : multiply two matrix
|
||||
# NasMatTrans: transpose a matrix
|
||||
# NasMatPrt : print a matrix
|
||||
var NasMatrix=
|
||||
{
|
||||
NasMatGen:func(row,col)
|
||||
{
|
||||
var GenMat={Row:row,Col:col,Elem:[]};
|
||||
for(var i=0;i<row;i+=1)
|
||||
{
|
||||
var TmpVec=[];
|
||||
for(var j=0;j<col;j+=1)
|
||||
append(TmpVec,0);
|
||||
append(GenMat.Elem,TmpVec);
|
||||
}
|
||||
return GenMat;
|
||||
},
|
||||
NasMatAdd:func(mat1,mat2)
|
||||
{
|
||||
var ResultMat=nil;
|
||||
if(mat1.Row==mat2.Row and mat1.Col==mat2.Col)
|
||||
{
|
||||
ResultMat=me.NasMatGen(mat1.Row,mat1.Col);
|
||||
for(var i=0;i<ResultMat.Row;i+=1)
|
||||
for(var j=0;j<ResultMat.Col;j+=1)
|
||||
ResultMat.Elem[i][j]=mat1.Elem[i][j]+mat2.Elem[i][j];
|
||||
}
|
||||
else
|
||||
print("NasNeuron: Mat1 and Mat2 have different rows and cols.");
|
||||
return ResultMat;
|
||||
},
|
||||
NasMatSub:func(mat1,mat2)
|
||||
{
|
||||
var ResultMat=nil;
|
||||
if(mat1.Row==mat2.Row and mat1.Col==mat2.Col)
|
||||
{
|
||||
ResultMat=me.NasMatGen(mat1.Row,mat1.Col);
|
||||
for(var i=0;i<ResultMat.Row;i+=1)
|
||||
for(var j=0;j<ResultMat.Col;j+=1)
|
||||
ResultMat.Elem[i][j]=mat1.Elem[i][j]-mat2.Elem[i][j];
|
||||
}
|
||||
else
|
||||
print("NasNeuron: Mat1 and Mat2 have different rows and cols.");
|
||||
return ResultMat;
|
||||
},
|
||||
NasMatMul:func(mat1,mat2)
|
||||
{
|
||||
var ResultMat=nil;
|
||||
if(mat1.Col==mat2.Row)
|
||||
{
|
||||
ResultMat=me.NasMatGen(mat1.Row,mat2.Col);
|
||||
for(var i=0;i<ResultMat.Row;i+=1)
|
||||
for(var j=0;j<ResultMat.Col;j+=1)
|
||||
{
|
||||
var sum=0;
|
||||
for(var k=0;k<mat1.Col;k+=1)
|
||||
sum+=mat1.Elem[i][k]*mat2.Elem[k][j];
|
||||
ResultMat.Elem[i][j]=sum;
|
||||
}
|
||||
}
|
||||
else
|
||||
print("NasNeuron: Mat1's Col is different from Mat2's Row.");
|
||||
return ResultMat;
|
||||
},
|
||||
NasMatTrans:func(mat)
|
||||
{
|
||||
var ResultMat=nil;
|
||||
ResultMat=me.NasMatGen(mat.Col,mat.Row);
|
||||
for(var i=0;i<ResultMat.Row;i+=1)
|
||||
for(var j=0;j<ResultMat.Col;j+=1)
|
||||
ResultMat.Elem[i][j]=mat.Elem[j][i];
|
||||
return ResultMat;
|
||||
},
|
||||
NasMatPrt:func(mat)
|
||||
{
|
||||
for(var i=0;i<mat.Row;i+=1)
|
||||
{
|
||||
for(var j=0;j<mat.Col;j+=1)
|
||||
print(mat.Elem[i][j],' ');
|
||||
print('\n');
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
};
|
||||
|
||||
NasMatrix.NasMatPrt(
|
||||
NasMatrix.NasMatGen(
|
||||
10,100
|
||||
)
|
||||
);
|
||||
@@ -329,7 +329,4 @@ var main=func()
|
||||
return nil;
|
||||
}
|
||||
|
||||
# var (a,b,c)=[1,2,3];
|
||||
# (a,b,c)=(b,c,a);
|
||||
# print(a,b,c);
|
||||
main();
|
||||
|
||||
@@ -45,7 +45,7 @@ var trans_ttf=func(string)
|
||||
str[j]~=char_ttf[0][j];
|
||||
}
|
||||
foreach(var i;str)
|
||||
print(i);
|
||||
println(i);
|
||||
return;
|
||||
}
|
||||
var curve1=func()
|
||||
@@ -100,7 +100,7 @@ var curve4=func()
|
||||
{
|
||||
forindex(var i;s)
|
||||
{
|
||||
print(s[i]);
|
||||
println(s[i]);
|
||||
s[i]='';
|
||||
}
|
||||
cnt=0;
|
||||
@@ -123,11 +123,12 @@ var curve5=func()
|
||||
var s="";
|
||||
for(var i=0;i<size(arr);i+=1)
|
||||
s~=shadow[arr[i]];
|
||||
print(s);
|
||||
println(s);
|
||||
}
|
||||
return;
|
||||
}
|
||||
trans_ttf("just for test");
|
||||
trans_ttf("ValKmjolnir");
|
||||
curve1();
|
||||
curve2();
|
||||
curve3();
|
||||
|
||||
12
test/bfs.nas
12
test/bfs.nas
@@ -20,7 +20,7 @@ var prt=func()
|
||||
s~=map[i][j];
|
||||
s~='\n';
|
||||
}
|
||||
print(s);
|
||||
print(s,'\n');
|
||||
}
|
||||
|
||||
var bfs=func(begin,end)
|
||||
@@ -50,16 +50,12 @@ var bfs=func(begin,end)
|
||||
}
|
||||
prt();
|
||||
}
|
||||
print("cannot reach.");
|
||||
print("cannot reach.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
prt();
|
||||
var x=num(input());
|
||||
var y=num(input());
|
||||
var begin=[x,y];
|
||||
x=num(input());
|
||||
y=num(input());
|
||||
var end=[x,y];
|
||||
var begin=[input(),input()];
|
||||
var end=[input(),input()];
|
||||
bfs(begin,end);
|
||||
prt();
|
||||
1
test/bigloop.nas
Normal file
1
test/bigloop.nas
Normal file
@@ -0,0 +1 @@
|
||||
for(var i=0;i<4000000;i+=1);
|
||||
31
test/bp.nas
31
test/bp.nas
@@ -125,8 +125,9 @@ var backward=func(x)
|
||||
}
|
||||
|
||||
var cnt=0;
|
||||
var show=0;
|
||||
var error=1e8;
|
||||
while(error>0.01)
|
||||
while(error>0.0005)
|
||||
{
|
||||
error=0;
|
||||
for(var i=0;i<4;i+=1)
|
||||
@@ -136,18 +137,22 @@ while(error>0.01)
|
||||
backward(i);
|
||||
}
|
||||
cnt+=1;
|
||||
print('epoch ',cnt,':',error);
|
||||
show+=1;
|
||||
if(show==200)
|
||||
{
|
||||
show=0;
|
||||
print('epoch ',cnt,':',error,'\r');
|
||||
}
|
||||
}
|
||||
print('\afinished.');
|
||||
while(1)
|
||||
print('finished after ',cnt,' epoch.\n');
|
||||
var vec=[
|
||||
[0,0],
|
||||
[0,1],
|
||||
[1,0],
|
||||
[1,1]
|
||||
];
|
||||
foreach(var v;vec)
|
||||
{
|
||||
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);
|
||||
run(v);
|
||||
print(v,': ',output[0].out,'\n');
|
||||
}
|
||||
30
test/calc.nas
Normal file
30
test/calc.nas
Normal file
@@ -0,0 +1,30 @@
|
||||
import("lib.nas");
|
||||
func(){
|
||||
var filename=[
|
||||
"main.cpp",
|
||||
"nasal_ast.h",
|
||||
"nasal_builtin.h",
|
||||
"nasal_codegen.h",
|
||||
"nasal_gc.h",
|
||||
"nasal_import.h",
|
||||
"nasal_lexer.h",
|
||||
"nasal_parse.h",
|
||||
"nasal_vm.h",
|
||||
"nasal.h"
|
||||
];
|
||||
var max_size=size('nasal_codegen.h');
|
||||
var (cnt,semi)=[0,0];
|
||||
foreach(var file;filename)
|
||||
{
|
||||
var s=io.fin(file);
|
||||
var name=file;
|
||||
for(var i=size(name);i<max_size;i+=1)
|
||||
name~=' ';
|
||||
var line_cnt=size(split('\n',s));
|
||||
var semi_cnt=size(split(';' ,s))-1;
|
||||
println(name,'| ',line_cnt,' \tline | ',semi_cnt,' \tsemi');
|
||||
cnt +=line_cnt;
|
||||
semi+=semi_cnt;
|
||||
}
|
||||
println('total: ',cnt,' line | ',semi,' semi');
|
||||
}();
|
||||
@@ -1,38 +0,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);
|
||||
}
|
||||
19
test/class.nas
Normal file
19
test/class.nas
Normal file
@@ -0,0 +1,19 @@
|
||||
import("lib.nas");
|
||||
|
||||
var student=
|
||||
{
|
||||
new:func(name,age)
|
||||
{
|
||||
return {
|
||||
parents:[student],
|
||||
name:name,
|
||||
age:age
|
||||
};
|
||||
},
|
||||
print_info:func(){println(me.name,' ',me.age);},
|
||||
get_age:func(){return me.age;},
|
||||
get_name:func(){return me.name;}
|
||||
};
|
||||
var s=student.new('tiansuohaoer',24);
|
||||
s.print_info();
|
||||
println(s.get_age(),' ',s.get_name());
|
||||
27
test/fib.nas
Normal file
27
test/fib.nas
Normal file
@@ -0,0 +1,27 @@
|
||||
var print=func(elements...)
|
||||
{
|
||||
nasal_call_builtin_std_cout(elements);
|
||||
return nil;
|
||||
};
|
||||
var setsize=func(vector,size)
|
||||
{
|
||||
nasal_call_builtin_set_size(vector,size);
|
||||
return nil;
|
||||
}
|
||||
var fib=func(x)
|
||||
{
|
||||
if(x<2) return x;
|
||||
return fib(x-1)+fib(x-2);
|
||||
}
|
||||
print(fib(30),'\n');
|
||||
|
||||
var m=[0,1,1,2,3,5,8];
|
||||
setsize(m,101);
|
||||
var fib=func(n)
|
||||
{
|
||||
if(m[n]!=nil) return m[n];
|
||||
var t=fib(n-1)+fib(n-2);
|
||||
m[n]=t;
|
||||
return t;
|
||||
}
|
||||
print(fib(100),'\n');
|
||||
@@ -1,6 +0,0 @@
|
||||
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 +0,0 @@
|
||||
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"});
|
||||
32
test/leetcode1319.nas
Normal file
32
test/leetcode1319.nas
Normal file
@@ -0,0 +1,32 @@
|
||||
import("lib.nas");
|
||||
# 并查集
|
||||
var n=4;
|
||||
var input=[[0,1],[0,2],[1,2]];
|
||||
|
||||
var find_root=func(x,parent)
|
||||
{
|
||||
while(parent[x]!=nil)
|
||||
x=parent[x];
|
||||
return x;
|
||||
}
|
||||
var union_root=func(x,y,parent)
|
||||
{
|
||||
var x_root=find_root(x,parent);
|
||||
var y_root=find_root(y,parent);
|
||||
if(x_root==y_root) return 0;
|
||||
else parent[x_root]=y_root;
|
||||
return 1;
|
||||
}
|
||||
var makeConnect=func(n,connections)
|
||||
{
|
||||
if(size(connections)<n-1) return -1;
|
||||
var cnt=n-1;
|
||||
var parent=[];
|
||||
setsize(parent,n);
|
||||
for(var i=0;i<size(connections);i+=1)
|
||||
if(union_root(connections[i][0],connections[i][1],parent))
|
||||
cnt-=1;
|
||||
return cnt;
|
||||
}
|
||||
|
||||
print(makeConnect(n,input));
|
||||
@@ -1,7 +1,6 @@
|
||||
import("lib.nas");
|
||||
|
||||
var s=io.fin("a.nas");
|
||||
s=split('',s);
|
||||
var s=split('',io.fin(input()));
|
||||
var len=size(s);
|
||||
var ptr=0;
|
||||
|
||||
@@ -59,7 +58,7 @@ var generate_str=func()
|
||||
ptr+=1;
|
||||
}
|
||||
if(ptr>=len)
|
||||
print("read eof when generating string.");
|
||||
print("read eof when generating string.\n");
|
||||
ptr+=1;
|
||||
return tok_str;
|
||||
}
|
||||
@@ -178,6 +177,6 @@ while(ptr<len)
|
||||
}
|
||||
foreach(var i;token)
|
||||
{
|
||||
print("(",cnt," | ",i,")");
|
||||
print("(",cnt," | ",i,")\n");
|
||||
cnt+=1;
|
||||
}
|
||||
90
test/lib.nas
90
test/lib.nas
@@ -8,6 +8,12 @@ var print=func(elements...)
|
||||
nasal_call_builtin_std_cout(elements);
|
||||
return nil;
|
||||
};
|
||||
var println=func(elements...)
|
||||
{
|
||||
nasal_call_builtin_std_cout(elements);
|
||||
print('\n');
|
||||
return nil;
|
||||
}
|
||||
var append=func(vector,elements...)
|
||||
{
|
||||
nasal_call_builtin_push_back(vector,elements);
|
||||
@@ -94,6 +100,26 @@ var substr=func(str,begin,length)
|
||||
{
|
||||
return nasal_call_builtin_substr(str,begin,length);
|
||||
}
|
||||
var streq=func(a,b)
|
||||
{
|
||||
return nasal_call_builtin_streq(a,b);
|
||||
}
|
||||
var left=func(string,length)
|
||||
{
|
||||
return nasal_call_builtin_left(string,length);
|
||||
}
|
||||
var right=func(string,length)
|
||||
{
|
||||
return nasal_call_builtin_right(string,length);
|
||||
}
|
||||
var cmp=func(a,b)
|
||||
{
|
||||
return nasal_call_builtin_cmp(a,b);
|
||||
}
|
||||
var chr=func(code) #//Unlike in FG, this chr does not support Extended ASCII
|
||||
{
|
||||
return nasal_call_builtin_chr(code);
|
||||
}
|
||||
|
||||
var io=
|
||||
{
|
||||
@@ -110,58 +136,22 @@ var io=
|
||||
|
||||
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);
|
||||
}
|
||||
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);
|
||||
},
|
||||
e: 2.7182818284590452354,
|
||||
pi: 3.14159265358979323846264338327950288,
|
||||
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); }
|
||||
};
|
||||
|
||||
64
test/life.nas
Normal file
64
test/life.nas
Normal file
@@ -0,0 +1,64 @@
|
||||
import("lib.nas");
|
||||
|
||||
var map=nil;
|
||||
|
||||
var check=func(x,y)
|
||||
{
|
||||
if(x>=30) x=0;
|
||||
if(x<0) x=19;
|
||||
if(y>=40) y=0;
|
||||
if(y<0) y=39;
|
||||
return map[x][y];
|
||||
}
|
||||
|
||||
var new_map=func()
|
||||
{
|
||||
var tmp=[];
|
||||
setsize(tmp,30);
|
||||
forindex(var i;tmp)
|
||||
{
|
||||
tmp[i]=[];
|
||||
setsize(tmp[i],40);
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
var prt=func()
|
||||
{
|
||||
var s='';
|
||||
foreach(var line;map)
|
||||
{
|
||||
foreach(var elem;line)
|
||||
s~=elem~' ';
|
||||
s~='\n';
|
||||
}
|
||||
system("cls");
|
||||
print(s);
|
||||
}
|
||||
|
||||
func()
|
||||
{
|
||||
rand(time(0));
|
||||
map=new_map();
|
||||
forindex(var i;map)
|
||||
forindex(var j;map[i])
|
||||
map[i][j]=rand()>0.7?'O':' ';
|
||||
var calc=[[0,1],[1,0],[0,-1],[-1,0],[1,1],[1,-1],[-1,-1],[-1,1]];
|
||||
for(var r=0;r<200;r+=1)
|
||||
{
|
||||
prt(map);
|
||||
var tmp=new_map();
|
||||
forindex(var i;map)
|
||||
forindex(var j;map[i])
|
||||
{
|
||||
var cnt=0;
|
||||
foreach(var k;calc)
|
||||
cnt+=(check(i+k[0],j+k[1])=='O');
|
||||
if(cnt==2) tmp[i][j]=map[i][j];
|
||||
elsif(cnt==3) tmp[i][j]='O';
|
||||
else tmp[i][j]=' ';
|
||||
}
|
||||
map=tmp;
|
||||
}
|
||||
return;
|
||||
}();
|
||||
@@ -1,3 +1,4 @@
|
||||
import("lib.nas");
|
||||
for(;;)break;
|
||||
for(;;)
|
||||
{
|
||||
|
||||
382
test/main.nas
382
test/main.nas
@@ -1,382 +0,0 @@
|
||||
# game left in corner by ValKmjolnir
|
||||
# 2020
|
||||
|
||||
# lib function defined here
|
||||
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 sleep=func(duration)
|
||||
{
|
||||
nasal_call_builtin_sleep(duration);
|
||||
return;
|
||||
}
|
||||
var input=func()
|
||||
{
|
||||
return nasal_call_builtin_input();
|
||||
}
|
||||
var io=
|
||||
{
|
||||
fin:func(filename)
|
||||
{
|
||||
return nasal_call_builtin_finput(filename);
|
||||
},
|
||||
fout:func(filename,str)
|
||||
{
|
||||
nasal_call_builtin_foutput(filename,str);
|
||||
return;
|
||||
}
|
||||
};
|
||||
var int=func(str)
|
||||
{
|
||||
return str+0;
|
||||
}
|
||||
var str=func(num)
|
||||
{
|
||||
return num~'';
|
||||
}
|
||||
# string split
|
||||
|
||||
# game elements defined here
|
||||
var role_property=
|
||||
{
|
||||
health:100,
|
||||
mood:100,
|
||||
satiety:100,
|
||||
thirst:100,
|
||||
health_change:func(x)
|
||||
{
|
||||
me.health+=x;
|
||||
if(me.health<0)
|
||||
me.health=0;
|
||||
elsif(me.health>100)
|
||||
me.health=100;
|
||||
return nil;
|
||||
},
|
||||
mood_change:func(x)
|
||||
{
|
||||
me.mood+=x;
|
||||
if(me.mood<0)
|
||||
me.mood=0;
|
||||
elsif(me.mood>100)
|
||||
me.mood=100;
|
||||
return nil;
|
||||
},
|
||||
satiety_change:func(x)
|
||||
{
|
||||
me.satiety+=x;
|
||||
if(me.satiety<0)
|
||||
me.satiety=0;
|
||||
elsif(me.satiety>100)
|
||||
me.satiety=100;
|
||||
return nil;
|
||||
},
|
||||
thirst_change:func(x)
|
||||
{
|
||||
me.thirst+=x;
|
||||
if(me.thirst<0)
|
||||
me.thirst=0;
|
||||
elsif(me.thirst>100)
|
||||
me.thirst=100;
|
||||
return nil;
|
||||
}
|
||||
};
|
||||
var screen=
|
||||
{
|
||||
picture:[],
|
||||
info_below_left:[],
|
||||
info_below_right:[],
|
||||
clear:func()
|
||||
{
|
||||
me.picture=[];
|
||||
me.info_below_left=[];
|
||||
me.info_below_right=[];
|
||||
return;
|
||||
},
|
||||
pic_addline:func(_str)
|
||||
{
|
||||
append(me.picture,_str);
|
||||
return;
|
||||
},
|
||||
left_add:func(_str)
|
||||
{
|
||||
append(me.info_below_left,_str);
|
||||
return;
|
||||
},
|
||||
right_add:func(_str)
|
||||
{
|
||||
append(me.info_below_right,_str);
|
||||
return;
|
||||
},
|
||||
prt_screen:func()
|
||||
{
|
||||
foreach(var i;me.picture)
|
||||
print(i);
|
||||
forindex(var i;me.info_below_left)
|
||||
print(me.info_below_left[i]~me.info_below_right[i]);
|
||||
return;
|
||||
}
|
||||
};
|
||||
var first_shown_info=func()
|
||||
{
|
||||
system("cls");
|
||||
var str_list=[
|
||||
"+-----------------------------------------------+",
|
||||
"| |",
|
||||
"| |",
|
||||
"| Let me tell you a story... |",
|
||||
"| A story that really happened many years ago...|",
|
||||
"| Nearly no one knows and cares about it... |",
|
||||
"| But some children may still suffer from... |",
|
||||
"| This kind of stories... |",
|
||||
"| And this kind of stories never stop hurting...|",
|
||||
"| People that are still alive... |",
|
||||
"| |",
|
||||
"| |",
|
||||
"+-----------------------------------------------+"
|
||||
];
|
||||
foreach(var i;str_list)
|
||||
print(i);
|
||||
return;
|
||||
}
|
||||
var generate_role_property=func()
|
||||
{
|
||||
screen.left_add("+-----------------------+");
|
||||
var str="";
|
||||
for(var i=10;i<=100;i+=10)
|
||||
{
|
||||
if(i<=role_property.health)
|
||||
str~="=";
|
||||
else
|
||||
str~=" ";
|
||||
}
|
||||
screen.left_add("|[health ]:"~str~" |");
|
||||
str="";
|
||||
for(var i=10;i<=100;i+=10)
|
||||
{
|
||||
if(i<=role_property.mood)
|
||||
str~="=";
|
||||
else
|
||||
str~=" ";
|
||||
}
|
||||
screen.left_add("|[mood ]:"~str~" |");
|
||||
str="";
|
||||
for(var i=10;i<=100;i+=10)
|
||||
{
|
||||
if(i<=role_property.satiety)
|
||||
str~="=";
|
||||
else
|
||||
str~=" ";
|
||||
}
|
||||
screen.left_add("|[satiety]:"~str~" |");
|
||||
str="";
|
||||
for(var i=10;i<=100;i+=10)
|
||||
{
|
||||
if(i<=role_property.thirst)
|
||||
str~="=";
|
||||
else
|
||||
str~=" ";
|
||||
}
|
||||
screen.left_add("|[thirst ]:"~str~" |");
|
||||
screen.left_add("+-----------------------+");
|
||||
return;
|
||||
}
|
||||
var generate_choose_list=func()
|
||||
{
|
||||
var str_list=[
|
||||
"-----------------------+",
|
||||
"[1]| next step |",
|
||||
"[2]| restart |",
|
||||
"[3]| store game |",
|
||||
"[4]| exit |",
|
||||
"-----------------------+"
|
||||
];
|
||||
foreach(var i;str_list)
|
||||
screen.right_add(i);
|
||||
return;
|
||||
}
|
||||
var next_step=func()
|
||||
{
|
||||
role_property.health_change(-1);
|
||||
role_property.mood_change(-1);
|
||||
role_property.satiety_change(-1);
|
||||
role_property.thirst_change(-10);
|
||||
var str_list=[
|
||||
"+-----------------------------------------------+",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"+-----------------------------------------------+"
|
||||
];
|
||||
foreach(var i;str_list)
|
||||
screen.pic_addline(i);
|
||||
return;
|
||||
}
|
||||
var restart=func()
|
||||
{
|
||||
role_property.health=100;
|
||||
role_property.mood=100;
|
||||
role_property.satiety=100;
|
||||
role_property.thirst=100;
|
||||
var str_list=[
|
||||
"+-----------------------------------------------+",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"+-----------------------------------------------+"
|
||||
];
|
||||
foreach(var i;str_list)
|
||||
screen.pic_addline(i);
|
||||
return;
|
||||
}
|
||||
var generate_incorrect_choice_screen=func()
|
||||
{
|
||||
var str_list=[
|
||||
"+-----------------------------------------------+",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| make a correct choice. |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"+-----------------------------------------------+"
|
||||
];
|
||||
foreach(var i;str_list)
|
||||
screen.pic_addline(i);
|
||||
}
|
||||
var generate_goodbye_screen=func()
|
||||
{
|
||||
var str_list=[
|
||||
"+-----------------------------------------------+",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| see you next life. |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"+-----------------------------------------------+"
|
||||
];
|
||||
foreach(var i;str_list)
|
||||
screen.pic_addline(i);
|
||||
}
|
||||
var store_file=func()
|
||||
{
|
||||
var str=role_property.health~'\n'~role_property.mood~'\n'~role_property.satiety~'\n'~role_property.thirst~'\n';
|
||||
io.fout("game-left-in-corner.glic",str);
|
||||
var str_list=[
|
||||
"+-----------------------------------------------+",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| data stored. |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"| |",
|
||||
"+-----------------------------------------------+"
|
||||
];
|
||||
foreach(var i;str_list)
|
||||
screen.pic_addline(i);
|
||||
return;
|
||||
}
|
||||
var get_file=func()
|
||||
{
|
||||
var str=io.fin("game-left-in-corner.glic");
|
||||
print(str);
|
||||
return;
|
||||
}
|
||||
var game_main=func()
|
||||
{
|
||||
first_shown_info();
|
||||
screen.clear();
|
||||
generate_role_property();
|
||||
generate_choose_list();
|
||||
screen.prt_screen();
|
||||
while(1)
|
||||
{
|
||||
screen.clear();
|
||||
print("|your choice[1|2|3|4]: |");
|
||||
var choice=input();
|
||||
if((choice!='1') and (choice!='2') and (choice!='3') and (choice!='4'))
|
||||
generate_incorrect_choice_screen();
|
||||
elsif(choice=='1')
|
||||
next_step();
|
||||
elsif(choice=='2')
|
||||
restart();
|
||||
elsif(choice=='3')
|
||||
store_file();
|
||||
elsif(choice=='4')
|
||||
{
|
||||
system("cls");
|
||||
screen.clear();
|
||||
generate_goodbye_screen();
|
||||
generate_role_property();
|
||||
generate_choose_list();
|
||||
screen.prt_screen();
|
||||
break;
|
||||
}
|
||||
system("cls");
|
||||
generate_role_property();
|
||||
generate_choose_list();
|
||||
screen.prt_screen();
|
||||
if(role_property.health==0 or role_property.mood==0 or role_property.satiety==0 or role_property.thirst==0)
|
||||
{
|
||||
print("|you died. |");
|
||||
print("+-----------------------------------------------+");
|
||||
system("pause");
|
||||
screen.clear();
|
||||
restart();
|
||||
system("cls");
|
||||
generate_role_property();
|
||||
generate_choose_list();
|
||||
screen.prt_screen();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
game_main();
|
||||
@@ -13,16 +13,16 @@ var film_node=[];
|
||||
for(var i=0;i<1000;i+=1)
|
||||
append(film_node,node("film"));
|
||||
var director_node=[];
|
||||
for(var i=0;i<400;i+=1)
|
||||
for(var i=0;i<200;i+=1)
|
||||
append(director_node,node("direct"));
|
||||
var actor_node=[];
|
||||
for(var i=0;i<2000;i+=1)
|
||||
for(var i=0;i<400;i+=1)
|
||||
append(actor_node,node("actor"));
|
||||
var writer_node=[];
|
||||
for(var i=0;i<300;i+=1)
|
||||
for(var i=0;i<100;i+=1)
|
||||
append(writer_node,node("writer"));
|
||||
var type_node=[];
|
||||
for(var i=0;i<20;i+=1)
|
||||
for(var i=0;i<40;i+=1)
|
||||
append(type_node,node("type"));
|
||||
var lang_node=[];
|
||||
for(var i=0;i<120;i+=1)
|
||||
@@ -40,14 +40,14 @@ func()
|
||||
var lang_size=size(lang_node);
|
||||
var country_size=size(country_node);
|
||||
|
||||
var director_link=int(1+rand()*2);
|
||||
var actor_link=int(1+rand()*10);
|
||||
var writer_link=int(1+rand());
|
||||
var type_link=int(1+rand()*3);
|
||||
var lang_link=int(1+rand()*4);
|
||||
var country_link=int(1+rand()*2);
|
||||
foreach(var film;film_node)
|
||||
{
|
||||
var director_link=int(1+rand()*2);
|
||||
var actor_link=int(1+rand()*20);
|
||||
var writer_link=int(1+rand()*2);
|
||||
var type_link=int(1+rand()*5);
|
||||
var lang_link=int(1+rand()*4);
|
||||
var country_link=int(1+rand()*4);
|
||||
for(var i=0;i<director_link;i+=1)
|
||||
{
|
||||
var director=director_node[rand()*director_size];
|
||||
@@ -118,18 +118,9 @@ var sort_list=func(begin,end)
|
||||
return;
|
||||
}
|
||||
|
||||
while(1)
|
||||
var get_next=func(index)
|
||||
{
|
||||
var list_size=size(film_list);
|
||||
list_size=list_size>10?10:list_size;
|
||||
for(var i=0;i<list_size;i+=1)
|
||||
print(i,'\t:',film_list[i].name,'\t',count_list[i]);
|
||||
var choose=input();
|
||||
if(choose=="exit")
|
||||
break;
|
||||
if(num(choose)>=list_size)
|
||||
die("choose a correct index");
|
||||
var label_list=film_node[num(choose)].next;
|
||||
var label_list=film_list[index].next;
|
||||
film_list=[];
|
||||
count_list=[];
|
||||
foreach(var label;label_list)
|
||||
@@ -140,7 +131,7 @@ while(1)
|
||||
if(film_list[i].name==film.name)
|
||||
{
|
||||
has=1;
|
||||
count_list[i]+=rand();
|
||||
count_list[i]+=1;
|
||||
break;
|
||||
}
|
||||
if(has==0)
|
||||
@@ -150,6 +141,21 @@ while(1)
|
||||
}
|
||||
}
|
||||
sort_list(0,size(film_list));
|
||||
return;
|
||||
}
|
||||
|
||||
while(1)
|
||||
{
|
||||
var list_size=size(film_list);
|
||||
list_size=list_size>10?10:list_size;
|
||||
for(var i=1;i<list_size;i+=1)
|
||||
println('| ',i,'\t:',film_list[i].name,'\t',count_list[i]);
|
||||
var choose=input();
|
||||
if(choose=="exit")
|
||||
break;
|
||||
if(num(choose)==0 or num(choose)>=list_size)
|
||||
die("choose a correct index");
|
||||
get_next(num(choose));
|
||||
}
|
||||
|
||||
foreach(var film;film_node)
|
||||
|
||||
246
test/prop.nas
246
test/prop.nas
@@ -1,246 +0,0 @@
|
||||
import("lib.nas");
|
||||
|
||||
var property_tree=
|
||||
{
|
||||
accelerations:
|
||||
{
|
||||
'n-z-cg-fps_sec':0,
|
||||
ned:
|
||||
{
|
||||
'down-accel-fps_sec':0,
|
||||
'east-accel-fps_sec':0,
|
||||
'north-accel-fps_sec':0,
|
||||
},
|
||||
nlf:0,
|
||||
pilot:
|
||||
{
|
||||
'x-accel-fps_sec':0,
|
||||
'y-accel-fps_sec':0,
|
||||
'z-accel-fps_sec':0,
|
||||
},
|
||||
'pilot-g':1,
|
||||
'pilot-gdamped':1
|
||||
},
|
||||
ai:
|
||||
{
|
||||
models:
|
||||
{
|
||||
carrier:
|
||||
{
|
||||
callsign:'',
|
||||
controls:{},
|
||||
environment:{},
|
||||
id:2,
|
||||
name:'Nimitz',
|
||||
navaids:{},
|
||||
orientation:{},
|
||||
position:{},
|
||||
radar:{},
|
||||
sign:'CVN-68',
|
||||
sim:{},
|
||||
subID:0,
|
||||
submodels:
|
||||
{
|
||||
path:'',
|
||||
serviceable:1
|
||||
},
|
||||
'surface-positions':{},
|
||||
type:'AI',
|
||||
valid:1,
|
||||
velocities:{},
|
||||
waypoint:{}
|
||||
},
|
||||
'carrier[1]':
|
||||
{
|
||||
callsign:'',
|
||||
controls:{},
|
||||
environment:{},
|
||||
id:3,
|
||||
name:'Eisenhower',
|
||||
navaids:{},
|
||||
orientation:{},
|
||||
position:{},
|
||||
radar:{},
|
||||
sign:'CVN-69',
|
||||
sim:{},
|
||||
subID:0,
|
||||
submodels:
|
||||
{
|
||||
path:'',
|
||||
serviceable:0
|
||||
},
|
||||
'surface-positions':{},
|
||||
type:'AI',
|
||||
valid:1,
|
||||
velocities:{},
|
||||
waypoint:{}
|
||||
},
|
||||
count:2,
|
||||
'model-added':'/ai[0]/models[0]/carrier[1]',
|
||||
'model-removed':nil,
|
||||
'num-players':0
|
||||
},
|
||||
submodels:
|
||||
{
|
||||
contrails:0
|
||||
},
|
||||
},
|
||||
aircraft:
|
||||
{
|
||||
icao:
|
||||
{
|
||||
equipment:'SDFGY',
|
||||
surveillance:'S',
|
||||
type:'ZZZZ',
|
||||
'wake-turbulence-category':'L'
|
||||
},
|
||||
performance:
|
||||
{
|
||||
approach:
|
||||
{
|
||||
'airspeed-knots':150,
|
||||
},
|
||||
climb:'\n\t\t\t\n\t\t\t',
|
||||
cruise:
|
||||
{
|
||||
'airspeed-knots':1000,
|
||||
'altitude-ft':4500,
|
||||
},
|
||||
descent:'\n\t\t\t\n\t\t\t',
|
||||
maximum:'\n\t\t\t\n\t\t\t',
|
||||
minimum:'\n\t\t\t\n\t\t\t',
|
||||
},
|
||||
settings:
|
||||
{
|
||||
fuel_persistent:0,
|
||||
ground_services_persistent:0,
|
||||
radio_persistent:0,
|
||||
tooltips:1,
|
||||
weight_persistent:0
|
||||
}
|
||||
},
|
||||
autopilot:
|
||||
{
|
||||
internal:{},
|
||||
locks:{},
|
||||
'route-manager':{},
|
||||
settings:{},
|
||||
'target-tracking':{},
|
||||
},
|
||||
canvas:
|
||||
{
|
||||
'by-index':
|
||||
{
|
||||
texture:
|
||||
{
|
||||
background:'rgba(0,0,0,0)',
|
||||
group:{},
|
||||
name:'Tooltip',
|
||||
placement:{},
|
||||
size:600,
|
||||
'size[1]':200,
|
||||
status:0,
|
||||
'status-msg':'OK',
|
||||
view:300,
|
||||
'view[1]':100
|
||||
},
|
||||
'texture[1]':
|
||||
{
|
||||
background:'rgba(0,0,0,0)',
|
||||
group:{},
|
||||
mipmapping:1,
|
||||
name:'SymbolCache1024x1024',
|
||||
placement:{},
|
||||
size:1024,
|
||||
'size[1]':1024,
|
||||
status:0,
|
||||
'status-msg':'OK',
|
||||
view:1024,
|
||||
'view[1]':1024
|
||||
},
|
||||
'texture[2]':
|
||||
{
|
||||
background:'rgba(0,0,0,0)',
|
||||
group:{},
|
||||
mipmapping:1,
|
||||
name:'SymbolCache1024x1024',
|
||||
placement:{},
|
||||
size:1024,
|
||||
'size[1]':1024,
|
||||
status:0,
|
||||
'status-msg':'OK',
|
||||
view:1024,
|
||||
'view[1]':1024
|
||||
},
|
||||
}
|
||||
},
|
||||
command:{},
|
||||
consumables:{},
|
||||
controls:{},
|
||||
cursor:'Aircraft/ufo/Models/cursor.ac',
|
||||
devices:{},
|
||||
earthview:{},
|
||||
engines:{},
|
||||
environment:{},
|
||||
ephemeris:{},
|
||||
fdm:{},
|
||||
gear:{},
|
||||
hazards:{},
|
||||
input:{},
|
||||
instrumentation:{},
|
||||
'local-weather':{},
|
||||
logging:{},
|
||||
models:{},
|
||||
nasal:{},
|
||||
orientation:{},
|
||||
position:{},
|
||||
rendering:{},
|
||||
scenery:{},
|
||||
sim:{},
|
||||
source:'Models',
|
||||
'surface-positions':{},
|
||||
systems:{},
|
||||
velocities:{},
|
||||
};
|
||||
|
||||
var setprop=func(prop,value)
|
||||
{
|
||||
if(type(prop)!="string")
|
||||
die("setprop: prop is not a string");
|
||||
var path=split('/',prop);
|
||||
var tmp=property_tree;
|
||||
var path_size=size(path);
|
||||
for(var i=0;i<path_size-1;i+=1)
|
||||
tmp=tmp[path[i]];
|
||||
tmp[path[path_size-1]]=value;
|
||||
return;
|
||||
}
|
||||
var getprop=func(prop)
|
||||
{
|
||||
if(type(prop)!="string")
|
||||
die("getprop: prop is not a string");
|
||||
var path=split('/',prop);
|
||||
var tmp=property_tree;
|
||||
foreach(var i;path)
|
||||
tmp=tmp[i];
|
||||
return tmp;
|
||||
}
|
||||
setprop("aircraft/icao/type",'IDG MD-11');
|
||||
|
||||
var print_prop=func(depth,prop)
|
||||
{
|
||||
var s='';
|
||||
for(var i=0;i<depth;i+=1)
|
||||
s~='| ';
|
||||
if(type(prop)!="hash")
|
||||
return;
|
||||
var m=keys(prop);
|
||||
foreach(var elem;m)
|
||||
{
|
||||
print(s,elem,':',prop[elem]);
|
||||
print_prop(depth+1,prop[elem]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
print_prop(0,property_tree);
|
||||
@@ -9,6 +9,24 @@
|
||||
# local node, there is no equivalent of the "relative path" variants
|
||||
# available in C++; just use node.getNode(path).whatever() instead.
|
||||
#
|
||||
|
||||
##
|
||||
# Utility. Turns any ghosts it finds (either solo, or in an
|
||||
# array) into Node objects.
|
||||
#
|
||||
var wrap = func(node) {
|
||||
var argtype = typeof(node);
|
||||
if(argtype == "ghost") {
|
||||
return wrapNode(node);
|
||||
} elsif(argtype == "vector") {
|
||||
var v = node;
|
||||
var n = size(v);
|
||||
for(var i=0; i<n; i+=1) { v[i] = wrapNode(v[i]); }
|
||||
return v;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
var Node = {
|
||||
getNode : func wrap(_getNode(me._g, arg)),
|
||||
getParent : func wrap(_getParent(me._g, arg)),
|
||||
@@ -166,23 +184,6 @@ var copy = func(src, dest, attr = 0) {
|
||||
if(attr) dest.setAttribute(src.getAttribute());
|
||||
}
|
||||
|
||||
##
|
||||
# Utility. Turns any ghosts it finds (either solo, or in an
|
||||
# array) into Node objects.
|
||||
#
|
||||
var wrap = func(node) {
|
||||
var argtype = typeof(node);
|
||||
if(argtype == "ghost") {
|
||||
return wrapNode(node);
|
||||
} elsif(argtype == "vector") {
|
||||
var v = node;
|
||||
var n = size(v);
|
||||
for(var i=0; i<n; i+=1) { v[i] = wrapNode(v[i]); }
|
||||
return v;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
##
|
||||
# Utility. Returns a new object with its superclass/parent set to the
|
||||
# Node object and its _g (ghost) field set to the specified object.
|
||||
|
||||
@@ -1,35 +1,40 @@
|
||||
# lib queue.nas
|
||||
var block_alloc=func()
|
||||
{
|
||||
return {elem:nil,next:nil};
|
||||
}
|
||||
# valkmjolnir 2021/3/3
|
||||
var new_queue=func()
|
||||
{
|
||||
return {next:nil};
|
||||
return {begin:nil,end:nil};
|
||||
}
|
||||
var queue_push=func(queue,elem)
|
||||
var queue_push=func(queue_head,elem)
|
||||
{
|
||||
var tmp=queue;
|
||||
while(tmp.next!=nil)
|
||||
tmp=tmp.next;
|
||||
tmp.next=block_alloc();
|
||||
tmp.next.elem=elem;
|
||||
}
|
||||
var queue_pop=func(queue)
|
||||
{
|
||||
var tmp=queue.next;
|
||||
if(tmp!=nil)
|
||||
queue.next=tmp.next;
|
||||
var new_node=
|
||||
{
|
||||
elem:elem,
|
||||
next:nil
|
||||
};
|
||||
if(queue_head.begin==nil)
|
||||
queue_head.begin=queue_head.end=new_node;
|
||||
else
|
||||
{
|
||||
queue_head.end.next=new_node;
|
||||
queue_head.end=new_node;
|
||||
}
|
||||
return;
|
||||
}
|
||||
var queue_front=func(queue)
|
||||
var queue_pop=func(queue_head)
|
||||
{
|
||||
var tmp=queue.next;
|
||||
if(tmp!=nil)
|
||||
return tmp.elem;
|
||||
var t=queue_head.begin;
|
||||
queue_head.begin=queue_head.begin.next;
|
||||
if(queue_head.begin==nil)
|
||||
queue_head.end=nil;
|
||||
return t;
|
||||
}
|
||||
var queue_front=func(queue_head)
|
||||
{
|
||||
if(queue_head.begin!=nil)
|
||||
return queue_head.begin.elem;
|
||||
return nil;
|
||||
}
|
||||
var queue_empty=func(queue)
|
||||
var queue_empty=func(queue_head)
|
||||
{
|
||||
return queue.next==nil;
|
||||
return queue_head.begin==nil;
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
# basic type
|
||||
import("lib.nas");
|
||||
nil;
|
||||
2147483647;
|
||||
0x7fffffff;
|
||||
@@ -54,7 +55,7 @@ var hash_4={
|
||||
|
||||
# function
|
||||
var func_1=func(){return 1;}
|
||||
var prt=func(x){print(x);return nil;}
|
||||
var prt=func(x){println(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);}
|
||||
@@ -72,21 +73,21 @@ 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());
|
||||
println(source['member_2']());
|
||||
println(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?
|
||||
println(func test_func()); # 1
|
||||
println(test_func()); # 1
|
||||
println(func test_func); # nothing
|
||||
println(test_func); # nothing
|
||||
println(([0,1,2,3])[1]); # 1
|
||||
println(({str:"what?"})["str"]); # what?
|
||||
println(({str:"what?"}).str); # what?
|
||||
|
||||
# lambda
|
||||
(func(x){return x>0? x:0;})(12);
|
||||
(func{print("hello world");})();
|
||||
(func{println("hello world");})();
|
||||
(((func(x){return 1.0/math.exp(x);})))(0);
|
||||
|
||||
# flexible definition & assignment
|
||||
@@ -123,4 +124,29 @@ 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;
|
||||
"123"~"456"-123456*2/2;
|
||||
|
||||
var hash={str:'hello',f:func{return me.str;}};
|
||||
var tmp_f=hash.f;
|
||||
hash=1;
|
||||
print(tmp_f());
|
||||
# undefined symbol 'me'
|
||||
# this means that
|
||||
# when generating local_scope for function f,
|
||||
# nasal_gc will not count 'me' as one reference of this hash
|
||||
|
||||
var h1={str:'hello',f:func{return me.str;}};
|
||||
var h2={str:'world',f:func{return nil;}};
|
||||
h2.f=h1.f;
|
||||
print(h2.f());
|
||||
# print 'world'
|
||||
# this means that 'me' in hash's functions
|
||||
# only points to the hash this function belongs to
|
||||
|
||||
var f1=func(){print(1);return 1;}
|
||||
var f2=func(){print(2);return 0;}
|
||||
f1() or f2();
|
||||
# print '1'
|
||||
# this means that when using 'or' or 'and',
|
||||
# if the result is clear when calculating,
|
||||
# objects behind will not be calculated
|
||||
@@ -1,3 +1,4 @@
|
||||
import("lib.nas");
|
||||
var global_value=0;
|
||||
var global_hash=
|
||||
{
|
||||
@@ -5,16 +6,16 @@ var global_hash=
|
||||
var2:2,
|
||||
var3:func(){return me.var2;}
|
||||
};
|
||||
print(global_value);
|
||||
print(global_hash.var3());
|
||||
println(global_value);
|
||||
println(global_hash.var3());
|
||||
|
||||
var func1=func()
|
||||
{
|
||||
global_value=1;
|
||||
print(global_value);
|
||||
println(global_value);
|
||||
var closure_value=1;
|
||||
var temp_value=1;
|
||||
print(temp_value);
|
||||
println(temp_value);
|
||||
return func{return closure_value;};
|
||||
}
|
||||
|
||||
@@ -23,10 +24,9 @@ var func2=func()
|
||||
for(var temp_value=0;temp_value<100;temp_value+=1)
|
||||
{
|
||||
if(temp_value<10)
|
||||
print(temp_value,"< 10");
|
||||
println(temp_value,"< 10");
|
||||
elsif(10<=temp_value and temp_value<50)
|
||||
print(temp_value,"< 50");
|
||||
temp_value=10;
|
||||
println(temp_value,"< 50");
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -41,9 +41,9 @@ var func3=func()
|
||||
};
|
||||
}
|
||||
|
||||
func1()();
|
||||
println(func1()());
|
||||
func2();
|
||||
func3()();
|
||||
println(func3()());
|
||||
|
||||
if(!global_value)
|
||||
{
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
import("lib.nas");
|
||||
var filename="";
|
||||
|
||||
filename=input();
|
||||
print(filename[0]);
|
||||
Reference in New Issue
Block a user