This commit is contained in:
Valk Richard Li 2020-01-21 16:13:06 +08:00 committed by GitHub
parent 3a234bc31c
commit 65782f4d72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 467 additions and 22 deletions

View File

@ -159,6 +159,7 @@ enum parse_error_type
error_token_in_block, // when a token should not be the begin of a statement in block
lack_semi,
lack_id,
definition_lack_id, // lack identifier
definition_lack_equal, // lack '=' when not getting ';'
@ -206,6 +207,8 @@ void print_parse_error(int error_type,int line,int error_token_type=__stack_end)
break;
case lack_semi:
std::cout<<error_info_head<<line<<": expect a \';\' at the end of the statement."<<std::endl;break;
case lack_id:
std::cout<<error_info_head<<line<<": expect an identifier here."<<std::endl;break;
case definition_lack_id:
std::cout<<error_info_head<<line<<": expect identifier(s) after \'var\'."<<std::endl;break;
case definition_lack_equal:
@ -254,7 +257,7 @@ void print_parse_error(int error_type,int line,int error_token_type=__stack_end)
std::cout<<"\' ."<<std::endl;
break;
case call_func_lack_comma:
std::cout<<error_info_head<<line<<": expect a \',\' here but get \'";
std::cout<<error_info_head<<line<<": expect a \',\' when calling a function but get \'";
print_parse_token(error_token_type);
std::cout<<"\' ."<<std::endl;
break;

View File

