#include "crank.h"
|
|
|
|
kstd::string_view crank_context::eval(kstd::string_view code)
|
|
{
|
|
auto ret = eval_no_copy(copy(code));
|
|
return ret;
|
|
}
|
|
|
|
kstd::string_view identity(kstd::string_view args, crank_context& ctx)
|
|
{
|
|
return args;
|
|
}
|
|
kstd::string_view set(kstd::string_view args, crank_context& ctx)
|
|
{
|
|
args = skip_whitespace(args);
|
|
auto key = extract_token(args);
|
|
auto value = skip_linearspace(kstd::string_view(args.begin()+key.size(),args.end()));
|
|
return ctx.store(key,value);
|
|
}
|
|
|
|
bool istokenok(int m)
|
|
{
|
|
return (
|
|
isalpha(m)
|
|
|| isdigit(m)
|
|
|| m=='$'
|
|
|| m=='-'
|
|
|| m=='_'
|
|
);
|
|
}
|
|
|
|
bool islinearspace(int m)
|
|
{
|
|
return (
|
|
m==' '
|
|
|| m=='\t'
|
|
);
|
|
}
|
|
|
|
kstd::string_view skip_whitespace(kstd::string_view code)
|
|
{
|
|
auto m = code.begin();
|
|
while(m<code.end() && isspace(*m))
|
|
{
|
|
m++;
|
|
}
|
|
return kstd::string_view(m,code.end());
|
|
}
|
|
|
|
kstd::string_view skip_linearspace(kstd::string_view code)
|
|
{
|
|
auto m = code.begin();
|
|
while(m<code.end() && islinearspace(*m))
|
|
{
|
|
m++;
|
|
}
|
|
return kstd::string_view(m,code.end());
|
|
}
|
|
|
|
template<char bound>
|
|
kstd::string_view extract_bounded(kstd::string_view code)
|
|
{
|
|
auto m = code.begin();
|
|
while(m<code.end() && *m!=bound)
|
|
{
|
|
if(*m=='"')
|
|
{
|
|
m++;
|
|
m+=extract_string(kstd::string_view(m,code.end())).size();
|
|
m++;
|
|
}
|
|
else if(*m=='{')
|
|
{
|
|
m++;
|
|
m+=extract_array(kstd::string_view(m,code.end())).size();
|
|
m++;
|
|
}
|
|
else if(*m=='[')
|
|
{
|
|
m++;
|
|
m+=extract_subcommand(kstd::string_view(m,code.end())).size();
|
|
m++;
|
|
}
|
|
else if(istokenok(*m))
|
|
{
|
|
m+=extract_token(kstd::string_view(m,code.end())).size();
|
|
}
|
|
else
|
|
{
|
|
m = skip_whitespace(kstd::string_view(m,code.end())).begin();
|
|
}
|
|
}
|
|
return kstd::string_view(code.begin(), m);
|
|
}
|
|
|
|
kstd::string_view extract_command(kstd::string_view code)
|
|
{
|
|
code = skip_whitespace(code);
|
|
return extract_bounded<'\n'>(code);
|
|
}
|
|
|
|
kstd::string_view extract_subcommand(kstd::string_view code)
|
|
{
|
|
return extract_bounded<']'>(code);
|
|
}
|
|
|
|
kstd::string_view extract_string(kstd::string_view code)
|
|
{
|
|
auto m = code.begin();
|
|
while(m<code.end() && *m!='"')
|
|
{
|
|
m+=(*m!='\\')?1:2;
|
|
}
|
|
return kstd::string_view(code.begin(), m);
|
|
}
|
|
|
|
kstd::string_view extract_token(kstd::string_view code)
|
|
{
|
|
auto m = code.begin();
|
|
while(m<code.end() && istokenok(*m))
|
|
{
|
|
m++;
|
|
}
|
|
return kstd::string_view(code.begin(), m);
|
|
}
|
|
|
|
kstd::string_view extract_array(kstd::string_view code)
|
|
{
|
|
return extract_bounded<'}'>(code);
|
|
}
|
|
|
|
kstd::string_view crank_context::execute_command(kstd::string_view code)
|
|
{
|
|
code = copy_replace(code);
|
|
auto token = extract_token(code);
|
|
auto symbol = get_symbol(token);
|
|
auto args = skip_linearspace(kstd::string_view(code.begin()+token.size(),code.end()));
|
|
if(symbol.size())
|
|
{
|
|
if(symbol[0]=='@')
|
|
{
|
|
symbol = skip_linearspace(kstd::string_view(symbol.begin()+1, symbol.end()));
|
|
while(istokenok(args[0]))
|
|
{
|
|
auto argname = extract_token(symbol);
|
|
symbol = skip_linearspace(kstd::string_view(symbol.begin()+argname.size(), symbol.end()));
|
|
auto argvalue = kstd::string_view();
|
|
if(args[0]=='{')
|
|
{
|
|
argvalue=extract_array(kstd::string_view(args.begin()+1, args.end()));
|
|
args = skip_linearspace(kstd::string_view(args.begin()+argvalue.size()+2, args.end()));
|
|
}
|
|
else if(args[0]=='[')
|
|
{
|
|
argvalue=crank_context::execute_command(extract_subcommand(kstd::string_view(args.begin()+1, args.end())));
|
|
args = skip_linearspace(kstd::string_view(args.begin()+argvalue.size()+2, args.end()));
|
|
}
|
|
else if(args[0]=='"')
|
|
{
|
|
argvalue=extract_string(kstd::string_view(args.begin()+1, args.end()));
|
|
args = skip_linearspace(kstd::string_view(args.begin()+argvalue.size()+2, args.end()));
|
|
}
|
|
else
|
|
{
|
|
argvalue=extract_token(kstd::string_view(args.begin()+1, args.end()));
|
|
args = skip_linearspace(kstd::string_view(args.begin()+argvalue.size(), args.end()));
|
|
}
|
|
store(argname,argvalue);
|
|
}
|
|
symbol = extract_array(symbol);
|
|
auto command = extract_command(symbol);
|
|
auto ret = kstd::string_view();
|
|
while(command.size())
|
|
{
|
|
ret = execute_command(command);
|
|
symbol = kstd::string_view(symbol.begin()+command.size(),symbol.end());
|
|
command = extract_command(symbol);
|
|
}
|
|
return ret;
|
|
}
|
|
else
|
|
{
|
|
return symbol;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return get_native(token)(args,this);
|
|
}
|
|
}
|
|
|
|
kstd::string_view crank_context::eval_no_copy(kstd::string_view code)
|
|
{
|
|
auto command = extract_command(code);
|
|
auto ret = kstd::string_view();;
|
|
while(command.size())
|
|
{
|
|
ret = execute_command(command);
|
|
code = kstd::string_view(code.begin()+command.size(),code.end());
|
|
command = extract_command(code);
|
|
}
|
|
return ret;
|
|
}
|