update
This commit is contained in:
parent
a723b878f0
commit
ca01383272
|
@ -41,7 +41,7 @@
|
|||
including a class named nasal_lexer
|
||||
including a string[] named lib_filename, by this way resource_file can load lib files
|
||||
including a string[] named reserve_word, it is used in lexer,when generating an identifier,nasal_lexer will check if it is a reserve word
|
||||
including a struct named token, this struct is often used in nasal_lexer
|
||||
including a struct named token, this struct is often used in nasal_lexer and nasal_parse
|
||||
including a function named is_reserve_word, checking if an identifier is a reserve word
|
||||
*/
|
||||
#include "nasal_lexer.h"
|
||||
|
|
|
@ -4,14 +4,21 @@
|
|||
class abstract_syntax_tree
|
||||
{
|
||||
private:
|
||||
// basic elements
|
||||
/*
|
||||
basic elements of ast node:
|
||||
line: this marks the generated node's line in source code
|
||||
node_type: this marks the node type
|
||||
children: store the children of this node
|
||||
*/
|
||||
int line;
|
||||
int node_type;
|
||||
std::list<abstract_syntax_tree> children;
|
||||
|
||||
// is this node is a number|string|identifier node
|
||||
// then the three elements below is of great use
|
||||
// var_name is set for __id
|
||||
/*
|
||||
var_number is used when the node_type is __number
|
||||
var_string is used when the node_type is __string
|
||||
var_name is used when the node_type is __id, __dynamic_id, call_hash
|
||||
*/
|
||||
double var_number;
|
||||
std::string var_string;
|
||||
std::string var_name;
|
||||
|
@ -23,11 +30,22 @@ class abstract_syntax_tree
|
|||
abstract_syntax_tree& operator=(const abstract_syntax_tree&);
|
||||
|
||||
/* main functions */
|
||||
// print
|
||||
/*
|
||||
print_tree is the entrance of print function
|
||||
print_tree will print the root address and call print_tree_block(1)
|
||||
print_tree_block will print the information of each node by using DFS
|
||||
*/
|
||||
void print_tree();
|
||||
void print_tree_block(const int);
|
||||
|
||||
// set
|
||||
/*
|
||||
set_clear : clear all the elements in ast node
|
||||
set_node_line : set the private:line
|
||||
set_node_type : set the private:node_type
|
||||
set_var_number: set the private:var_number
|
||||
set_var_string: set the private:var_string
|
||||
set_var_name : set the private:var_name
|
||||
*/
|
||||
void set_clear();
|
||||
void set_node_line(const int);
|
||||
void set_node_type(const int);
|
||||
|
@ -36,7 +54,13 @@ class abstract_syntax_tree
|
|||
void set_var_name(std::string);
|
||||
void add_children(abstract_syntax_tree);
|
||||
|
||||
// get
|
||||
/*
|
||||
get_node_line : get the private:line
|
||||
get_node_type : get the private:node_type
|
||||
get_var_number: get private:var_number
|
||||
get_var_string: get private:var_string
|
||||
get_var_name : get private:var_name
|
||||
*/
|
||||
int get_node_line();
|
||||
int get_node_type();
|
||||
double get_var_number();
|
||||
|
@ -44,7 +68,10 @@ class abstract_syntax_tree
|
|||
std::string get_var_name();
|
||||
std::list<abstract_syntax_tree>& get_children();
|
||||
|
||||
// merge
|
||||
/*
|
||||
merge children of another ast into this one
|
||||
used to link lib ast and source codes' ast together
|
||||
*/
|
||||
void merge_children(abstract_syntax_tree&);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef __NASAL_ENUM_H__
|
||||
#define __NASAL_ENUM_H__
|
||||
|
||||
// lexer token type is only used in nasal_lexer
|
||||
// each scanned token will be recognized as one of these below
|
||||
enum lexer_token_type
|
||||
{
|
||||
__token_reserve_word=1,
|
||||
|
@ -25,29 +27,42 @@ void print_lexer_token(int type)
|
|||
// parse_gen_type include enums for parser and ast
|
||||
enum parse_gen_type
|
||||
{
|
||||
/*
|
||||
stack end is an important flag for parse token stack to
|
||||
check if it's stack is at end
|
||||
if stack is empty,the parser will get a wrong memory space and cause SIGSEGV
|
||||
*/
|
||||
__stack_end=1,
|
||||
|
||||
// operators
|
||||
__cmp_equal,__cmp_not_equal,__cmp_less,__cmp_less_or_equal,__cmp_more,__cmp_more_or_equal,
|
||||
// == != < <= > >=
|
||||
__and_operator,__or_operator,__nor_operator,__add_operator,__sub_operator,__mul_operator,__div_operator,__link_operator,
|
||||
// and or ! + - * / ~
|
||||
__equal,__add_equal,__sub_equal,__mul_equal,__div_equal,__link_equal,
|
||||
// = += -= *= /= ~=
|
||||
// operators == != < <= > >=
|
||||
__cmp_equal,
|
||||
__cmp_not_equal,
|
||||
__cmp_less,__cmp_less_or_equal,
|
||||
__cmp_more,__cmp_more_or_equal,
|
||||
// operators and or ! + - * / ~
|
||||
__and_operator, __or_operator,__nor_operator,
|
||||
__add_operator,__sub_operator,
|
||||
__mul_operator,__div_operator,__link_operator,
|
||||
// operators = += -= *= /= ~=
|
||||
__equal,
|
||||
__add_equal,__sub_equal,
|
||||
__mul_equal,__div_equal,__link_equal,
|
||||
// operators {} [] () ; , : . ?
|
||||
__left_brace,__right_brace, // {}
|
||||
__left_bracket,__right_bracket, // []
|
||||
__left_curve,__right_curve, // ()
|
||||
__semi,__comma,__colon,__dot,__ques_mark, // ; , : . ?
|
||||
__unknown_operator,
|
||||
|
||||
// reserve words
|
||||
__var,__func,__return,__nil,
|
||||
__var,
|
||||
__func,__return,__nil,
|
||||
__if,__elsif,__else,
|
||||
__continue,__break,
|
||||
__for,__forindex,__foreach,__while,
|
||||
|
||||
// basic scalar type: number string identifier dynamic_identifier
|
||||
__number,__string,__id,__dynamic_id,
|
||||
// basic scalar type: number string
|
||||
__number,__string,
|
||||
// basic identifier type: identifier dynamic_identifier
|
||||
__id,__dynamic_id,
|
||||
|
||||
// abstract_syntax_tree type below
|
||||
// abstract_syntax_tree also uses the types above, such as operators
|
||||
|
@ -62,6 +77,7 @@ enum parse_gen_type
|
|||
__definition,
|
||||
__conditional
|
||||
};
|
||||
// print tokens that used in nasal_parse
|
||||
void print_parse_token(int type)
|
||||
{
|
||||
std::string context="";
|
||||
|
@ -130,6 +146,7 @@ void print_parse_token(int type)
|
|||
std::cout<<context;
|
||||
return;
|
||||
}
|
||||
// print node types that used in abstract_syntax_tree
|
||||
void print_ast_type(int type)
|
||||
{
|
||||
std::string context="";
|
||||
|
@ -204,6 +221,7 @@ void print_ast_type(int type)
|
|||
return;
|
||||
}
|
||||
|
||||
// basic scalar type used in nasal_runtime and nasal_gc
|
||||
enum scalar_type
|
||||
{
|
||||
scalar_nil=0,
|
||||
|
@ -213,6 +231,7 @@ enum scalar_type
|
|||
scalar_hash,
|
||||
scalar_function
|
||||
};
|
||||
// print types that used in nasal_runtime and nasal_gc
|
||||
void print_scalar_type(const int type)
|
||||
{
|
||||
switch(type)
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
/*
|
||||
__token_reserve_word:
|
||||
for,foreach,forindex,while : loop
|
||||
var,func : definition
|
||||
break,continue : in loop
|
||||
return : in function
|
||||
if,else,elsif : if-else statement
|
||||
and,or : calculation
|
||||
nil : special type
|
||||
var,func : definition
|
||||
break,continue : in loop
|
||||
return : in function
|
||||
if,else,elsif : conditional expr
|
||||
and,or : calculation
|
||||
nil : special type
|
||||
__token_identifier:
|
||||
must begin with '_' or 'a'~'z' or 'A'~'Z'
|
||||
can include '_' or 'a'~'z' or 'A'~'Z' or '0'~'9'
|
||||
|
@ -27,11 +27,13 @@
|
|||
__token_operator:
|
||||
! + - * / ~
|
||||
= += -= *= /= ~=
|
||||
== != > >= < <= ('and' 'or' are operators too but they are recognized as operator in generate_detail_token())
|
||||
== != > >= < <=
|
||||
('and' 'or' are operators too but they are recognized as operator in generate_detail_token())
|
||||
() [] {} ; , . : ?
|
||||
others: __unknown_operator
|
||||
*/
|
||||
|
||||
/* filenames of lib files */
|
||||
const std::string lib_filename[10]=
|
||||
{
|
||||
"lib/base.nas",
|
||||
|
@ -45,14 +47,14 @@ const std::string lib_filename[10]=
|
|||
"lib/unix.nas",
|
||||
"lib/utf8.nas"
|
||||
};
|
||||
|
||||
/* reserve words */
|
||||
std::string reserve_word[15]=
|
||||
{
|
||||
"for","foreach","forindex","while",
|
||||
"var","func","break","continue","return",
|
||||
"if","else","elsif","and","or","nil"
|
||||
};
|
||||
|
||||
/* check if an identifier is a reserve word */
|
||||
int is_reserve_word(std::string str)
|
||||
{
|
||||
for(int i=0;i<15;++i)
|
||||
|
@ -67,13 +69,11 @@ class resource_file
|
|||
std::list<char> resource;
|
||||
public:
|
||||
/*
|
||||
resource_file();
|
||||
~resource_file();
|
||||
void delete_all_source();
|
||||
void input_file(std::string);
|
||||
void load_lib_file();
|
||||
std::list<char>& get_source();
|
||||
void print_resource();
|
||||
delete_all_source: clear all the source codes in std::list<char> resource
|
||||
input_file : input source codes by filenames
|
||||
load_lib_file : input lib source codes
|
||||
get_source : get the std::list<char> resource
|
||||
print_resource : print source codes
|
||||
*/
|
||||
resource_file()
|
||||
{
|
||||
|
@ -157,7 +157,7 @@ class resource_file
|
|||
return;
|
||||
}
|
||||
};
|
||||
|
||||
/* struct token: mainly used in nasal_lexer and nasal_parse*/
|
||||
struct token
|
||||
{
|
||||
int line;
|
||||
|
@ -178,25 +178,27 @@ class nasal_lexer
|
|||
std::list<token> token_list;
|
||||
std::list<token> detail_token_list;
|
||||
int error;
|
||||
// change utf8 codes into '?'
|
||||
// this function will be deleted if there is a way to print utf8 codes out correctly
|
||||
std::string utf8_clear(std::string tmp)
|
||||
{
|
||||
/*
|
||||
0xxx xxxx 0x0 1 byte
|
||||
110x xxxx 0xc0 2 byte
|
||||
1110 xxxx 0xe0 3 byte
|
||||
1111 0xxx 0xf0 4 byte
|
||||
1111 10xx 0xf8 5 byte
|
||||
1111 110x 0xfc 6 byte
|
||||
bytes after it is:
|
||||
10xx xxxx 0x80
|
||||
|
||||
so utf-8 format is:
|
||||
0xxxxxxx
|
||||
110xxxxx 10xxxxxx
|
||||
1110xxxx 10xxxxxx 10xxxxxx
|
||||
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
0xxx xxxx 0x0 1 byte
|
||||
110x xxxx 0xc0 2 byte
|
||||
1110 xxxx 0xe0 3 byte
|
||||
1111 0xxx 0xf0 4 byte
|
||||
1111 10xx 0xf8 5 byte
|
||||
1111 110x 0xfc 6 byte
|
||||
bytes after it is:
|
||||
10xx xxxx 0x80
|
||||
|
||||
so utf-8 format is:
|
||||
0xxxxxxx
|
||||
110xxxxx 10xxxxxx
|
||||
1110xxxx 10xxxxxx 10xxxxxx
|
||||
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
*/
|
||||
unsigned char utf8head[6]={0x0,0xc0,0xe0,0xf0,0xf8,0xfc};
|
||||
std::string ret="";
|
||||
|
@ -222,13 +224,11 @@ class nasal_lexer
|
|||
}
|
||||
public:
|
||||
/*
|
||||
nasal_lexer();
|
||||
~nasal_lexer();
|
||||
void print_token_list();
|
||||
void scanner(std::list<char>&);
|
||||
void generate_detail_token();
|
||||
int get_error();
|
||||
std::list<token>& get_detail_token();
|
||||
print_token_list : print generated token list
|
||||
scanner : scan the source codes and generate tokens
|
||||
generate_detail_token: recognize and change token types to detailed types that can be processed by nasal_parse
|
||||
get_error : get the number of errors that occurred when generating tokens
|
||||
get_detail_token : output the detailed tokens,must be used after generate_detail_token()
|
||||
*/
|
||||
nasal_lexer()
|
||||
{
|
||||
|
|
|
@ -1,6 +1,18 @@
|
|||
#ifndef __NASAL_MISC_H__
|
||||
#define __NASAL_MISC_H__
|
||||
|
||||
/*
|
||||
check_numerable_string:
|
||||
check if a string can be converted to a number
|
||||
|
||||
strings like these below is correct:
|
||||
'0.00012'
|
||||
'12314.234'
|
||||
'1234'
|
||||
'0xdeadbeef'
|
||||
'0xDEADBEEF'
|
||||
'0o71230'
|
||||
*/
|
||||
bool check_numerable_string(std::string str)
|
||||
{
|
||||
if(str.length()>1 && str[0]=='-')
|
||||
|
@ -49,6 +61,10 @@ bool check_numerable_string(std::string str)
|
|||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
trans_string_to_number:
|
||||
convert string to number
|
||||
*/
|
||||
double trans_string_to_number(std::string str)
|
||||
{
|
||||
bool is_negative=false;
|
||||
|
@ -120,6 +136,10 @@ double trans_string_to_number(std::string str)
|
|||
return trans_str_number;
|
||||
}
|
||||
|
||||
/*
|
||||
trans_number_to_string:
|
||||
convert number to string
|
||||
*/
|
||||
std::string trans_number_to_string(double number)
|
||||
{
|
||||
std::string trans_num_string="";
|
||||
|
@ -149,9 +169,12 @@ std::string trans_number_to_string(double number)
|
|||
return trans_num_string;
|
||||
}
|
||||
|
||||
/*
|
||||
prt_hex:
|
||||
transform int to hex format and print it out (std::cout)
|
||||
*/
|
||||
void prt_hex(const int ptr)
|
||||
{
|
||||
// transform int to hex and print it (std::cout)
|
||||
char hex[9];
|
||||
hex[8]=0;
|
||||
int tmp_plc=ptr;
|
||||
|
@ -162,6 +185,26 @@ void prt_hex(const int ptr)
|
|||
}
|
||||
else
|
||||
std::cout<<"0x";
|
||||
/*
|
||||
int: 00000000 00000000 00000000 00000000
|
||||
int: 0x00 00 00 00
|
||||
example:
|
||||
a=0x13 57 9b df
|
||||
a=00010011 01010111 10011011 11011111
|
||||
a & 0x00 00 00 0f:
|
||||
00010011 01010111 10011011 11011111
|
||||
and 00000000 00000000 00000000 00001111
|
||||
---------------------------------------
|
||||
00000000 00000000 00000000 00001111
|
||||
a>>=4:
|
||||
00000001 00110101 01111001 10111101
|
||||
a & 0x00 00 00 0f
|
||||
00000001 00110101 01111001 10111101
|
||||
and 00000000 00000000 00000000 00001111
|
||||
---------------------------------------
|
||||
00000000 00000000 00000000 00001101
|
||||
then convert 0~15 to 0~9 a~f
|
||||
*/
|
||||
for(int j=7;j>=0;--j)
|
||||
{
|
||||
int tmp=(tmp_plc & 0x0000000f);
|
||||
|
|
|
@ -4,11 +4,19 @@
|
|||
class nasal_parse
|
||||
{
|
||||
private:
|
||||
/*
|
||||
parse_token_stream: get detailed tokens from lexer and store them in this stack
|
||||
checked_tokens : checked tokens will be stored here
|
||||
this_token : changed by function get_token and push_token,and used when generating ast
|
||||
error : record the number of errors occurred when generating ast
|
||||
root : after generating process, the ast will be stored in root
|
||||
*/
|
||||
std::stack<token> parse_token_stream;
|
||||
std::stack<token> checked_tokens;
|
||||
token this_token;
|
||||
int error;
|
||||
abstract_syntax_tree root;
|
||||
/* parsse_error_type: used in print_parse_error,including all types of errors*/
|
||||
enum parse_error_type
|
||||
{
|
||||
parse_unknown_error=0, // unknown error
|
||||
|
@ -52,33 +60,36 @@ class nasal_parse
|
|||
|
||||
ternary_operator_lack_colon, // lack ':'
|
||||
};
|
||||
/* print the error type and it's line*/
|
||||
void print_parse_error(int,int,int);
|
||||
// most important function of parser
|
||||
// these two functions are used to get and push token
|
||||
// by using them,parser can generate ast
|
||||
/*
|
||||
get_token and push_token are most important functions of parser
|
||||
these two functions are used to get and push token
|
||||
and the result will be stored in this_token
|
||||
*/
|
||||
void get_token();
|
||||
void push_token();
|
||||
// block statements generation
|
||||
/* block statements generation */
|
||||
abstract_syntax_tree block_generate();
|
||||
// check ';'
|
||||
void check_semi();
|
||||
// check '(' confliction
|
||||
bool check_multi_assignment();// check multi_call_id '=' multi_scalar
|
||||
bool check_multi_scalar(); // check multi_scalar
|
||||
bool check_var_in_curve(); // check multi_definition: (var id,id,id)
|
||||
bool check_function_end(abstract_syntax_tree&); // check end of definition or '=' is a function
|
||||
/* check '(' confliction */
|
||||
bool check_multi_assignment(); // check multi_call_id '=' multi_scalar
|
||||
bool check_multi_scalar(); // check multi_scalar
|
||||
bool check_var_in_curve(); // check multi_definition: (var id,id,id)
|
||||
bool check_function_end(abstract_syntax_tree&); // check end of definition or '=' is a function
|
||||
/*
|
||||
calculation() will get elements generated by and_calculation()
|
||||
and_calculation() will get elements generated by or_calculation()
|
||||
or_calculation() will get elements generated by cmp_calculation()
|
||||
cmp_calculation() will get elements generated by additive_calculation()
|
||||
additive_calculation() will get elements generated by multive_calculation()
|
||||
multive_calculation() will get elements generated by assign_calculation()(assignment <call_id> '=' <calculation>) and scalar_generate()
|
||||
assign_calculation() get elements from scalar_generate()
|
||||
please notice that:
|
||||
if the elements begin with '!' or '-',multive_calculation() gets them from scalar_generate()
|
||||
if not,multive_calculation() gets them from assign_calculation()
|
||||
because '!' and '-' cannot be used with assignment together such as: -a=1
|
||||
calculation : will get elements generated by and_calculation()
|
||||
and_calculation : will get elements generated by or_calculation()
|
||||
or_calculation : will get elements generated by cmp_calculation()
|
||||
cmp_calculation : will get elements generated by additive_calculation()
|
||||
additive_calculation: will get elements generated by multive_calculation()
|
||||
multive_calculation : will get elements generated by assign_calculation()(assignment <call_id> '=' <calculation>) and scalar_generate()
|
||||
assign_calculation : get elements from scalar_generate()
|
||||
please notice that:
|
||||
if the elements begin with '!' or '-',multive_calculation() gets them from scalar_generate()
|
||||
if not,multive_calculation() gets them from assign_calculation()
|
||||
because '!' and '-' cannot be used with assignment together such as: -a=1
|
||||
*/
|
||||
abstract_syntax_tree calculation();
|
||||
abstract_syntax_tree and_calculation();
|
||||
|
@ -87,13 +98,13 @@ class nasal_parse
|
|||
abstract_syntax_tree additive_calculation();
|
||||
abstract_syntax_tree multive_calculation();
|
||||
abstract_syntax_tree scalar_generate();
|
||||
// normal data type generation
|
||||
/* normal data type generation */
|
||||
abstract_syntax_tree hash_generate();
|
||||
abstract_syntax_tree vector_generate();
|
||||
abstract_syntax_tree function_generate();
|
||||
// return_expr() generates ebnf: <return> [<calculation>] ';'
|
||||
/* return_expr() generates ebnf: <return> [<calculation>] ';' */
|
||||
abstract_syntax_tree return_expr();
|
||||
// normal expressions
|
||||
/* normal expressions */
|
||||
abstract_syntax_tree multi_scalar_assignment();
|
||||
abstract_syntax_tree definition();
|
||||
abstract_syntax_tree loop_expr();
|
||||
|
@ -102,7 +113,7 @@ class nasal_parse
|
|||
// basic functions
|
||||
void delete_all_elements()
|
||||
{
|
||||
// used in 'del' command
|
||||
// used in 'del' command in main()
|
||||
while(!parse_token_stream.empty())
|
||||
parse_token_stream.pop();
|
||||
while(!checked_tokens.empty())
|
||||
|
@ -114,8 +125,7 @@ class nasal_parse
|
|||
void get_token_list(std::list<token>&);
|
||||
int get_error();
|
||||
abstract_syntax_tree& get_root();
|
||||
// abstract_syntax_tree generation
|
||||
// main process of parser
|
||||
/* main process of parser */
|
||||
void main_generate();
|
||||
};
|
||||
|
||||
|
@ -126,6 +136,7 @@ void nasal_parse::print_detail_token()
|
|||
std::stack<token> tmp=parse_token_stream;
|
||||
// indent
|
||||
std::string indent="";
|
||||
int brace_cnt=0;
|
||||
int line=1;
|
||||
std::cout<<line<<"\t";
|
||||
while((!tmp.empty()) && (tmp.top().type!=__stack_end))
|
||||
|
@ -133,6 +144,7 @@ void nasal_parse::print_detail_token()
|
|||
if(tmp.top().line!=line)
|
||||
{
|
||||
// if line changes,print '\n' and number of line
|
||||
// by using this loop,empty line will also be output
|
||||
for(int i=line+1;i<tmp.top().line;++i)
|
||||
std::cout<<std::endl<<i<<"\t";
|
||||
line=tmp.top().line;
|
||||
|
@ -140,9 +152,14 @@ void nasal_parse::print_detail_token()
|
|||
}
|
||||
print_parse_token(tmp.top().type);
|
||||
if(tmp.top().type==__left_brace)
|
||||
{
|
||||
++brace_cnt;
|
||||
indent+=' ';
|
||||
}
|
||||
else if(tmp.top().type==__right_brace)
|
||||
--brace_cnt;
|
||||
tmp.pop();
|
||||
if((!tmp.empty()) && (tmp.top().type==__right_brace))
|
||||
if((!tmp.empty()) && (tmp.top().type==__right_brace) && brace_cnt>=1)
|
||||
indent.pop_back();
|
||||
}
|
||||
std::cout<<std::endl;
|
||||
|
@ -394,8 +411,7 @@ bool nasal_parse::check_multi_assignment()
|
|||
this->get_token();
|
||||
++cnt;
|
||||
// these determine statements are used with curve_cnt,bracket_cnt and brace_cnt together
|
||||
// to avoid checking commas in other curves/brackets/braces
|
||||
// such as ([0,1,2,3])
|
||||
// to avoid checking commas in other curves/brackets/braces such as ([0,1,2,3])
|
||||
// but in multi_assignment, only things like (id[scalar],id.id[scalar]) can be recognized as multi_scalar
|
||||
// if ([0,1,2,3]) and i don't use these judgements,then ([0,1,2,3]) will be recognized as multi_scalar
|
||||
// but in fact ([0,1,2,3]) is not
|
||||
|
@ -406,13 +422,16 @@ bool nasal_parse::check_multi_assignment()
|
|||
if(this_token.type==__right_bracket)--bracket_cnt;
|
||||
if(this_token.type==__right_brace) --brace_cnt;
|
||||
|
||||
// if curves,brackets,braces are in pairs and this_token is comma,it is really multi_id calls
|
||||
if(!curve_cnt && !bracket_cnt && !brace_cnt && this_token.type==__comma)
|
||||
{
|
||||
ret=true;
|
||||
break;
|
||||
}
|
||||
if(!curve_cnt && !bracket_cnt && brace_cnt<0)
|
||||
// error occurred
|
||||
if(curve_cnt<0 || brace_cnt<0 || brace_cnt<0)
|
||||
break;
|
||||
// exit when meeting stack end
|
||||
if((!parse_token_stream.empty() && parse_token_stream.top().type==__stack_end) || (this_token.type==__semi))
|
||||
break;
|
||||
}
|
||||
|
@ -446,13 +465,16 @@ bool nasal_parse::check_multi_scalar()
|
|||
if(this_token.type==__right_bracket)--bracket_cnt;
|
||||
if(this_token.type==__right_brace) --brace_cnt;
|
||||
|
||||
// if curves,brackets,braces are in pairs and this_token is comma,it is really multi_scalar
|
||||
if(!curve_cnt && !bracket_cnt && !brace_cnt && this_token.type==__comma)
|
||||
{
|
||||
ret=true;
|
||||
break;
|
||||
}
|
||||
if(!curve_cnt && !bracket_cnt && brace_cnt<0)
|
||||
// error occurred
|
||||
if(curve_cnt<0 || brace_cnt<0 || brace_cnt<0)
|
||||
break;
|
||||
// exit when meeting stack end
|
||||
if((!parse_token_stream.empty() && parse_token_stream.top().type==__stack_end) || (this_token.type==__semi))
|
||||
break;
|
||||
}
|
||||
|
@ -575,8 +597,7 @@ abstract_syntax_tree nasal_parse::block_generate()
|
|||
block_node.set_node_type(__normal_statement_block);
|
||||
if(this_token.type!=__left_brace)
|
||||
{
|
||||
// only one statement
|
||||
// so this doesn't need check_semi()
|
||||
// only one statement, so this doesn't need check_semi()
|
||||
switch(this_token.type)
|
||||
{
|
||||
case __var:
|
||||
|
@ -629,6 +650,8 @@ abstract_syntax_tree nasal_parse::block_generate()
|
|||
print_parse_error(error_token_in_block,this_token.line,this_token.type);
|
||||
break;
|
||||
}
|
||||
// thought don't need to check semi at end, a statement having a semi at its end is also right
|
||||
// this statement is used to check statement having a semi at its end
|
||||
this->get_token();
|
||||
if(this_token.type!=__semi)
|
||||
this->push_token();
|
||||
|
@ -702,8 +725,8 @@ abstract_syntax_tree nasal_parse::block_generate()
|
|||
print_parse_error(error_token_in_block,this_token.line,this_token.type);
|
||||
break;
|
||||
}
|
||||
// why the last statement can avoid semi check()?
|
||||
// see more details in function: check_semi()
|
||||
// the last statement can avoid semi check althought need_semi_check is true
|
||||
// because check_semi will scan the next token,if this token is '}',then semi_check can be avoided
|
||||
if(need_semi_check)
|
||||
check_semi();
|
||||
this->get_token();
|
||||
|
|
|
@ -82,6 +82,7 @@ class nasal_runtime
|
|||
__special_call_vector_too_large_value,
|
||||
__normal_call_vector_too_large_value,
|
||||
__function_returned_value_be_assigned,
|
||||
__subvec_value_be_assigned,
|
||||
__call_function_lack_para,
|
||||
__forindex_foreach_not_vector,
|
||||
__break_not_used_in_loop,
|
||||
|
@ -165,7 +166,9 @@ void nasal_runtime::error_interrupt(const int type,const int line)
|
|||
case __normal_call_vector_too_large_value:
|
||||
std::cout<<"the number used to call the vector is too large(over 0x7fffffff)."<<std::endl;break;
|
||||
case __function_returned_value_be_assigned:
|
||||
std::cout<<"cannot assigned a value that function returns."<<std::endl;break;
|
||||
std::cout<<"cannot assign a value that function returns."<<std::endl;break;
|
||||
case __subvec_value_be_assigned:
|
||||
std::cout<<"cannot assign a subvec value."<<std::endl;break;
|
||||
case __call_function_lack_para:
|
||||
std::cout<<"lack parameter(s) when calling a function."<<std::endl;break;
|
||||
case __forindex_foreach_not_vector:
|
||||
|
@ -1863,8 +1866,7 @@ int nasal_runtime::assignment(std::list<std::map<std::string,int> >& local_scope
|
|||
assigned_addr=&((*iter)[tmp_id_name]);
|
||||
if(!assigned_addr)
|
||||
return -1;
|
||||
int assigned_value_addr=*assigned_addr;
|
||||
nasal_gc.reference_add(*assigned_addr);
|
||||
std::vector<int> tmp_subvec_addr;
|
||||
for(std::list<abstract_syntax_tree>::iterator iter=node.get_children().begin();iter!=node.get_children().end();++iter)
|
||||
{
|
||||
// call vector/special call hash/subvec
|
||||
|
@ -1872,7 +1874,7 @@ int nasal_runtime::assignment(std::list<std::map<std::string,int> >& local_scope
|
|||
if(iter->get_node_type()==__call_vector)
|
||||
{
|
||||
// check the scalar type of called identifier here
|
||||
int called_type=nasal_gc.get_scalar(assigned_value_addr).get_type();
|
||||
int called_type=nasal_gc.get_scalar(*assigned_addr).get_type();
|
||||
if(called_type!=scalar_vector && called_type!=scalar_hash)
|
||||
{
|
||||
error_interrupt(__error_value_type,iter->get_node_line());
|
||||
|
@ -1971,7 +1973,7 @@ int nasal_runtime::assignment(std::list<std::map<std::string,int> >& local_scope
|
|||
int begin_num=(int)nasal_gc.get_scalar(num1_addr).get_number().get_number();
|
||||
int end_num=0;
|
||||
if(num2_addr<0 || nasal_gc.get_scalar(num2_addr).get_type()==scalar_nil)
|
||||
end_num=nasal_gc.get_scalar(assigned_value_addr).get_vector().get_size();
|
||||
end_num=nasal_gc.get_scalar(*assigned_addr).get_vector().get_size();
|
||||
else
|
||||
end_num=(int)nasal_gc.get_scalar(num2_addr).get_number().get_number();
|
||||
if(num1_addr>=0)
|
||||
|
@ -1982,7 +1984,7 @@ int nasal_runtime::assignment(std::list<std::map<std::string,int> >& local_scope
|
|||
for(int i=begin_num;i<end_num;++i)
|
||||
{
|
||||
// addr used here
|
||||
int tmp_data_addr=nasal_gc.get_scalar(assigned_value_addr).get_vector().get_elem(i);
|
||||
int tmp_data_addr=nasal_gc.get_scalar(*assigned_addr).get_vector().get_elem(i);
|
||||
int new_addr=-1;
|
||||
if(tmp_data_addr<0)
|
||||
{
|
||||
|
@ -2019,12 +2021,11 @@ int nasal_runtime::assignment(std::list<std::map<std::string,int> >& local_scope
|
|||
nasal_gc.reference_delete(tmp_data_addr);
|
||||
subvec_result.push_back(new_addr);
|
||||
}
|
||||
int tmp_addr=assigned_value_addr;
|
||||
assigned_value_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(assigned_value_addr).set_type(scalar_vector);
|
||||
int tmp_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(tmp_addr).set_type(scalar_vector);
|
||||
for(int i=0;i<subvec_result.size();++i)
|
||||
nasal_gc.get_scalar(assigned_value_addr).get_vector().vec_push(subvec_result[i]);
|
||||
nasal_gc.reference_delete(tmp_addr);
|
||||
nasal_gc.get_scalar(tmp_addr).get_vector().vec_push(subvec_result[i]);
|
||||
tmp_subvec_addr.push_back(tmp_addr);
|
||||
assigned_addr=NULL;
|
||||
}// end sub-vector
|
||||
else
|
||||
|
@ -2058,16 +2059,12 @@ int nasal_runtime::assignment(std::list<std::map<std::string,int> >& local_scope
|
|||
error_interrupt(__normal_call_vector_too_large_value,iter->get_children().front().get_node_line());
|
||||
return -1;
|
||||
}
|
||||
int tmp_addr=assigned_value_addr;
|
||||
assigned_addr=nasal_gc.get_scalar(tmp_addr).get_vector().get_elem_addr((int)place_num);
|
||||
assigned_addr=nasal_gc.get_scalar(*assigned_addr).get_vector().get_elem_addr((int)place_num);
|
||||
if(!assigned_addr)
|
||||
{
|
||||
error_interrupt(__invalid_vector_member,iter->get_children().front().get_children().front().get_node_line());
|
||||
return -1;
|
||||
}
|
||||
assigned_value_addr=*assigned_addr;
|
||||
nasal_gc.reference_add(assigned_value_addr);
|
||||
nasal_gc.reference_delete(tmp_addr);
|
||||
}
|
||||
else if(called_type==scalar_hash)
|
||||
{
|
||||
|
@ -2076,16 +2073,12 @@ int nasal_runtime::assignment(std::list<std::map<std::string,int> >& local_scope
|
|||
error_interrupt(__error_value_type_when_calling_hash,iter->get_children().front().get_node_line());
|
||||
return -1;
|
||||
}
|
||||
int tmp_addr=assigned_value_addr;
|
||||
assigned_addr=nasal_gc.get_scalar(tmp_addr).get_hash().get_hash_member_addr(nasal_gc.get_scalar(data_addr).get_string().get_string());
|
||||
assigned_addr=nasal_gc.get_scalar(*assigned_addr).get_hash().get_hash_member_addr(nasal_gc.get_scalar(data_addr).get_string().get_string());
|
||||
if(!assigned_addr)
|
||||
{
|
||||
error_interrupt(__invalid_hash_member,iter->get_children().front().get_node_line());
|
||||
return -1;
|
||||
}
|
||||
assigned_value_addr=*assigned_addr;
|
||||
nasal_gc.reference_add(assigned_value_addr);
|
||||
nasal_gc.reference_delete(tmp_addr);
|
||||
}
|
||||
nasal_gc.reference_delete(tmp_data_addr);
|
||||
}
|
||||
|
@ -2093,21 +2086,17 @@ int nasal_runtime::assignment(std::list<std::map<std::string,int> >& local_scope
|
|||
// call hash identifier.identifier
|
||||
else if(iter->get_node_type()==__call_hash)
|
||||
{
|
||||
if(nasal_gc.get_scalar(assigned_value_addr).get_type()!=scalar_hash)
|
||||
if(nasal_gc.get_scalar(*assigned_addr).get_type()!=scalar_hash)
|
||||
{
|
||||
error_interrupt(__not_callable_hash,iter->get_node_line());
|
||||
return -1;
|
||||
}
|
||||
int tmp_addr=assigned_value_addr;
|
||||
assigned_addr=nasal_gc.get_scalar(assigned_value_addr).get_hash().get_hash_member_addr(iter->get_var_name());
|
||||
assigned_addr=nasal_gc.get_scalar(*assigned_addr).get_hash().get_hash_member_addr(iter->get_var_name());
|
||||
if(!assigned_addr)
|
||||
{
|
||||
error_interrupt(__invalid_hash_member,iter->get_node_line());
|
||||
return -1;
|
||||
}
|
||||
assigned_value_addr=*assigned_addr;
|
||||
nasal_gc.reference_add(assigned_value_addr);
|
||||
nasal_gc.reference_delete(tmp_addr);
|
||||
}// end call hash
|
||||
// call function identifier(...)
|
||||
else if(iter->get_node_type()==__call_function)
|
||||
|
@ -2116,34 +2105,56 @@ int nasal_runtime::assignment(std::list<std::map<std::string,int> >& local_scope
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
switch(nasal_gc.get_scalar(data_addr).get_type())
|
||||
nasal_gc.reference_delete(*assigned_addr);
|
||||
if(assigned_addr)
|
||||
{
|
||||
case scalar_nil:
|
||||
*assigned_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(*assigned_addr).set_type(scalar_nil);
|
||||
break;
|
||||
case scalar_number:
|
||||
*assigned_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(*assigned_addr).set_type(scalar_number);
|
||||
nasal_gc.get_scalar(*assigned_addr).get_number().deep_copy(nasal_gc.get_scalar(data_addr).get_number());
|
||||
break;
|
||||
case scalar_string:
|
||||
*assigned_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(*assigned_addr).set_type(scalar_string);
|
||||
nasal_gc.get_scalar(*assigned_addr).get_string().deep_copy(nasal_gc.get_scalar(data_addr).get_string());
|
||||
break;
|
||||
case scalar_function:
|
||||
*assigned_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(*assigned_addr).set_type(scalar_function);
|
||||
nasal_gc.get_scalar(*assigned_addr).get_function().deep_copy(nasal_gc.get_scalar(data_addr).get_function());
|
||||
break;
|
||||
case scalar_vector:
|
||||
case scalar_hash:
|
||||
*assigned_addr=data_addr;
|
||||
nasal_gc.reference_add(data_addr);
|
||||
break;
|
||||
switch(nasal_gc.get_scalar(data_addr).get_type())
|
||||
{
|
||||
case scalar_nil:
|
||||
*assigned_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(*assigned_addr).set_type(scalar_nil);
|
||||
break;
|
||||
case scalar_number:
|
||||
*assigned_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(*assigned_addr).set_type(scalar_number);
|
||||
nasal_gc.get_scalar(*assigned_addr).get_number().deep_copy(nasal_gc.get_scalar(data_addr).get_number());
|
||||
break;
|
||||
case scalar_string:
|
||||
*assigned_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(*assigned_addr).set_type(scalar_string);
|
||||
nasal_gc.get_scalar(*assigned_addr).get_string().deep_copy(nasal_gc.get_scalar(data_addr).get_string());
|
||||
break;
|
||||
case scalar_function:
|
||||
*assigned_addr=nasal_gc.gc_alloc();
|
||||
nasal_gc.get_scalar(*assigned_addr).set_type(scalar_function);
|
||||
nasal_gc.get_scalar(*assigned_addr).get_function().deep_copy(nasal_gc.get_scalar(data_addr).get_function());
|
||||
break;
|
||||
case scalar_vector:
|
||||
case scalar_hash:
|
||||
*assigned_addr=data_addr;
|
||||
nasal_gc.reference_add(data_addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error_interrupt(__subvec_value_be_assigned,node.get_children().back().get_node_line());
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
assigned_addr=find_address()
|
||||
while(children.size())
|
||||
{
|
||||
assigned_addr=new_addr()
|
||||
}
|
||||
*assigned_addr->refcnt--
|
||||
*assigned_addr=new_value_addr
|
||||
*/
|
||||
// data_addr is only a parameter here,and it's refcnt has not been changed when using it here
|
||||
nasal_gc.reference_add(*assigned_addr);
|
||||
for(int i=0;i<tmp_subvec_addr.size();++i)
|
||||
nasal_gc.reference_delete(tmp_subvec_addr[i]);
|
||||
return *assigned_addr;
|
||||
}
|
||||
int nasal_runtime::call_identifier(std::list<std::map<std::string,int> >& local_scope,abstract_syntax_tree& node)
|
||||
|
@ -2870,8 +2881,8 @@ int nasal_runtime::block_proc(std::list<std::map<std::string,int> >& local_scope
|
|||
return state;
|
||||
}
|
||||
int nasal_runtime::func_proc(
|
||||
std::list<std::map<std::string,int> >& parameters_assist_scope,// scope that used to generate parameters
|
||||
std::list<std::map<std::string,int> >& local_scope,// running scope,often gets the scope that calls it
|
||||
std::list<std::map<std::string,int> >& function_scope,// running scope,often gets the scope that has been recorded in nasal function
|
||||
abstract_syntax_tree& parameter_list, // parameter list format of nasal function
|
||||
abstract_syntax_tree& func_root, // main runnning block of nasal function
|
||||
abstract_syntax_tree& input_parameters, // input parameters when calling this nasal function
|
||||
|
@ -2881,12 +2892,7 @@ int nasal_runtime::func_proc(
|
|||
function_returned_addr=-1;
|
||||
std::map<std::string,int> new_scope;
|
||||
local_scope.push_back(new_scope);
|
||||
for(std::list<std::map<std::string,int> >::iterator i=function_scope.begin();i!=function_scope.end();++i)
|
||||
for(std::map<std::string,int>::iterator j=i->begin();j!=i->end();++j)
|
||||
{
|
||||
local_scope.back()[j->first]=j->second;
|
||||
nasal_gc.reference_delete(j->second);
|
||||
}
|
||||
|
||||
if(called_hash_addr>=0)
|
||||
local_scope.back()["me"]=called_hash_addr;
|
||||
// loading parameters
|
||||
|
@ -2904,7 +2910,7 @@ int nasal_runtime::func_proc(
|
|||
else if(iter->get_node_type()==__default_parameter)
|
||||
{
|
||||
para_name_list.push_back(iter->get_children().front().get_var_name());
|
||||
int default_val_addr=calculation(local_scope,iter->get_children().back());
|
||||
int default_val_addr=calculation(parameters_assist_scope,iter->get_children().back());
|
||||
if(default_val_addr<0)
|
||||
return -1;
|
||||
local_scope.back()[para_name_list.back()]=default_val_addr;
|
||||
|
@ -2925,7 +2931,7 @@ int nasal_runtime::func_proc(
|
|||
{
|
||||
if(has_dynamic_id)
|
||||
{
|
||||
int val_addr=calculation(local_scope,*iter);
|
||||
int val_addr=calculation(parameters_assist_scope,*iter);
|
||||
if(val_addr<0)
|
||||
return -1;
|
||||
nasal_gc.get_scalar(dynamic_args).get_vector().vec_push(val_addr);
|
||||
|
@ -2935,7 +2941,7 @@ int nasal_runtime::func_proc(
|
|||
}
|
||||
else
|
||||
{
|
||||
int val_addr=calculation(local_scope,*iter);
|
||||
int val_addr=calculation(parameters_assist_scope,*iter);
|
||||
if(val_addr<0)
|
||||
return -1;
|
||||
if(local_scope.back()[para_name_list[tmp_ptr]]<0)
|
||||
|
@ -2956,7 +2962,7 @@ int nasal_runtime::func_proc(
|
|||
std::string tmp_para_name=iter->get_children().front().get_var_name();
|
||||
if(local_scope.back().find(tmp_para_name)!=local_scope.back().end())
|
||||
{
|
||||
int val_addr=calculation(local_scope,iter->get_children().back());
|
||||
int val_addr=calculation(parameters_assist_scope,iter->get_children().back());
|
||||
if(val_addr<0)
|
||||
return -1;
|
||||
if(local_scope.back()[tmp_para_name]<0)
|
||||
|
|
Loading…
Reference in New Issue