update
This commit is contained in:
parent
64488ba281
commit
2cfbbcb653
|
@ -1,15 +1,15 @@
|
|||
#ifndef __NASAL_LEXER_H__
|
||||
#define __NASAL_LEXER_H__
|
||||
|
||||
#define IS_IDENTIFIER_HEAD(c) (c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z')
|
||||
#define IS_IDENTIFIER_BODY(c) (c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z')||('0'<=c&&c<='9')
|
||||
#define IS_NUMBER_HEAD(c) ('0'<=c&&c<='9')
|
||||
#define IS_NUMBER_BODY(c) ('0'<=c&&c<='9')||('a'<=c&&c<='f')||('A'<=c&&c<='F')||(c=='e'||c=='E'||c=='.'||c=='x'||c=='o')
|
||||
#define IS_IDENTIFIER_HEAD(c) ((c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z'))
|
||||
#define IS_IDENTIFIER_BODY(c) ((c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z')||('0'<=c&&c<='9'))
|
||||
#define IS_HEX_NUMBER(c) (('0'<=c&&c<='9')||('a'<=c&&c<='f')||('A'<=c && c<='F'))
|
||||
#define IS_OCT_NUMEBR(c) ('0'<=c&&c<='7')
|
||||
#define IS_DIGIT(c) ('0'<=c&&c<='9')
|
||||
#define IS_STRING_HEAD(c) (c=='\''||c=='\"')
|
||||
// single operators have only one character
|
||||
#define IS_SINGLE_OPRATOR(c) (c=='('||c==')'||c=='['||c==']'||c=='{'||c=='}'||c==','||c==';'||c=='|'||c==':'||\
|
||||
c=='?'||c=='`'||c=='&'||c=='@'||c=='%'||c=='$'||c=='^'||c=='\\')
|
||||
#define IS_DOT(c) (c=='.')
|
||||
// calculation operators may have two chars, for example: += -= *= /= ~= != == >= <=
|
||||
#define IS_CALC_OPERATOR(c) (c=='='||c=='+'||c=='-'||c=='*'||c=='!'||c=='/'||c=='<'||c=='>'||c=='~')
|
||||
#define IS_NOTE_HEAD(c) (c=='#')
|
||||
|
@ -83,6 +83,7 @@ private:
|
|||
int error;
|
||||
std::vector<token> token_list;
|
||||
std::string identifier_gen(std::vector<char>&,int&,int&);
|
||||
void generate_number_error(int,std::string);
|
||||
std::string number_gen(std::vector<char>&,int&,int&);
|
||||
std::string string_gen(std::vector<char>&,int&,int&);
|
||||
public:
|
||||
|
@ -109,42 +110,95 @@ std::string nasal_lexer::identifier_gen(std::vector<char>& res,int& ptr,int& lin
|
|||
// after running this process, ptr will point to the next token's beginning character
|
||||
}
|
||||
|
||||
void nasal_lexer::generate_number_error(int line,std::string token_str)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">> [lexer] line "<<line<<": \""<<token_str<<"\" is not a correct number.\n";
|
||||
return;
|
||||
}
|
||||
std::string nasal_lexer::number_gen(std::vector<char>& res,int& ptr,int& line)
|
||||
{
|
||||
int res_size=res.size();
|
||||
bool scientific_notation=false;// numbers like 1e8 are scientific_notation
|
||||
bool is_hex=(ptr<res_size && res[ptr]=='0' && ptr+1<res_size && res[ptr+1]=='x');
|
||||
bool is_oct=(ptr<res_size && res[ptr]=='0' && ptr+1<res_size && res[ptr+1]=='o');
|
||||
std::string token_str="";
|
||||
while(ptr<res_size && IS_NUMBER_BODY(res[ptr]))
|
||||
// generate hex number
|
||||
if(res[ptr]=='0' && ptr+1<res_size && res[ptr+1]=='x')
|
||||
{
|
||||
token_str+=res[ptr];
|
||||
if((res[ptr]=='e' || res[ptr]=='E') && !is_hex && !is_oct)
|
||||
token_str="0x";
|
||||
ptr+=2;
|
||||
while(ptr<res_size && IS_HEX_NUMBER(res[ptr]))
|
||||
token_str+=res[ptr++];
|
||||
if(token_str=="0x")
|
||||
{
|
||||
scientific_notation=true;
|
||||
++ptr;
|
||||
break;
|
||||
generate_number_error(line,token_str);
|
||||
return "0";
|
||||
}
|
||||
++ptr;
|
||||
return token_str;
|
||||
}
|
||||
if(scientific_notation && ptr<res_size)
|
||||
// generate oct number
|
||||
else if(res[ptr]=='0' && ptr+1<res_size && res[ptr+1]=='o')
|
||||
{
|
||||
if(res[ptr]=='-')
|
||||
token_str="0o";
|
||||
ptr+=2;
|
||||
while(ptr<res_size && IS_OCT_NUMEBR(res[ptr]))
|
||||
token_str+=res[ptr++];
|
||||
if(token_str=="0o")
|
||||
{
|
||||
token_str+='-';
|
||||
++ptr;
|
||||
generate_number_error(line,token_str);
|
||||
return "0";
|
||||
}
|
||||
while(ptr<res_size && '0'<=res[ptr] && res[ptr]<='9')
|
||||
return token_str;
|
||||
}
|
||||
// generate dec number
|
||||
// dec number -> 0|[1~9][0~9]*(.[0~9]*)(e|E(+|-)0|[1~9][0~9]*)
|
||||
if(ptr<res_size && res[ptr]=='0')
|
||||
token_str+=res[ptr++];
|
||||
while(ptr<res_size && IS_DIGIT(res[ptr]))
|
||||
token_str+=res[ptr++];
|
||||
if(ptr<res_size && res[ptr]=='.')
|
||||
{
|
||||
token_str+=res[ptr++];
|
||||
// "xxxx." is not a correct number
|
||||
if(ptr>=res_size)
|
||||
{
|
||||
token_str+=res[ptr];
|
||||
++ptr;
|
||||
generate_number_error(line,token_str);
|
||||
return "0";
|
||||
}
|
||||
while(ptr<res_size && IS_DIGIT(res[ptr]))
|
||||
token_str+=res[ptr++];
|
||||
// "xxxx." is not a correct number
|
||||
if(token_str.back()=='.')
|
||||
{
|
||||
generate_number_error(line,token_str);
|
||||
return "0";
|
||||
}
|
||||
}
|
||||
if(!check_numerable_string(token_str))
|
||||
if(ptr<res_size && (res[ptr]=='e' || res[ptr]=='E'))
|
||||
{
|
||||
++error;
|
||||
std::cout<<">> [lexer] line "<<line<<": \'"<<token_str<<"\' is not a numerable string."<<std::endl;
|
||||
token_str="0";
|
||||
token_str+=res[ptr++];
|
||||
// "xxxe" is not a correct number
|
||||
if(ptr>=res_size)
|
||||
{
|
||||
generate_number_error(line,token_str);
|
||||
return "0";
|
||||
}
|
||||
if(ptr<res_size && (res[ptr]=='-' || res[ptr]=='+'))
|
||||
token_str+=res[ptr++];
|
||||
if(ptr>=res_size)
|
||||
{
|
||||
generate_number_error(line,token_str);
|
||||
return "0";
|
||||
}
|
||||
if(ptr<res_size && res[ptr]=='0')
|
||||
token_str+=res[ptr++];
|
||||
while(ptr<res_size && IS_DIGIT(res[ptr]))
|
||||
token_str+=res[ptr++];
|
||||
// "xxxe(-|+)" is not a correct number
|
||||
if(token_str.back()=='e' || token_str.back()=='E' || token_str.back()=='-' || token_str.back()=='+')
|
||||
{
|
||||
generate_number_error(line,token_str);
|
||||
return "0";
|
||||
}
|
||||
}
|
||||
return token_str;
|
||||
}
|
||||
|
@ -218,7 +272,7 @@ void nasal_lexer::scanner(std::vector<char>& res)
|
|||
new_token.type=tok_identifier;
|
||||
token_list.push_back(new_token);
|
||||
}
|
||||
else if(IS_NUMBER_HEAD(res[ptr]))
|
||||
else if(IS_DIGIT(res[ptr]))
|
||||
{
|
||||
token_str=number_gen(res,ptr,line);
|
||||
token new_token;
|
||||
|
@ -252,9 +306,9 @@ void nasal_lexer::scanner(std::vector<char>& res)
|
|||
token_list.push_back(new_token);
|
||||
++ptr;
|
||||
}
|
||||
else if(IS_DOT(res[ptr]))
|
||||
else if(res[ptr]=='.')
|
||||
{
|
||||
if(ptr+2<res_size && IS_DOT(res[ptr+1]) && IS_DOT(res[ptr+2]))
|
||||
if(ptr+2<res_size && res[ptr+1]=='.' && res[ptr+2]=='.')
|
||||
{
|
||||
token_str="...";
|
||||
ptr+=3;
|
||||
|
|
|
@ -32,25 +32,26 @@ inline bool check_oct_string(std::string str,int len)
|
|||
}
|
||||
inline bool check_dec_string(std::string str,int len)
|
||||
{
|
||||
int dot_cnt=0;
|
||||
if(str[0]=='.') return false;
|
||||
if(str[0]=='0' && ('0'<=str[1] && str[1]<='9')) return false;
|
||||
int i=0;
|
||||
for(;i<len;++i)
|
||||
// check integer part
|
||||
while('0'<=str[i] && str[i]<='9' && i<len) ++i;
|
||||
if(i==len) return true;
|
||||
if(str[i]!='e' && str[i]!='E' && str[i]!='.') return false;
|
||||
// check decimal part
|
||||
if(str[i]=='.')
|
||||
{
|
||||
if(str[i]=='.')
|
||||
{
|
||||
if(i==len-1 || str[i+1]=='e' || str[i+1]=='E') return false;
|
||||
++dot_cnt;
|
||||
}
|
||||
else if(str[i]=='e' || str[i]=='E') break;
|
||||
else if(str[i]<'0' || str[i]>'9' ) return false;
|
||||
++i;
|
||||
if(i==len) return false;
|
||||
while('0'<=str[i] && str[i]<='9' && i<len) ++i;
|
||||
}
|
||||
if(i==len) return true;
|
||||
if(str[i]!='e' && str[i]!='E') return false;
|
||||
// check scientific notation
|
||||
if(str[i]=='e' || str[i]=='E')
|
||||
{
|
||||
++i;
|
||||
if(i==len) return false;
|
||||
if(str[i]=='-')
|
||||
if(str[i]=='-' || str[i]=='+')
|
||||
{
|
||||
++i;
|
||||
if(i==len) return false;
|
||||
|
@ -59,7 +60,6 @@ inline bool check_dec_string(std::string str,int len)
|
|||
if(str[i]<'0' || str[i]>'9')
|
||||
return false;
|
||||
}
|
||||
if(dot_cnt>1) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -67,18 +67,16 @@ bool check_numerable_string(std::string str)
|
|||
{
|
||||
int len=str.length();
|
||||
if(!len) return false;
|
||||
if(str[0]=='-' && len>1)
|
||||
if(str[0]=='-' || str[0]=='+')
|
||||
{
|
||||
if(len==1) return false;
|
||||
std::string tmp="";
|
||||
for(int i=1;i<len;++i)
|
||||
tmp.push_back(str[i]);
|
||||
tmp+=str[i];
|
||||
str=tmp;
|
||||
--len;
|
||||
}
|
||||
else if(str[0]=='-' && len==1)
|
||||
return false;
|
||||
if(len==1 && '0'<=str[0] && str[0]<='9')
|
||||
return true;
|
||||
else if(len>2 && str[0]=='0' && str[1]=='x')
|
||||
if(len>2 && str[0]=='0' && str[1]=='x')
|
||||
return check_hex_string(str,len);
|
||||
else if(len>2 && str[0]=='0' && str[1]=='o')
|
||||
return check_oct_string(str,len);
|
||||
|
@ -93,8 +91,7 @@ bool check_numerable_string(std::string str)
|
|||
*/
|
||||
inline double hex_to_double(std::string str,int len)
|
||||
{
|
||||
double ret=0;
|
||||
double num_pow=1;
|
||||
double ret=0,num_pow=1;
|
||||
for(int i=len-1;i>1;--i)
|
||||
{
|
||||
if('0'<=str[i] && str[i]<='9')
|
||||
|
@ -109,8 +106,7 @@ inline double hex_to_double(std::string str,int len)
|
|||
}
|
||||
inline double oct_to_double(std::string str,int len)
|
||||
{
|
||||
double ret=0;
|
||||
double num_pow=1;
|
||||
double ret=0,num_pow=1;
|
||||
for(int i=len-1;i>1;--i)
|
||||
{
|
||||
ret+=num_pow*(str[i]-'0');
|
||||
|
@ -122,34 +118,29 @@ inline double dec_to_double(std::string str,int len)
|
|||
{
|
||||
double ret=0;
|
||||
int i=0;
|
||||
for(;i<len;++i)
|
||||
while('0'<=str[i] && str[i]<='9' && i<len)
|
||||
{
|
||||
if('0'<=str[i] && str[i]<='9')
|
||||
ret=ret*10+(str[i]-'0');
|
||||
else if(str[i]=='.' || str[i]=='e' || str[i]=='E')
|
||||
break;
|
||||
ret=ret*10+(str[i]-'0');
|
||||
++i;
|
||||
}
|
||||
if(i==len) return ret;
|
||||
if(str[i]=='.')
|
||||
{
|
||||
++i;
|
||||
double num_pow=0.1;
|
||||
for(;i<len;++i)
|
||||
while('0'<=str[i] && str[i]<='9' && i<len)
|
||||
{
|
||||
if('0'<=str[i] && str[i]<='9')
|
||||
{
|
||||
ret+=num_pow*(str[i]-'0');
|
||||
num_pow*=0.1;
|
||||
}
|
||||
else if(str[i]=='e' || str[i]=='E')
|
||||
break;
|
||||
ret+=num_pow*(str[i]-'0');
|
||||
num_pow*=0.1;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
if(i==len) return ret;
|
||||
if(str[i]=='e' || str[i]=='E')
|
||||
{
|
||||
|
||||
++i;
|
||||
bool is_negative=(str[i]=='-');
|
||||
if(is_negative) ++i;
|
||||
if(str[i]=='-' || str[i]=='+') ++i;
|
||||
double num_pow=0;
|
||||
for(;i<len;++i) num_pow=num_pow*10+(str[i]-'0');
|
||||
num_pow=std::pow(10,is_negative?-num_pow:num_pow);
|
||||
|
@ -163,19 +154,16 @@ double trans_string_to_number(std::string str)
|
|||
int len=str.length();
|
||||
double ret_num=0;
|
||||
if(!len) return 0;
|
||||
if(str[0]=='-' && len>1)
|
||||
if(str[0]=='-' || str[0]=='+')
|
||||
{
|
||||
is_negative=true;
|
||||
is_negative=(str[0]=='-');
|
||||
std::string tmp="";
|
||||
for(int i=1;i<len;++i)
|
||||
tmp.push_back(str[i]);
|
||||
str=tmp;
|
||||
--len;
|
||||
}
|
||||
else if(str[0]=='-' && len==1)
|
||||
return 0;
|
||||
if(len==1 && '0'<=str[0] && str[0]<='9')
|
||||
ret_num=(double)(str[0]-'0');
|
||||
else if(len>2 && str[0]=='0' && str[1]=='x')
|
||||
if(len>2 && str[0]=='0' && str[1]=='x')
|
||||
ret_num=hex_to_double(str,len);
|
||||
else if(len>2 && str[0]=='0' && str[1]=='o')
|
||||
ret_num=oct_to_double(str,len);
|
||||
|
|
|
@ -56,7 +56,7 @@ private:
|
|||
int call_vector(nasal_ast&,int,int);
|
||||
int call_hash(nasal_ast&,int,int);
|
||||
int call_function(nasal_ast&,std::string,int,int,int);
|
||||
int call_builtin_function(nasal_ast&,int);
|
||||
int call_builtin_function(std::string,int);
|
||||
// get scalars' memory place in complex data structure like vector/hash/function/closure(scope)
|
||||
int call_scalar_mem(nasal_ast&,int);
|
||||
int call_vector_mem(nasal_ast&,int,int);
|
||||
|
@ -193,7 +193,9 @@ void nasal_runtime::run()
|
|||
nasal_vm.del_reference(global_scope_address);
|
||||
nasal_vm.clear();
|
||||
|
||||
std::cout<<">> [runtime] process exited after "<<end_time-begin_time<<"s "<<(returned_statement==rt_exit_without_error?"without errors.":"with errors.")<<std::endl;
|
||||
time_t total_run_time=end_time-begin_time;
|
||||
if(total_run_time>=1)
|
||||
std::cout<<">> [runtime] process exited after "<<total_run_time<<"s "<<(returned_statement==rt_exit_without_error?".\n":"with errors.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -634,13 +636,16 @@ int nasal_runtime::call_scalar(nasal_ast& node,int local_scope_addr)
|
|||
value_address=nasal_vm.gc_get(global_scope_address).get_closure().get_value_address(val_name);
|
||||
if(value_address<0)
|
||||
{
|
||||
value_address=call_builtin_function(node.get_children()[0],local_scope_addr);
|
||||
value_address=call_builtin_function(val_name,local_scope_addr);
|
||||
if(value_address>=0)
|
||||
return value_address;
|
||||
}
|
||||
if(value_address<0)
|
||||
{
|
||||
std::cout<<">> [runtime] call_nasal_scalar: cannot find value named \'"<<val_name<<"\'."<<std::endl;
|
||||
if(builtin_func_hashmap.find(val_name)!=builtin_func_hashmap.end())
|
||||
std::cout<<">> [runtime] call_scalar: call "<<val_name<<" failed.\n";
|
||||
else
|
||||
std::cout<<">> [runtime] call_scalar: cannot find value named \""<<val_name<<"\".\n";
|
||||
++error;
|
||||
return -1;
|
||||
}
|
||||
|
@ -1128,13 +1133,12 @@ int nasal_runtime::call_function(nasal_ast& node,std::string func_name,int base_
|
|||
}
|
||||
return ret_value_addr;
|
||||
}
|
||||
int nasal_runtime::call_builtin_function(nasal_ast& node,int local_scope_addr)
|
||||
int nasal_runtime::call_builtin_function(std::string val_name,int local_scope_addr)
|
||||
{
|
||||
int ret_value_addr=-1;
|
||||
int builtin_func_num=-1;
|
||||
std::string builtin_name=node.get_str();
|
||||
if(builtin_func_hashmap.find(builtin_name)!=builtin_func_hashmap.end())
|
||||
ret_value_addr=(this->*builtin_func_hashmap[builtin_name])(local_scope_addr);
|
||||
if(builtin_func_hashmap.find(val_name)!=builtin_func_hashmap.end())
|
||||
ret_value_addr=(this->*builtin_func_hashmap[val_name])(local_scope_addr);
|
||||
return ret_value_addr;
|
||||
}
|
||||
int nasal_runtime::call_scalar_mem(nasal_ast& node,int local_scope_addr)
|
||||
|
|
Loading…
Reference in New Issue