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