A Tcl like command language made for the Clinl kernel testing
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 

203 Zeilen
4.5 KiB

#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;
}