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.

202 Zeilen
4.5 KiB

vor 6 Jahren
  1. #include "crank.h"
  2. kstd::string_view crank_context::eval(kstd::string_view code)
  3. {
  4. auto ret = eval_no_copy(copy(code));
  5. return ret;
  6. }
  7. kstd::string_view identity(kstd::string_view args, crank_context& ctx)
  8. {
  9. return args;
  10. }
  11. kstd::string_view set(kstd::string_view args, crank_context& ctx)
  12. {
  13. args = skip_whitespace(args);
  14. auto key = extract_token(args);
  15. auto value = skip_linearspace(kstd::string_view(args.begin()+key.size(),args.end()));
  16. return ctx.store(key,value);
  17. }
  18. bool istokenok(int m)
  19. {
  20. return (
  21. isalpha(m)
  22. || isdigit(m)
  23. || m=='$'
  24. || m=='-'
  25. || m=='_'
  26. );
  27. }
  28. bool islinearspace(int m)
  29. {
  30. return (
  31. m==' '
  32. || m=='\t'
  33. );
  34. }
  35. kstd::string_view skip_whitespace(kstd::string_view code)
  36. {
  37. auto m = code.begin();
  38. while(m<code.end() && isspace(*m))
  39. {
  40. m++;
  41. }
  42. return kstd::string_view(m,code.end());
  43. }
  44. kstd::string_view skip_linearspace(kstd::string_view code)
  45. {
  46. auto m = code.begin();
  47. while(m<code.end() && islinearspace(*m))
  48. {
  49. m++;
  50. }
  51. return kstd::string_view(m,code.end());
  52. }
  53. template<char bound>
  54. kstd::string_view extract_bounded(kstd::string_view code)
  55. {
  56. auto m = code.begin();
  57. while(m<code.end() && *m!=bound)
  58. {
  59. if(*m=='"')
  60. {
  61. m++;
  62. m+=extract_string(kstd::string_view(m,code.end())).size();
  63. m++;
  64. }
  65. else if(*m=='{')
  66. {
  67. m++;
  68. m+=extract_array(kstd::string_view(m,code.end())).size();
  69. m++;
  70. }
  71. else if(*m=='[')
  72. {
  73. m++;
  74. m+=extract_subcommand(kstd::string_view(m,code.end())).size();
  75. m++;
  76. }
  77. else if(istokenok(*m))
  78. {
  79. m+=extract_token(kstd::string_view(m,code.end())).size();
  80. }
  81. else
  82. {
  83. m = skip_whitespace(kstd::string_view(m,code.end())).begin();
  84. }
  85. }
  86. return kstd::string_view(code.begin(), m);
  87. }
  88. kstd::string_view extract_command(kstd::string_view code)
  89. {
  90. code = skip_whitespace(code);
  91. return extract_bounded<'\n'>(code);
  92. }
  93. kstd::string_view extract_subcommand(kstd::string_view code)
  94. {
  95. return extract_bounded<']'>(code);
  96. }
  97. kstd::string_view extract_string(kstd::string_view code)
  98. {
  99. auto m = code.begin();
  100. while(m<code.end() && *m!='"')
  101. {
  102. m+=(*m!='\\')?1:2;
  103. }
  104. return kstd::string_view(code.begin(), m);
  105. }
  106. kstd::string_view extract_token(kstd::string_view code)
  107. {
  108. auto m = code.begin();
  109. while(m<code.end() && istokenok(*m))
  110. {
  111. m++;
  112. }
  113. return kstd::string_view(code.begin(), m);
  114. }
  115. kstd::string_view extract_array(kstd::string_view code)
  116. {
  117. return extract_bounded<'}'>(code);
  118. }
  119. kstd::string_view crank_context::execute_command(kstd::string_view code)
  120. {
  121. code = copy_replace(code);
  122. auto token = extract_token(code);
  123. auto symbol = get_symbol(token);
  124. auto args = skip_linearspace(kstd::string_view(code.begin()+token.size(),code.end()));
  125. if(symbol.size())
  126. {
  127. if(symbol[0]=='@')
  128. {
  129. symbol = skip_linearspace(kstd::string_view(symbol.begin()+1, symbol.end()));
  130. while(istokenok(args[0]))
  131. {
  132. auto argname = extract_token(symbol);
  133. symbol = skip_linearspace(kstd::string_view(symbol.begin()+argname.size(), symbol.end()));
  134. auto argvalue = kstd::string_view();
  135. if(args[0]=='{')
  136. {
  137. argvalue=extract_array(kstd::string_view(args.begin()+1, args.end()));
  138. args = skip_linearspace(kstd::string_view(args.begin()+argvalue.size()+2, args.end()));
  139. }
  140. else if(args[0]=='[')
  141. {
  142. argvalue=crank_context::execute_command(extract_subcommand(kstd::string_view(args.begin()+1, args.end())));
  143. args = skip_linearspace(kstd::string_view(args.begin()+argvalue.size()+2, args.end()));
  144. }
  145. else if(args[0]=='"')
  146. {
  147. argvalue=extract_string(kstd::string_view(args.begin()+1, args.end()));
  148. args = skip_linearspace(kstd::string_view(args.begin()+argvalue.size()+2, args.end()));
  149. }
  150. else
  151. {
  152. argvalue=extract_token(kstd::string_view(args.begin()+1, args.end()));
  153. args = skip_linearspace(kstd::string_view(args.begin()+argvalue.size(), args.end()));
  154. }
  155. store(argname,argvalue);
  156. }
  157. symbol = extract_array(symbol);
  158. auto command = extract_command(symbol);
  159. auto ret = kstd::string_view();
  160. while(command.size())
  161. {
  162. ret = execute_command(command);
  163. symbol = kstd::string_view(symbol.begin()+command.size(),symbol.end());
  164. command = extract_command(symbol);
  165. }
  166. return ret;
  167. }
  168. else
  169. {
  170. return symbol;
  171. }
  172. }
  173. else
  174. {
  175. return get_native(token)(args,this);
  176. }
  177. }
  178. kstd::string_view crank_context::eval_no_copy(kstd::string_view code)
  179. {
  180. auto command = extract_command(code);
  181. auto ret = kstd::string_view();;
  182. while(command.size())
  183. {
  184. ret = execute_command(command);
  185. code = kstd::string_view(code.begin()+command.size(),code.end());
  186. command = extract_command(code);
  187. }
  188. return ret;
  189. }