string.b 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. implement String;
  2. include "string.m";
  3. splitl(s: string, cl: string): (string, string)
  4. {
  5. n := len s;
  6. for(j := 0; j < n; j++) {
  7. if(in(s[j], cl))
  8. return (s[0:j], s[j:n]);
  9. }
  10. return (s,"");
  11. }
  12. splitr(s: string, cl: string): (string, string)
  13. {
  14. n := len s;
  15. for(j := n-1; j >= 0; j--) {
  16. if(in(s[j], cl))
  17. return (s[0:j+1], s[j+1:n]);
  18. }
  19. return ("",s);
  20. }
  21. drop(s: string, cl: string): string
  22. {
  23. n := len s;
  24. for(j := 0; j < n; j++) {
  25. if(!in(s[j], cl))
  26. return (s[j:n]);
  27. }
  28. return "";
  29. }
  30. take(s: string, cl: string): string
  31. {
  32. n := len s;
  33. for(j := 0; j < n; j++) {
  34. if(!in(s[j], cl))
  35. return (s[0:j]);
  36. }
  37. return s;
  38. }
  39. in(c: int, s: string): int
  40. {
  41. n := len s;
  42. if(n == 0)
  43. return 0;
  44. ans := 0;
  45. negate := 0;
  46. if(s[0] == '^') {
  47. negate = 1;
  48. s = s[1:];
  49. n--;
  50. }
  51. for(i := 0; i < n; i++) {
  52. if(s[i] == '-' && i > 0 && i < n-1) {
  53. if(c >= s[i-1] && c <= s[i+1]) {
  54. ans = 1;
  55. break;
  56. }
  57. i++;
  58. }
  59. else
  60. if(c == s[i]) {
  61. ans = 1;
  62. break;
  63. }
  64. }
  65. if(negate)
  66. ans = !ans;
  67. return ans;
  68. }
  69. splitstrl(s: string, t: string): (string, string)
  70. {
  71. n := len s;
  72. nt := len t;
  73. if(nt == 0)
  74. return ("", s);
  75. c0 := t[0];
  76. mainloop:
  77. for(j := 0; j <= n-nt; j++) {
  78. if(s[j] == c0) {
  79. for(k := 1; k < nt; k++)
  80. if(s[j+k] != t[k])
  81. continue mainloop;
  82. return(s[0:j], s[j:n]);
  83. }
  84. }
  85. return (s,"");
  86. }
  87. splitstrr(s: string, t: string): (string, string)
  88. {
  89. n := len s;
  90. nt := len t;
  91. if(nt == 0)
  92. return (s, "");
  93. c0 := t[0];
  94. mainloop:
  95. for(j := n-nt; j >= 0; j--) {
  96. if(s[j] == c0) {
  97. for(k := 1; k < nt; k++)
  98. if(s[j+k] != t[k])
  99. continue mainloop;
  100. return(s[0:j+nt], s[j+nt:n]);
  101. }
  102. }
  103. return ("",s);
  104. }
  105. prefix(pre: string, s: string): int
  106. {
  107. if(len s < len pre)
  108. return 0;
  109. for(k := 0; k < len pre; k++)
  110. if(pre[k] != s[k])
  111. return 0;
  112. return 1;
  113. }
  114. tolower(s: string): string
  115. {
  116. for(i := 0; i < len s; i++) {
  117. c := s[i];
  118. if(c >= 'A' && c <= 'Z')
  119. s[i] += 'a' - 'A';
  120. }
  121. return s;
  122. }
  123. toupper(s: string): string
  124. {
  125. for(i := 0; i < len s; i++) {
  126. c := s[i];
  127. if(c >= 'a' && c <= 'z')
  128. s[i] += 'A' - 'a';
  129. }
  130. return s;
  131. }
  132. startnum(s: string, base: int): (int, int, int)
  133. {
  134. if(s == nil || base != 0 && (base < 2 || base > 36))
  135. return (0, 0, 0);
  136. # skip possible leading white space
  137. c := ' ';
  138. for (i := 0; i < len s; i++) {
  139. c = s[i];
  140. if(c != ' ' && c != '\t' && c != '\n')
  141. break;
  142. }
  143. # optional sign
  144. neg := 0;
  145. if(c == '-' || c == '+') {
  146. if(c == '-')
  147. neg = 1;
  148. i++;
  149. }
  150. if(base == 0) {
  151. # parse possible leading base designator
  152. start := i;
  153. base = -1;
  154. for (; i < start+3 && i < len s; i++) {
  155. c = s[i];
  156. if (c == 'r' && i > start) {
  157. base = int s[start:i];
  158. i++;
  159. break;
  160. } else if (c < '0' || c > '9')
  161. break;
  162. }
  163. if (base == -1) {
  164. i = start;
  165. base = 10;
  166. } else if (base == 0 || base > 36)
  167. return (0, 0, i);
  168. }
  169. if(i >= len s)
  170. return (0, 0, 0);
  171. return (base, neg, i);
  172. }
  173. tobig(s: string, base: int): (big, string)
  174. {
  175. neg, i: int;
  176. (base, neg, i) = startnum(s, base);
  177. if(base == 0)
  178. return (big 0, s);
  179. # parse number itself.
  180. # probably this should check for overflow, and max out, as limbo op does?
  181. start := i;
  182. n := big 0;
  183. for (; i < len s; i++) {
  184. if((d := digit(s[i], base)) < 0)
  185. break;
  186. n = n*big base + big d;
  187. }
  188. if (i == start)
  189. return (big 0, s);
  190. if (neg)
  191. return (-n, s[i:]);
  192. return (n, s[i:]);
  193. }
  194. toint(s: string, base: int): (int, string)
  195. {
  196. neg, i: int;
  197. (base, neg, i) = startnum(s, base);
  198. if(base == 0)
  199. return (0, s);
  200. # parse number itself.
  201. # probably this should check for overflow, and max out, as limbo op does?
  202. start := i;
  203. n := 0;
  204. for (; i < len s; i++){
  205. if((d := digit(s[i], base)) < 0)
  206. break;
  207. n = n*base + d;
  208. }
  209. if (i == start)
  210. return (0, s);
  211. if (neg)
  212. return (-n, s[i:]);
  213. return (n, s[i:]);
  214. }
  215. digit(c: int, base: int): int
  216. {
  217. if ('0' <= c && c <= '0' + base - 1)
  218. return c-'0';
  219. else if ('a' <= c && c < 'a' + base - 10)
  220. return (c - 'a' + 10);
  221. else if ('A' <= c && c < 'A' + base - 10)
  222. return (c - 'A' + 10);
  223. else
  224. return -1;
  225. }
  226. rpow(x: real, n: int): real
  227. {
  228. inv := 0;
  229. if(n < 0){
  230. n = -n;
  231. inv = 1;
  232. }
  233. r := 1.0;
  234. for(;;){
  235. if(n&1)
  236. r *= x;
  237. if((n >>= 1) == 0)
  238. break;
  239. x *= x;
  240. }
  241. if(inv)
  242. r = 1.0/r;
  243. return r;
  244. }
  245. match(p: string, s: string, i: int): int
  246. {
  247. if(i+len p > len s)
  248. return 0;
  249. for(j := 0; j < len p; j++){
  250. c := s[i++];
  251. if(c >= 'A' && c <= 'Z')
  252. c += 'a'-'A';
  253. if(p[j] != c)
  254. return 0;
  255. }
  256. return 1;
  257. }
  258. toreal(s: string, base: int): (real, string)
  259. {
  260. neg, i: int;
  261. (base, neg, i) = startnum(s, base);
  262. if(base == 0)
  263. return (0.0, s);
  264. c := s[i];
  265. if((c == 'i' || c == 'I') && match("infinity", s, i))
  266. return (real s, s[i+8:]);
  267. if((c == 'n' || c == 'N') && match("nan", s, i))
  268. return (real s, s[i+3:]);
  269. if(digit(c, base) < 0)
  270. return (0.0, s);
  271. num := 0.0;
  272. for(; i < len s && (d := digit(s[i], base)) >= 0; i++)
  273. num = num*real base + real d;
  274. dig := 0; # digits in fraction
  275. if(i < len s && s[i] == '.'){
  276. i++;
  277. for(; i < len s && (d = digit(s[i], base)) >= 0; i++){
  278. num = num*real base + real d;
  279. dig++;
  280. }
  281. }
  282. exp := 0;
  283. eneg := 0;
  284. if(i < len s && ((c = s[i]) == 'e' || c == 'E')){
  285. start := i; # might still be badly formed
  286. i++;
  287. if(i < len s && ((c = s[i]) == '-' || c == '+')){
  288. i++;
  289. if(c == '-'){
  290. dig = -dig;
  291. eneg = 1;
  292. }
  293. }
  294. if(i < len s && s[i] >= '0' && s[i] <= '9'){ # exponents are always decimal
  295. for(; i < len s && (d = digit(s[i], 10)) >= 0; i++)
  296. exp = exp*base + d;
  297. }else
  298. i = start;
  299. }
  300. if(base == 10)
  301. return (real s[0: i], s[i:]); # conversion can be more accurate
  302. exp -= dig;
  303. if(exp < 0){
  304. exp = -exp;
  305. eneg = !eneg;
  306. }
  307. if(exp < 0 || exp > 19999)
  308. exp = 19999; # huge but otherwise arbitrary limit
  309. dem := rpow(real base, exp);
  310. if(eneg)
  311. num /= dem;
  312. else
  313. num *= dem;
  314. if(neg)
  315. return (-num,s[i:]);
  316. return (num, s[i:]);
  317. }
  318. append(s: string, l: list of string): list of string
  319. {
  320. t: list of string;
  321. # Reverse l, prepend s, and reverse result.
  322. while (l != nil) {
  323. t = hd l :: t;
  324. l = tl l;
  325. }
  326. t = s :: t;
  327. do {
  328. l = hd t :: l;
  329. t = tl t;
  330. } while (t != nil);
  331. return l;
  332. }
  333. quoted(argv: list of string): string
  334. {
  335. return quotedc(argv, nil);
  336. }
  337. quotedc(argv: list of string, cl: string): string
  338. {
  339. s := "";
  340. while(argv != nil){
  341. arg := hd argv;
  342. for(i := 0; i < len arg; i++){
  343. c := arg[i];
  344. if(c == ' ' || c == '\t' || c == '\n' || c == '\'' || in(c, cl))
  345. break;
  346. }
  347. if(i < len arg || arg == nil){
  348. s += "'" + arg[0:i];
  349. for(; i < len arg; i++){
  350. if (arg[i] == '\'')
  351. s[len s] = '\'';
  352. s[len s] = arg[i];
  353. }
  354. s[len s] = '\'';
  355. }else
  356. s += arg;
  357. if(tl argv != nil)
  358. s[len s] = ' ';
  359. argv = tl argv;
  360. }
  361. return s;
  362. }
  363. unquoted(s: string): list of string
  364. {
  365. args: list of string;
  366. word: string;
  367. inquote := 0;
  368. for(j := len s; j > 0;){
  369. c := s[j-1];
  370. if(c == ' ' || c == '\t' || c == '\n'){
  371. j--;
  372. continue;
  373. }
  374. for(i := j-1; i >= 0 && ((c = s[i]) != ' ' && c != '\t' && c != '\n' || inquote); i--){ # collect word
  375. if(c == '\''){
  376. word = s[i+1:j] + word;
  377. j = i;
  378. if(!inquote || i == 0 || s[i-1] != '\'')
  379. inquote = !inquote;
  380. else
  381. i--;
  382. }
  383. }
  384. args = (s[i+1:j]+word) :: args;
  385. word = nil;
  386. j = i;
  387. }
  388. # if quotes were unbalanced, balance them and try again.
  389. if(inquote)
  390. return unquoted(s + "'");
  391. return args;
  392. }