123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427 |
- implement String;
- include "string.m";
- splitl(s: string, cl: string): (string, string)
- {
- n := len s;
- for(j := 0; j < n; j++) {
- if(in(s[j], cl))
- return (s[0:j], s[j:n]);
- }
- return (s,"");
- }
- splitr(s: string, cl: string): (string, string)
- {
- n := len s;
- for(j := n-1; j >= 0; j--) {
- if(in(s[j], cl))
- return (s[0:j+1], s[j+1:n]);
- }
- return ("",s);
- }
- drop(s: string, cl: string): string
- {
- n := len s;
- for(j := 0; j < n; j++) {
- if(!in(s[j], cl))
- return (s[j:n]);
- }
- return "";
- }
- take(s: string, cl: string): string
- {
- n := len s;
- for(j := 0; j < n; j++) {
- if(!in(s[j], cl))
- return (s[0:j]);
- }
- return s;
- }
- in(c: int, s: string): int
- {
- n := len s;
- if(n == 0)
- return 0;
- ans := 0;
- negate := 0;
- if(s[0] == '^') {
- negate = 1;
- s = s[1:];
- n--;
- }
- for(i := 0; i < n; i++) {
- if(s[i] == '-' && i > 0 && i < n-1) {
- if(c >= s[i-1] && c <= s[i+1]) {
- ans = 1;
- break;
- }
- i++;
- }
- else
- if(c == s[i]) {
- ans = 1;
- break;
- }
- }
- if(negate)
- ans = !ans;
- return ans;
- }
- splitstrl(s: string, t: string): (string, string)
- {
- n := len s;
- nt := len t;
- if(nt == 0)
- return ("", s);
- c0 := t[0];
- mainloop:
- for(j := 0; j <= n-nt; j++) {
- if(s[j] == c0) {
- for(k := 1; k < nt; k++)
- if(s[j+k] != t[k])
- continue mainloop;
- return(s[0:j], s[j:n]);
- }
- }
- return (s,"");
- }
- splitstrr(s: string, t: string): (string, string)
- {
- n := len s;
- nt := len t;
- if(nt == 0)
- return (s, "");
- c0 := t[0];
- mainloop:
- for(j := n-nt; j >= 0; j--) {
- if(s[j] == c0) {
- for(k := 1; k < nt; k++)
- if(s[j+k] != t[k])
- continue mainloop;
- return(s[0:j+nt], s[j+nt:n]);
- }
- }
- return ("",s);
- }
- prefix(pre: string, s: string): int
- {
- if(len s < len pre)
- return 0;
- for(k := 0; k < len pre; k++)
- if(pre[k] != s[k])
- return 0;
- return 1;
- }
- tolower(s: string): string
- {
- for(i := 0; i < len s; i++) {
- c := s[i];
- if(c >= 'A' && c <= 'Z')
- s[i] += 'a' - 'A';
- }
- return s;
- }
- toupper(s: string): string
- {
- for(i := 0; i < len s; i++) {
- c := s[i];
- if(c >= 'a' && c <= 'z')
- s[i] += 'A' - 'a';
- }
- return s;
- }
- startnum(s: string, base: int): (int, int, int)
- {
- if(s == nil || base != 0 && (base < 2 || base > 36))
- return (0, 0, 0);
- # skip possible leading white space
- c := ' ';
- for (i := 0; i < len s; i++) {
- c = s[i];
- if(c != ' ' && c != '\t' && c != '\n')
- break;
- }
- # optional sign
- neg := 0;
- if(c == '-' || c == '+') {
- if(c == '-')
- neg = 1;
- i++;
- }
- if(base == 0) {
- # parse possible leading base designator
- start := i;
- base = -1;
- for (; i < start+3 && i < len s; i++) {
- c = s[i];
- if (c == 'r' && i > start) {
- base = int s[start:i];
- i++;
- break;
- } else if (c < '0' || c > '9')
- break;
- }
- if (base == -1) {
- i = start;
- base = 10;
- } else if (base == 0 || base > 36)
- return (0, 0, i);
- }
- if(i >= len s)
- return (0, 0, 0);
- return (base, neg, i);
- }
- tobig(s: string, base: int): (big, string)
- {
- neg, i: int;
- (base, neg, i) = startnum(s, base);
- if(base == 0)
- return (big 0, s);
- # parse number itself.
- # probably this should check for overflow, and max out, as limbo op does?
- start := i;
- n := big 0;
- for (; i < len s; i++) {
- if((d := digit(s[i], base)) < 0)
- break;
- n = n*big base + big d;
- }
- if (i == start)
- return (big 0, s);
- if (neg)
- return (-n, s[i:]);
- return (n, s[i:]);
- }
- toint(s: string, base: int): (int, string)
- {
- neg, i: int;
- (base, neg, i) = startnum(s, base);
- if(base == 0)
- return (0, s);
- # parse number itself.
- # probably this should check for overflow, and max out, as limbo op does?
- start := i;
- n := 0;
- for (; i < len s; i++){
- if((d := digit(s[i], base)) < 0)
- break;
- n = n*base + d;
- }
- if (i == start)
- return (0, s);
- if (neg)
- return (-n, s[i:]);
- return (n, s[i:]);
- }
- digit(c: int, base: int): int
- {
- if ('0' <= c && c <= '0' + base - 1)
- return c-'0';
- else if ('a' <= c && c < 'a' + base - 10)
- return (c - 'a' + 10);
- else if ('A' <= c && c < 'A' + base - 10)
- return (c - 'A' + 10);
- else
- return -1;
- }
- rpow(x: real, n: int): real
- {
- inv := 0;
- if(n < 0){
- n = -n;
- inv = 1;
- }
- r := 1.0;
- for(;;){
- if(n&1)
- r *= x;
- if((n >>= 1) == 0)
- break;
- x *= x;
- }
- if(inv)
- r = 1.0/r;
- return r;
- }
- match(p: string, s: string, i: int): int
- {
- if(i+len p > len s)
- return 0;
- for(j := 0; j < len p; j++){
- c := s[i++];
- if(c >= 'A' && c <= 'Z')
- c += 'a'-'A';
- if(p[j] != c)
- return 0;
- }
- return 1;
- }
- toreal(s: string, base: int): (real, string)
- {
- neg, i: int;
- (base, neg, i) = startnum(s, base);
- if(base == 0)
- return (0.0, s);
- c := s[i];
- if((c == 'i' || c == 'I') && match("infinity", s, i))
- return (real s, s[i+8:]);
- if((c == 'n' || c == 'N') && match("nan", s, i))
- return (real s, s[i+3:]);
- if(digit(c, base) < 0)
- return (0.0, s);
- num := 0.0;
- for(; i < len s && (d := digit(s[i], base)) >= 0; i++)
- num = num*real base + real d;
- dig := 0; # digits in fraction
- if(i < len s && s[i] == '.'){
- i++;
- for(; i < len s && (d = digit(s[i], base)) >= 0; i++){
- num = num*real base + real d;
- dig++;
- }
- }
- exp := 0;
- eneg := 0;
- if(i < len s && ((c = s[i]) == 'e' || c == 'E')){
- start := i; # might still be badly formed
- i++;
- if(i < len s && ((c = s[i]) == '-' || c == '+')){
- i++;
- if(c == '-'){
- dig = -dig;
- eneg = 1;
- }
- }
- if(i < len s && s[i] >= '0' && s[i] <= '9'){ # exponents are always decimal
- for(; i < len s && (d = digit(s[i], 10)) >= 0; i++)
- exp = exp*base + d;
- }else
- i = start;
- }
- if(base == 10)
- return (real s[0: i], s[i:]); # conversion can be more accurate
- exp -= dig;
- if(exp < 0){
- exp = -exp;
- eneg = !eneg;
- }
- if(exp < 0 || exp > 19999)
- exp = 19999; # huge but otherwise arbitrary limit
- dem := rpow(real base, exp);
- if(eneg)
- num /= dem;
- else
- num *= dem;
- if(neg)
- return (-num,s[i:]);
- return (num, s[i:]);
- }
- append(s: string, l: list of string): list of string
- {
- t: list of string;
- # Reverse l, prepend s, and reverse result.
- while (l != nil) {
- t = hd l :: t;
- l = tl l;
- }
- t = s :: t;
- do {
- l = hd t :: l;
- t = tl t;
- } while (t != nil);
- return l;
- }
- quoted(argv: list of string): string
- {
- return quotedc(argv, nil);
- }
- quotedc(argv: list of string, cl: string): string
- {
- s := "";
- while(argv != nil){
- arg := hd argv;
- for(i := 0; i < len arg; i++){
- c := arg[i];
- if(c == ' ' || c == '\t' || c == '\n' || c == '\'' || in(c, cl))
- break;
- }
- if(i < len arg || arg == nil){
- s += "'" + arg[0:i];
- for(; i < len arg; i++){
- if (arg[i] == '\'')
- s[len s] = '\'';
- s[len s] = arg[i];
- }
- s[len s] = '\'';
- }else
- s += arg;
- if(tl argv != nil)
- s[len s] = ' ';
- argv = tl argv;
- }
- return s;
- }
- unquoted(s: string): list of string
- {
- args: list of string;
- word: string;
- inquote := 0;
- for(j := len s; j > 0;){
- c := s[j-1];
- if(c == ' ' || c == '\t' || c == '\n'){
- j--;
- continue;
- }
- for(i := j-1; i >= 0 && ((c = s[i]) != ' ' && c != '\t' && c != '\n' || inquote); i--){ # collect word
- if(c == '\''){
- word = s[i+1:j] + word;
- j = i;
- if(!inquote || i == 0 || s[i-1] != '\'')
- inquote = !inquote;
- else
- i--;
- }
- }
- args = (s[i+1:j]+word) :: args;
- word = nil;
- j = i;
- }
- # if quotes were unbalanced, balance them and try again.
- if(inquote)
- return unquoted(s + "'");
- return args;
- }
|