@ -21,6 +21,7 @@ class nasal_parse
abstract_syntax_tree& get_root();
// abstract_syntax_tree generation
bool check_multi_assignment();
bool check_comma_in_curve();
void main_generate();
void statements_block_generate(abstract_syntax_tree&);
@ -136,6 +137,25 @@ abstract_syntax_tree& nasal_parse::get_root()
return root;
}
bool nasal_parse::check_multi_assignment()
{
bool ret=false;
int cnt=0;
this->get_token();
++cnt;// get '('
this->get_token();
++cnt;
if(this_token.type==__id)
{
}
return ret;
}
bool nasal_parse::check_comma_in_curve()
{
// when generating multi_assignment
@ -537,6 +557,8 @@ abstract_syntax_tree nasal_parse::multive_calculation()
abstract_syntax_tree calc_node;
abstract_syntax_tree tmp_node;
this->get_token();
// be careful that unary calculation and assignment cannot be used together
// such as: -a=1; this is incorrect use.
if((this_token.type==__sub_operator) || (this_token.type==__nor_operator))
{
calc_node.set_node_line(this_token.line);
@ -546,7 +568,7 @@ abstract_syntax_tree nasal_parse::multive_calculation()
null_node.set_node_type(__number);
null_node.set_var_number("0");
calc_node.add_children(null_node);
calc_node.add_children(assign_calculation());
calc_node.add_children(scalar_generate());
}
else
{
@ -571,7 +593,7 @@ abstract_syntax_tree nasal_parse::multive_calculation()
null_node.set_node_type(__number);
null_node.set_var_number("0");
calc_node.add_children(null_node);
calc_node.add_children(assign_calculation());
calc_node.add_children(scalar_generate());
}
else
{
@ -676,8 +698,8 @@ abstract_syntax_tree nasal_parse::scalar_generate()
if(this_token.type==__colon)
{
scalar_para=false;
this->push_token();
this->push_token();
this->push_token();// colon
this->push_token();// identifier
while(this_token.type!=__right_curve)
{
abstract_syntax_tree special_para_node;
@ -721,10 +743,12 @@ abstract_syntax_tree nasal_parse::scalar_generate()
}
else
{
this->push_token();
this->push_token();
this->push_token();// not colon
this->push_token();// identifier
}
}
else
this->push_token();// if not identifier then push in
if(scalar_para)
while(this_token.type!=__right_curve)
{
@ -863,7 +887,7 @@ abstract_syntax_tree nasal_parse::hash_generate()
}
hash_member_node.add_children(calculation());
this->get_token();
if(this_token.type!=__comma && this_token.type!=__right_brace)
if((this_token.type!=__comma) && (this_token.type!=__right_brace))
{
++error;
print_parse_error(hash_gen_lack_end,this_token.line,this_token.type);
@ -896,7 +920,7 @@ abstract_syntax_tree nasal_parse::vector_generate()
{
vector_node.add_children(calculation());
this->get_token();
if(this_token.type!=__comma && this_token.type!=__right_bracket)
if((this_token.type!=__comma) && (this_token.type!=__right_bracket))
{
++error;
print_parse_error(vector_gen_lack_end,this_token.line,this_token.type);
@ -1096,7 +1120,9 @@ abstract_syntax_tree nasal_parse::loop_expr()
loop_main_node.set_node_type(this_token.type);
if(this_token.type==__for)
{
;
this->get_token();
if(this_token.type==__semi)
this->push_token();
}
else if(this_token.type==__while)
{
@ -1116,7 +1142,44 @@ abstract_syntax_tree nasal_parse::loop_expr()
}
else
{
;
// forindex
// foreach
this->get_token();// '('
if(this_token.type!=__left_curve)
{
++error;
print_parse_error(lack_left_curve,this_token.line,this_token.type);
}
this->get_token();// 'var'
if(this_token.type!=__var)
this->push_token();
this->get_token();// id
if(this_token.type!=__id)
{
++error;
print_parse_error(lack_id,this_token.line);
}
else
{
abstract_syntax_tree id_node;
id_node.set_node_line(this_token.line);
id_node.set_node_type(__id);
id_node.set_var_name(this_token.str);
loop_main_node.add_children(id_node);
}
this->get_token();// ';'
if(this_token.type!=__semi)
{
++error;
print_parse_error(lack_semi,this_token.line);
}
loop_main_node.add_children(scalar_generate());// get hash/vector or keys(hash/vector)
this->get_token();
if(this_token.type!=__right_curve)
{
++error;
print_parse_error(lack_right_curve,this_token.line,this_token.type);
}
}
statements_block_generate(loop_main_node);
return loop_main_node;

View File

@ -26,7 +26,6 @@
| <vector>
| <func> <id>
| <function>
| <assignment>
| '(' <calculation> ')'
| <scalar> { ('[' {<calculation> ','} ']') | ('[' <calculation> ':' [<calculation>] ']') | ('.' <id>) | ('(' {<calculation> ','} ')') | ('(' {<id> ':' <calculation> ','} ')') }
;
@ -55,13 +54,9 @@
<definition> =
<var> <id> '=' <scalar>
| <var> '(' {<id> ','} ')' '=' (<scalar> | '(' {<scalar> ','} ')')
| '(' <var> {<id> ','} ')' '=' (<scalar> | '(' {<scalar> ','} ')')
;
<forindex_loop_definition> =
<var> <id>
;
<foreach_loop_definition> =
<var> <id>
;
<assignment> =
<scalar> ('=' | '+=' | '-=' | '*=' | '/=' | '~=') <calculation>
| '(' {<scalar> ','} ')' ('=' | '+=' | '-=' | '*=' | '/=' | '~=') (<calculation> | '(' {<calculation> ','} ')')
@ -82,12 +77,12 @@
;
(* in forindex and foreach the scalar and definition cannot be lacked*)
<forindex_loop> =
<forindex> '(' <forindex_loop_definition> ';' <scalar> ')' <statement> [';']
| <forindex> '(' <forindex_loop_definition> ';' <scalar> ')' '{' {<statement> ';'} '}'
<forindex> '(' (<var> <id>)|(<id>) ';' <scalar> ')' <statement> [';']
| <forindex> '(' (<var> <id>)|(<id>) ';' <scalar> ')' '{' {<statement> ';'} '}'
;
<foreach_loop> =
<foreach> '(' <foreach_loop_definition> ';' <scalar> ')' <statement> [';']
| <foreach> '(' <foreach_loop_definition> ';' <scalar> ')' '{' {<statement> ';'} '}'
<foreach> '(' (<var> <id>)|(<id>) ';' <scalar> ')' <statement> [';']
| <foreach> '(' (<var> <id>)|(<id>) ';' <scalar> ')' '{' {<statement> ';'} '}'
;
<choose_expr> = <choose_expr_if> {<choose_expr_elsif>} [<choose_expr_else>]

View File

@ -0,0 +1,28 @@
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;
}
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;

210
version2.0/test/final.nas Normal file
View File

@ -0,0 +1,210 @@
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();

30
version2.0/test/loop.nas Normal file
View File

@ -0,0 +1,30 @@
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);
}

116
version2.0/test/scalar.nas Normal file
View File

@ -0,0 +1,116 @@
# 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,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);
# 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;