A Tcl like command language made for the Clinl kernel testing
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

202 lignes
4.5 KiB

il y a 6 ans
  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. }