Permalink
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Dec 20, 2018
Dec 20, 2018
Jan 14, 2015
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Jan 14, 2015
Mar 19, 2018
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Mar 19, 2018
Jan 14, 2015
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Jan 14, 2015
Mar 19, 2018
Jan 14, 2015
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Jan 14, 2015
Jan 14, 2015
Mar 19, 2018
Mar 19, 2018
Jan 14, 2015
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 27, 2019
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Apr 2, 2019
Mar 19, 2018
Aug 31, 2017
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Aug 31, 2017
Apr 16, 2019
Mar 19, 2018
Apr 16, 2019
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Nov 12, 2018
Nov 12, 2018
Nov 12, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Apr 2, 2019
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Aug 31, 2017
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Jan 6, 2016
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Aug 31, 2017
May 24, 2019
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Aug 31, 2017
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Nov 14, 2018
Mar 19, 2018
Mar 19, 2018
Nov 15, 2019
Jul 28, 2018
Oct 27, 2019
Nov 2, 2018
Oct 27, 2019
Nov 2, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Nov 12, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Jun 29, 2017
Jun 29, 2017
Jun 29, 2017
Oct 13, 2019
Jun 29, 2017
Jul 10, 2017
Jul 10, 2017
Mar 19, 2018
Mar 19, 2018
Oct 13, 2019
Oct 13, 2019
Newer
100644
2387 lines (2188 sloc)
76.2 KB
21
if($.start === null || $.start === _b_.None){$.start = 0}
22
else if($.start < 0){
23
$.start += $.self.length
24
$.start = Math.max(0, $.start)
25
}
26
if($.end === null || $.end === _b_.None){$.end = $.self.length}
27
else if($.end < 0){
28
$.end += $.self.length
29
$.end = Math.max(0, $.end)
30
}
32
if(! isinstance($.start, _b_.int) || ! isinstance($.end, _b_.int)){
33
throw _b_.TypeError.$factory("slice indices must be integers " +
34
"or None or have an __index__ method")
35
}
52
if(!(typeof other === "string")){
53
try{return getattr(other, "__radd__")(self)}
54
catch(err){
55
throw _b_.TypeError.$factory("Can't convert " +
61
str.__contains__ = function(self, item){
62
if(!(typeof item == "string")){
63
throw _b_.TypeError.$factory("'in <string>' requires " +
64
"string as left operand, not " + item.__class__)
65
}
67
if(nbcar == 0) {return true} // a string contains the empty string
68
if(self.length == 0){return nbcar == 0}
69
for(var i = 0, len = self.length; i < len; i++){
70
if(self.substr(i, nbcar) == item){return true}
79
// __dir__must be assigned explicitely because attribute resolution for
80
// builtin classes doesn't use __mro__
84
if(other === undefined){ // compare object "self" to class "str"
85
return self === str
95
if(fmt.type && fmt.type != "s"){
96
throw _b_.ValueError.$factory("Unknown format code '" + fmt.type +
104
if(fmt.sign !== undefined){
105
throw _b_.ValueError.$factory(
106
"Sign not allowed in string format specifier")
116
if(arg < 0) {pos += self.length}
117
if(pos >= 0 && pos < self.length){return self.charAt(pos)}
118
throw _b_.IndexError.$factory("string index out of range")
119
}
120
if(isinstance(arg, slice)) {
121
var s = _b_.slice.$conv_for_seq(arg, self.length),
122
start = s.start,
123
stop = s.stop,
124
step = s.step
125
var res = "",
127
if(step > 0){
128
if(stop <= start){return ""}
129
for(var i = start; i < stop; i += step){res += self.charAt(i)}
131
if(stop >= start){return ''}
132
for(var i = start; i > stop; i += step){res += self.charAt(i)}
140
var prefix = 2,
141
suffix = 3,
142
mask = (2 ** 32 - 1)
143
function fnv(p){
144
if(p.length == 0){
145
return 0
146
}
148
var x = prefix
149
x = (x ^ (p.charCodeAt(0) << 7)) & mask
150
for(var i = 0, len = p.length; i < len; i++){
151
x = ((1000003 * x) ^ p.charCodeAt(i)) & mask
152
}
153
x = (x ^ p.length) & mask
154
x = (x ^ suffix) & mask
212
// left adjusted
213
return s + get_char_array(padding - s.length, flags.pad_char)
214
}
215
}
216
224
if(val.__class__ === $B.long_int){
225
s = $B.long_int.to_base(val, 10)
226
}else{
227
s = val.toString()
229
if(s[0] === "-"){
230
return "-" + get_char_array(precision - s.length + 1, "0") + s.slice(1)
241
if(val === Infinity){
242
val = "inf"
243
}else if(val === -Infinity){
244
val = "-inf"
245
}else{
246
val = "nan"
268
var str_format = function(val, flags) {
269
// string format supports left and right padding
270
flags.pad_char = " " // even if 0 padding is defined, don't use it
276
if(val.__class__ === $B.long_int){
277
val = $B.long_int.to_base(val, 10)
278
}else{
279
val = parseInt(val)
297
var repr_format = function(val, flags) {
298
flags.pad_char = " " // even if 0 padding is defined, don't use it
299
return format_padding(repr(val), flags)
300
}
302
var ascii_format = function(val, flags) {
303
flags.pad_char = " " // even if 0 padding is defined, don't use it
304
return format_padding(ascii(val), flags)
305
}
317
flags.precision = parseInt(flags.precision, 10)
318
validate_precision(flags.precision)
319
}
320
return parseFloat(val)
321
}
324
var trailing_zeros = /(.*?)(0+)([eE].*)/,
325
leading_zeros = /\.(0*)/,
326
trailing_dot = /\.$/
328
var validate_precision = function(precision) {
329
// force precision to limits of javascript
334
var floating_point_format = function(val, upper, flags){
335
val = _float_helper(val, flags),
336
v = val.toString(),
337
v_len = v.length,
338
dot_idx = v.indexOf('.')
339
if(dot_idx < 0){dot_idx = v_len}
340
if(val < 1 && val > -1){
341
var zeros = leading_zeros.exec(v),
342
numzeros
343
if(zeros){
348
if(numzeros >= 4){
349
val = format_sign(val, flags) + format_float_precision(val, upper,
350
flags, _floating_g_exp_helper)
351
if(!flags.alternate){
364
return format_padding(format_sign(val, flags) +
365
format_float_precision(val, upper, flags,
366
function(val, precision) {
367
return val.toFixed(min(precision, v_len - dot_idx) +
368
numzeros)
369
}),
370
flags
371
)
372
}
373
374
if(dot_idx > flags.precision){
375
val = format_sign(val, flags) + format_float_precision(val, upper,
376
flags, _floating_g_exp_helper)
377
if(! flags.alternate){
389
return format_padding(format_sign(val, flags) +
390
format_float_precision(val, upper, flags,
391
function(val, precision) {
392
if(!flags.decimal_point){
393
precision = min(v_len - 1, 6)
394
}else if (precision > v_len){
395
if(! flags.alternate){
396
precision = v_len
397
}
399
if(precision < dot_idx){
400
precision = dot_idx
401
}
402
return val.toFixed(precision - dot_idx)
403
}),
404
flags
405
)
408
var _floating_g_exp_helper = function(val, precision, flags, upper){
409
if(precision){--precision}
412
var e_idx = val.lastIndexOf("e")
413
if(e_idx > val.length - 4){
414
val = val.substring(0, e_idx + 2) + "0" + val.substring(e_idx + 2)
417
return val
418
}
419
420
// fF
421
var floating_point_decimal_format = function(val, upper, flags) {
422
val = _float_helper(val, flags)
423
return format_padding(format_sign(val, flags) +
424
format_float_precision(val, upper, flags,
425
function(val, precision, flags) {
426
val = val.toFixed(precision)
427
if(precision === 0 && flags.alternate){
428
val += '.'
429
}
430
return val
431
}),
432
flags
433
)
434
}
435
436
var _floating_exp_helper = function(val, precision, flags, upper) {
437
val = val.toExponential(precision)
438
// pad exponent to two digits
451
return format_padding(format_sign(val, flags) +
452
format_float_precision(val, upper, flags, _floating_exp_helper), flags)
478
if(flags.alternate){
479
if(ret.charAt(0) === "-"){
480
if(upper){ret = "-0X" + ret.slice(1)}
481
else{ret = "-0x" + ret.slice(1)}
482
}else{
483
if(upper){ret = "0X" + ret}
484
else{ret = "0x" + ret}
494
if(val.__class__ === $B.long_int){
495
ret = $B.long_int.to_base(8)
496
}else{
497
ret = parseInt(val)
498
ret = ret.toString(8)
514
if(flags.alternate){
515
if(ret.charAt(0) === "-"){ret = "-0o" + ret.slice(1)}
516
else{ret = "0o" + ret}
521
var single_char_format = function(val, flags){
522
if(isinstance(val, str) && val.length == 1) return val
523
try{
531
var num_flag = function(c, flags){
532
if(c === "0" && ! flags.padding && ! flags.decimal_point && ! flags.left){
533
flags.pad_char = "0"
539
flags.precision = (flags.precision || "") + c
540
}
541
}
542
543
var decimal_point_flag = function(val, flags) {
545
// can only have one decimal point
546
throw new UnsupportedChar()
547
}
548
flags.decimal_point = true
549
}
550
551
var neg_flag = function(val, flags){
552
flags.pad_char = " " // overrides '0' flag
569
"s": str_format,
570
"d": num_format,
571
"i": num_format,
572
"u": num_format,
573
"o": octal_format,
574
"r": repr_format,
575
"a": ascii_format,
576
"g": function(val, flags){
577
return floating_point_format(val, false, flags)
578
},
579
"G": function(val, flags){return floating_point_format(val, true, flags)},
580
"f": function(val, flags){
581
return floating_point_decimal_format(val, false, flags)
582
},
583
"F": function(val, flags){
584
return floating_point_decimal_format(val, true, flags)
585
},
586
"e": function(val, flags){
587
return floating_point_exponential_format(val, false, flags)
588
},
589
"E": function(val, flags){
590
return floating_point_exponential_format(val, true, flags)
591
},
592
"x": function(val, flags){return signed_hex_format(val, false, flags)},
593
"X": function(val, flags){return signed_hex_format(val, true, flags)},
594
"c": single_char_format,
595
"0": function(val, flags){return num_flag("0", flags)},
596
"1": function(val, flags){return num_flag("1", flags)},
597
"2": function(val, flags){return num_flag("2", flags)},
598
"3": function(val, flags){return num_flag("3", flags)},
599
"4": function(val, flags){return num_flag("4", flags)},
600
"5": function(val, flags){return num_flag("5", flags)},
601
"6": function(val, flags){return num_flag("6", flags)},
602
"7": function(val, flags){return num_flag("7", flags)},
603
"8": function(val, flags){return num_flag("8", flags)},
604
"9": function(val, flags){return num_flag("9", flags)},
605
"-": neg_flag,
606
" ": space_flag,
607
"+": sign_flag,
608
".": decimal_point_flag,
609
"#": alternate_flag
610
}
611
612
// exception thrown when an unsupported char is encountered in legacy format
659
if(self === undefined){
660
throw _b_.TypeError.$factory(
661
"not enough arguments for format string")
688
throw _b_.ValueError.$factory(
689
"unsupported format character '" + invalid_char +
690
"' (0x" + invalid_char.charCodeAt(0).toString(16) +
691
") at index " + newpos)
692
}else if(err.name === "NotANumber"){
693
var try_char = s[newpos],
694
cls = self.__class__
695
if(!cls){
696
if(typeof(self) === "string"){
697
cls = "str"
698
}else{
704
throw _b_.TypeError.$factory("%" + try_char +
705
" format: a number is required, not " + cls)
706
}else{
738
}while(pos < length)
739
740
if(argpos !== null){
741
if(args.length > argpos){
742
throw _b_.TypeError.$factory(
743
"not enough arguments for format string")
744
}else if(args.length < argpos){
745
throw _b_.TypeError.$factory(
746
"not all arguments converted during string formatting")
748
}else if(nbph == 0){
749
throw _b_.TypeError.$factory(
750
"not all arguments converted during string formatting")
758
var $ = $B.args("__mul__", 2, {self: null, other: null},
759
["self", "other"], arguments, {}, null, null)
760
if(! isinstance($.other, _b_.int)){throw _b_.TypeError.$factory(
761
"Can't multiply sequence by non-int of type '" +
773
res = self.replace(/\\/g, "\\\\")
774
// special cases
775
res = res.replace(new RegExp("\u0007", "g"), "\\x07").
776
replace(new RegExp("\b", "g"), "\\x08").
777
replace(new RegExp("\f", "g"), "\\x0c").
778
replace(new RegExp("\n", "g"), "\\n").
779
replace(new RegExp("\r", "g"), "\\r").
780
replace(new RegExp("\t", "g"), "\\t")
783
if(res.search('"') == -1 && res.search("'") == -1){
784
return "'" + res + "'"
785
}else if(self.search('"') == -1){
786
return '"' + res + '"'
787
}
788
var qesc = new RegExp("'", "g") // to escape single quote
789
res = "'" + res.replace(qesc, "\\'") + "'"
793
str.__setitem__ = function(self, attr, value){
794
throw _b_.TypeError.$factory(
795
"'str' object does not support item assignment")
797
var combining = []
798
for(var cp = 0x300; cp <= 0x36F; cp++){
799
combining.push(String.fromCharCode(cp))
800
}
801
var combining_re = new RegExp("(" + combining.join("|") + ")")
813
$comp_func += "" // source code
814
var $comps = {">": "gt", ">=": "ge", "<": "lt", "<=": "le"}
823
var $notimplemented = function(self, other){
824
throw NotImplementedError.$factory(
825
"OPERATOR not implemented for class str")
828
str.capitalize = function(self){
829
var $ = $B.args("capitalize", 1, {self}, ["self"],
830
arguments, {}, null, null)
831
if(self.length == 0){return ""}
832
return self.charAt(0).toUpperCase() + self.substr(1)
833
}
834
835
str.casefold = function(self){
836
var $ = $B.args("casefold", 1, {self}, ["self"],
837
arguments, {}, null, null),
838
res = "",
839
char,
840
cf
841
for(var i = 0, len = self.length; i < len; i++){
842
char = self.charCodeAt(i)
843
cf = $B.unicode_casefold[char]
844
if(cf){
845
cf.forEach(function(cp){
846
res += String.fromCharCode(cp)
847
})
848
}else{
849
res += self.charAt(i).toLowerCase()
850
}
851
}
852
return res
853
}
855
str.center = function(){
856
var $ = $B.args("center", 3, {self: null, width: null, fillchar: null},
857
["self", "width", "fillchar"],
858
arguments, {fillchar:" "}, null, null),
859
self = $.self
871
var $ = $B.args("count", 4, {self:null, sub:null, start:null, stop:null},
872
["self", "sub", "start", "stop"], arguments, {start:null, stop:null},
880
if($.stop !== null){_slice = _b_.slice.$factory($.start, $.stop)}
881
else{_slice = _b_.slice.$factory($.start, $.self.length)}
886
if($.sub.length == 0){
887
if($.start == $.self.length){return 1}
888
else if(substr.length == 0){return 0}
889
return substr.length + 1
891
var n = 0,
892
pos = 0
893
while(pos < substr.length){
894
pos = substr.indexOf($.sub, pos)
895
if(pos >= 0){n++; pos += $.sub.length}
896
else{break}
901
str.encode = function(){
902
var $ = $B.args("encode", 3, {self: null, encoding: null, errors: null},
903
["self", "encoding", "errors"], arguments,
904
{encoding: "utf-8", errors: "strict"}, null, null)
905
if($.encoding == "rot13" || $.encoding == "rot_13"){
910
if(("a" <= char && char <= "m") || ("A" <= char && char <= "M")){
911
res += String.fromCharCode(String.charCodeAt(char) + 13)
912
}else if(("m" < char && char <= "z") ||
913
("M" < char && char <= "Z")){
914
res += String.fromCharCode(String.charCodeAt(char) - 13)
923
// Return True if the string ends with the specified suffix, otherwise
924
// return False. suffix can also be a tuple of suffixes to look for.
925
// With optional start, test beginning at that position. With optional
929
["self", "suffix", "start", "end"],
930
arguments, {start: 0, end: null}, null, null)
937
var s = $.self.substring($.start, $.end)
938
for(var i = 0, len = suffixes.length; i < len; i++){
942
if(suffix.length <= s.length &&
943
s.substr(s.length - suffix.length) == suffix){return true}
949
var $ = $B.args("expandtabs", 2, {self: null, tabsize: null},
950
["self", "tabsize"], arguments, {tabsize: 8}, null, null)
951
var s = $B.$GetInt($.tabsize),
952
col = 0,
953
pos = 0,
954
res = ""
955
if(s == 1){return self.replace(/\t/g," ")}
956
while(pos < self.length){
964
res += car
965
col = 0
966
break
967
default:
968
res += car
969
col++
970
break
971
}
972
pos++
973
}
979
// Return the lowest index in the string where substring sub is found,
980
// such that sub is contained in the slice s[start:end]. Optional
981
// arguments start and end are interpreted as in slice notation.
984
{self: null, sub: null, start: null, end: null},
985
["self", "sub", "start", "end"],
986
arguments, {start: 0, end: null}, null, null)
990
if(!isinstance($.start, _b_.int)||!isinstance($.end, _b_.int)){
991
throw _b_.TypeError.$factory("slice indices must be " +
992
"integers or None or have an __index__ method")}
993
// Can't use string.substring(start, end) because if end < start,
994
// Javascript transforms it into substring(end, start)...
995
var s = ""
996
for(var i = $.start; i < $.end; i++){
997
s += $.self.charAt(i)
998
}
1000
if($.sub.length == 0 && $.start == $.self.length){return $.self.length}
1001
if(s.length + $.sub.length == 0){return -1}
1003
var last_search = s.length - $.sub.length
1004
for(var i = 0; i <= last_search; i++){
1005
if(s.substr(i, $.sub.length) == $.sub){return $.start + i}
1016
// a.x[z]!r:...
1017
// the object has attributes :
1018
// - name : "a"
1019
// - name_ext : [".x", "[z]"]
1020
// - conv : r
1021
// - spec : rest of string after :
1029
// No : in the string : it only contains a name
1030
name = fmt_string
1031
}else{
1032
// name is before the first ":"
1033
// spec (the format specification) is after
1034
name = elts[0]
1038
var elts = name.split("!")
1039
if(elts.length > 1){
1040
name = elts[0]
1041
conv = elts[1] // conversion flag
1045
// "name' may be a subscription or attribute
1046
// Put these "extensions" in the list "name_ext"
1047
function name_repl(match){
1048
name_ext.push(match)
1050
}
1051
var name_ext_re = /\.[_a-zA-Z][_a-zA-Z0-9]*|\[[_a-zA-Z][_a-zA-Z0-9]*\]|\[[0-9]+\]/g
1052
name = name.replace(name_ext_re, name_repl)
1053
}
1060
// Parse self to detect formatting instructions
1061
// Create a list "parts" made of sections of the string :
1062
// - elements of even rank are literal text
1063
// - elements of odd rank are "format objects", built from the
1064
// format strings in self (of the form {...})
1075
text += "{"
1076
pos += 2
1077
}else if(car == "}" && self.charAt(pos + 1) == "}"){
1084
// Store current literal text
1085
parts.push(text)
1086
1087
// Search the end of the format string, ie the } closing the
1088
// opening {. Since the string can contain other pairs {} for
1089
// nested formatting, an integer nb is incremented for each { and
1090
// decremented for each } ; the end of the format string is
1091
// reached when nb == 0
1092
var end = pos + 1,
1093
nb = 1
1094
while(end < _len){
1095
if(self.charAt(end) == "{"){nb++; end++}
1096
else if(self.charAt(end) == "}"){
1097
nb--; end++
1098
if(nb == 0){
1103
var fmt_obj = $B.parse_format(fmt_string)
1104
fmt_obj.raw_name = fmt_obj.name
1105
fmt_obj.raw_spec = fmt_obj.spec
1140
return parts
1141
}
1142
1143
str.format = function(self) {
1144
var $ = $B.args("format", 1, {self: null}, ["self"],
1145
arguments, {}, "$args", "$kw")
1146
1147
var parts = $B.split_format($.self)
1148
1159
1160
if(fmt.spec !== undefined){
1161
// "spec" may contain "nested replacement fields"
1162
// In this case, evaluate them using the positional
1163
// or keyword arguments passed to format()
1164
function replace_nested(name, key){
1165
if(/\d+/.exec(key)){
1166
// If key is numeric, search in positional
1167
// arguments
1168
return _b_.tuple.__getitem__($.$args,
1169
parseInt(key))
1170
}else{
1171
// Else try in keyword arguments
1172
return _b_.dict.__getitem__($.$kw, key)
1173
}
1174
}
1175
fmt.spec = fmt.spec.replace(/\{(.*?)\}/g,
1176
replace_nested)
1177
}
1179
// Numerical reference : use positional arguments
1180
var pos = parseInt(fmt.name),
1190
// Attribute
1191
value = _b_.getattr(value, ext.substr(1))
1192
}else{
1193
// Subscription
1196
if(key.charAt(0).search(/\d/) > -1){key = parseInt(key)}
1197
value = _b_.getattr(value, "__getitem__")(key)
1201
// If the conversion flag is set, first call a function to convert
1202
// the value
1203
if(fmt.conv == "a"){value = _b_.ascii(value)}
1204
else if(fmt.conv == "r"){value = _b_.repr(value)}
1205
else if(fmt.conv == "s"){value = _b_.str.$factory(value)}
1219
throw NotImplementedError.$factory(
1220
"function format_map not implemented yet")
1231
/* Return true if the string is empty or all characters in the string are
1232
ASCII, false otherwise. ASCII characters have code points in the range
1233
U+0000-U+007F. */
1234
for(var i = 0, len = self.length; i < len; i++){
1235
if(self.charCodeAt(i) > 127){return false}
1236
}
1237
return true
1238
}
1239
1240
str.isalnum = function(self){
1241
/* Return true if all characters in the string are alphanumeric and there
1242
is at least one character, false otherwise. A character c is alphanumeric
1243
if one of the following returns True: c.isalpha(), c.isdecimal(),
1244
c.isdigit(), or c.isnumeric(). */
1245
var $ = $B.args("isalnum", 1, {self: null}, ["self"],
1246
arguments, {}, null, null),
1247
char
1248
for(var i = 0, len = self.length; i < len; i++){
1249
char = self.charCodeAt(i)
1250
if(unicode_tables.Ll[char] ||
1251
unicode_tables.Lu[char] ||
1252
unicode_tables.Lm[char] ||
1253
unicode_tables.Lt[char] ||
1254
unicode_tables.Lo[char] ||
1255
unicode_tables.Nd[char] ||
1256
unicode_tables.digits[char] ||
1257
unicode_tables.numeric[char]){
1258
continue
1259
}
1260
return false
1261
}
1262
return true
1263
}
1264
1265
str.isalpha = function(self){
1266
/* Return true if all characters in the string are alphabetic and there is
1267
at least one character, false otherwise. Alphabetic characters are those
1268
characters defined in the Unicode character database as "Letter", i.e.,
1269
those with general category property being one of "Lm", "Lt", "Lu", "Ll",
1270
or "Lo". */
1271
var $ = $B.args("isalpha", 1, {self: null}, ["self"],
1272
arguments, {}, null, null),
1273
char
1274
for(var i = 0, len = self.length; i < len; i++){
1275
char = self.charCodeAt(i)
1276
if(unicode_tables.Ll[char] ||
1277
unicode_tables.Lu[char] ||
1278
unicode_tables.Lm[char] ||
1279
unicode_tables.Lt[char] ||
1280
unicode_tables.Lo[char]){
1281
continue
1282
}
1283
return false
1284
}
1285
return true
1286
}
1287
1288
str.isdecimal = function(self){
1289
/* Return true if all characters in the string are decimal characters and
1290
there is at least one character, false otherwise. Decimal characters are
1291
those that can be used to form numbers in base 10, e.g. U+0660,
1292
ARABIC-INDIC DIGIT ZERO. Formally a decimal character is a character in
1293
the Unicode General Category "Nd". */
1294
var $ = $B.args("isdecimal", 1, {self: null}, ["self"],
1295
arguments, {}, null, null),
1296
char
1297
for(var i = 0, len = self.length; i < len; i++){
1298
char = self.charCodeAt(i)
1299
if(! unicode_tables.Nd[char]){
1300
return false
1301
}
1302
}
1303
return self.length > 0
1304
}
1305
1306
str.isdigit = function(self){
1307
/* Return true if all characters in the string are digits and there is at
1308
least one character, false otherwise. */
1309
var $ = $B.args("isdigit", 1, {self: null}, ["self"],
1310
arguments, {}, null, null),
1311
char
1312
for(var i = 0, len = self.length; i < len; i++){
1313
char = self.charCodeAt(i)
1314
if(! unicode_tables.digits[char]){
1315
return false
1316
}
1317
}
1318
return self.length > 0
1319
}
1320
1321
str.isidentifier = function(self){
1322
/* Return true if the string is a valid identifier according to the
1323
language definition. */
1324
var $ = $B.args("isidentifier", 1, {self: null}, ["self"],
1325
arguments, {}, null, null),
1326
char
1327
if(self.length == 0){return false}
1328
else if(unicode_tables.XID_Start[self.charCodeAt(0)] === undefined){
1329
return false
1330
}else{
1331
for(var i = 1, len = self.length; i < len; i++){
1332
if(unicode_tables.XID_Continue[self.charCodeAt(i)] === undefined){
1333
return false
1334
}
1335
}
1336
}
1337
return true
1338
}
1339
1340
str.islower = function(self){
1341
/* Return true if all cased characters 4 in the string are lowercase and
1342
there is at least one cased character, false otherwise. */
1343
var $ = $B.args("islower", 1, {self: null}, ["self"],
1344
arguments, {}, null, null),
1345
has_cased = false,
1346
char
1347
1348
for(var i = 0, len = self.length; i < len; i++){
1349
char = self.charCodeAt(i)
1350
if(unicode_tables.Ll[char]){has_cased = true; continue}
1351
else if(unicode_tables.Lu[char] || unicode_tables.Lt[char]){
1352
return false
1353
}
1354
}
1355
return has_cased
1356
}
1357
1358
str.isnumeric = function(self){
1359
/* Return true if all characters in the string are numeric characters, and
1360
there is at least one character, false otherwise. Numeric characters
1361
include digit characters, and all characters that have the Unicode numeric
1362
value property, e.g. U+2155, VULGAR FRACTION ONE FIFTH. Formally, numeric
1363
characters are those with the property value Numeric_Type=Digit,
1364
Numeric_Type=Decimal or Numeric_Type=Numeric.*/
1365
var $ = $B.args("isnumeric", 1, {self: null}, ["self"],
1366
arguments, {}, null, null)
1367
for(var i = 0, len = self.length; i < len; i++){
1368
if(! unicode_tables.numeric[self.charCodeAt(i)]){
1369
return false
1370
}
1371
}
1372
return self.length > 0
1373
}
1374
1375
var printable,
1376
printable_gc = ['Cc', 'Cf', 'Co', 'Cs','Zl', 'Zp', 'Zs']
1377
1378
str.isprintable = function(self){
1379
/* Return true if all characters in the string are printable or the string
1380
is empty, false otherwise. Nonprintable characters are those characters
1381
defined in the Unicode character database as "Other" or "Separator",
1382
excepting the ASCII space (0x20) which is considered printable. */
1383
1384
// Set printable if not set yet
1385
if(printable === undefined){
1386
for(var i = 0; i < printable_gc.length; i++){
1387
var table = unicode_tables[printable_gc[i]]
1388
for(var cp in table){
1389
printable[cp] = true
1390
}
1391
}
1392
printable[32] = true
1393
}
1394
1395
var $ = $B.args("isprintable", 1, {self: null}, ["self"],
1396
arguments, {}, null, null),
1397
char,
1398
flag
1399
for(var i = 0, len = self.length; i < len; i++){
1400
char = self.charCodeAt(i)
1401
if(! printable[char]){
1402
return false
1403
}
1404
}
1405
return true
1406
}
1407
1408
str.isspace = function(self){
1409
/* Return true if there are only whitespace characters in the string and
1410
there is at least one character, false otherwise.
1411
1412
A character is whitespace if in the Unicode character database, either its
1413
general category is Zs ("Separator, space"), or its bidirectional class is
1414
one of WS, B, or S.*/
1415
var $ = $B.args("isspace", 1, {self: null}, ["self"],
1416
arguments, {}, null, null),
1417
char
1418
for(var i = 0, len = self.length; i < len; i++){
1419
char = self.charCodeAt(i)
1420
if(! unicode_tables.Zs[char] &&
1421
$B.unicode_bidi_whitespace.indexOf(char) == -1){
1422
return false
1423
}
1424
}
1425
return self.length > 0
1426
}
1427
1428
str.istitle = function(self){
1429
/* Return true if the string is a titlecased string and there is at least
1430
one character, for example uppercase characters may only follow uncased
1431
characters and lowercase characters only cased ones. Return false
1432
otherwise. */
1433
var $ = $B.args("istitle", 1, {self: null}, ["self"],
1434
arguments, {}, null, null)
1435
return self.length > 0 && str.title(self) == self
1436
}
1437
1438
str.isupper = function(self){
1439
/* Return true if all cased characters 4 in the string are lowercase and
1440
there is at least one cased character, false otherwise. */
1441
var $ = $B.args("islower", 1, {self: null}, ["self"],
1442
arguments, {}, null, null),
1443
has_cased = false,
1444
char
1445
1446
for(var i = 0, len = self.length; i < len; i++){
1447
char = self.charCodeAt(i)
1448
if(unicode_tables.Lu[char]){has_cased = true; continue}
1449
else if(unicode_tables.Ll[char] || unicode_tables.Lt[char]){
1467
if(! isinstance(obj2, str)){throw _b_.TypeError.$factory(
1468
"sequence item " + count + ": expected str instance, " +
1482
var $ = $B.args("ljust", 3, {self: null, width: null, fillchar:null},
1483
["self", "width", "fillchar"],
1484
arguments, {fillchar: " "}, null, null)
1490
str.lower = function(self){
1491
var $ = $B.args("lower", 1, {self: null}, ["self"],
1492
arguments, {}, null, null)
1493
return self.toLowerCase()
1494
}
1495
1497
var $ = $B.args("lstrip", 2, {self: null, chars: null}, ["self", "chars"],
1498
arguments, {chars:_b_.None}, null, null)
1499
if($.chars === _b_.None){return $.self.trimLeft()}
1500
for(var i = 0; i < $.self.length; i++){
1501
if($.chars.indexOf($.self.charAt(i)) === -1){
1502
return $.self.substring(i)
1510
var $ = $B.args("maketrans", 3, {x: null, y: null, z: null},
1511
["x", "y", "z"], arguments, {y: null, z: null}, null, null)
1516
// If there is only one argument, it must be a dictionary mapping
1517
// Unicode ordinals (integers) or characters (strings of length 1) to
1518
// Unicode ordinals, strings (of arbitrary lengths) or None. Character
1520
if(! _b_.isinstance($.x, _b_.dict)){
1521
throw _b_.TypeError.$factory(
1522
"maketrans only argument must be a dict")
1525
for(var i = 0, len = items.length; i < len; i++){
1526
var k = items[i][0],
1527
v = items[i][1]
1528
if(! _b_.isinstance(k, _b_.int)){
1529
if(_b_.isinstance(k, _b_.str) && k.length == 1){
1530
k = _b_.ord(k)
1531
}else{throw _b_.TypeError.$factory("dictionary key " + k +
1534
if(v !== _b_.None && ! _b_.isinstance(v, [_b_.int, _b_.str])){
1535
throw _b_.TypeError.$factory("dictionary value " + v +
1543
// and in the resulting dictionary, each character in x will be mapped
1544
// to the character at the same position in y
1547
}else if($.x.length !== $.y.length){
1548
throw _b_.TypeError.$factory(
1549
"maketrans arguments must be strings or same length")
1555
if(! _b_.isinstance($.z, _b_.str)){
1556
throw _b_.TypeError.$factory(
1557
"maketrans third argument must be a string")
1579
var $ = $B.args("partition", 2, {self: null, sep: null}, ["self", "sep"],
1580
arguments, {}, null, null)
1585
return _b_.tuple.$factory([$.self.substring(0, i), $.sep,
1586
$.self.substring(i + $.sep.length)])
1587
}
1588
1589
function $re_escape(str){
1590
var specials = "[.*+?|()$^"
1591
for(var i = 0, len = specials.length; i < len; i++){
1592
var re = new RegExp("\\"+specials.charAt(i), "g")
1593
str = str.replace(re, "\\"+specials.charAt(i))
1594
}
1595
return str
1602
var $ = $B.args("replace", 4,
1603
{self: null, old: null, $$new: null, count: null},
1604
["self", "old", "$$new", "count"],
1605
arguments, {count: -1}, null, null),
1606
count = $.count,
1607
self = $.self,
1608
old = $.old,
1609
_new = $.$$new
1616
"' object cannot be interpreted as an integer")
1617
}else if(isinstance(count, _b_.float)){
1618
throw _b_.TypeError.$factory("integer argument expected, got float")
1619
}
1620
if(count == 0){return self}
1621
if(count.__class__ == $B.long_int){count = parseInt(count.value)}
1622
if(old == ""){
1623
if(_new == ""){return self}
1624
if(self == ""){return _new}
1625
var elts = self.split("")
1626
if(count > -1 && elts.length >= count){
1627
var rest = elts.slice(count).join("")
1628
return _new + elts.slice(0, count).join(_new) + rest
1629
}else{return _new + elts.join(_new) + _new}
1644
if(count < 0){count = res.length}
1645
while(count > 0){
1646
pos = res.indexOf(old, pos)
1647
if(pos < 0){break}
1648
res = res.substr(0, pos) + _new + res.substr(pos + old.length)
1649
pos = pos + _new.length
1650
count--
1656
// Return the highest index in the string where substring sub is found,
1657
// such that sub is contained within s[start:end]. Optional arguments
1659
if(arguments.length == 2 && typeof substr == "string"){
1660
return self.lastIndexOf(substr)
1661
}
1663
{self: null, sub: null, start: null, end: null},
1664
["self", "sub", "start", "end"],
1665
arguments, {start: 0, end: null}, null, null)
1677
for(var i = $.end - sublen; i >= $.start; i--){
1678
if($.self.substr(i, sublen) == $.sub){return i}
1685
var res = str.rfind.apply(null, arguments)
1686
if(res == -1){throw _b_.ValueError.$factory("substring not found")}
1691
var $ = $B.args("rjust",3,
1692
{self: null, width: null, fillchar: null},
1693
["self", "width", "fillchar"],
1694
arguments, {fillchar: " "}, null, null)
1702
var $ = $B.args("rpartition", 2, {self: null, sep: null}, ["self", "sep"],
1703
arguments, {}, null, null)
1707
var items = str.partition(self, sep).reverse()
1708
for(var i = 0; i < items.length; i++){
1709
items[i] = items[i].split("").reverse().join("")
1715
var $ = $B.args("rsplit", 3, {self: null, sep: null, maxsplit: null},
1716
["self", "sep", "maxsplit"], arguments,
1717
{sep: _b_.None, maxsplit: -1}, null, null),
1718
sep = $.sep
1721
var rev_str = reverse($.self),
1722
rev_sep = sep === _b_.None ? sep : reverse($.sep),
1733
str.rstrip = function(self, x){
1734
var $ = $B.args("rstrip", 2, {self: null, chars: null}, ["self", "chars"],
1735
arguments, {chars: _b_.None}, null, null)
1736
if($.chars === _b_.None){return $.self.trimRight()}
1738
if($.chars.indexOf($.self.charAt(j)) == -1){
1739
return $.self.substring(0, j + 1)
1746
var $ = $B.args("split", 3, {self: null, sep: null, maxsplit: null},
1747
["self", "sep", "maxsplit"], arguments,
1748
{sep: _b_.None, maxsplit: -1}, null, null),
1749
sep = $.sep,
1750
maxsplit = $.maxsplit,
1751
self = $.self,
1752
pos = 0
1753
if(maxsplit.__class__ === $B.long_int){maxsplit = parseInt(maxsplit.value)}
1754
if(sep == ""){throw _b_.ValueError.$factory("empty separator")}
1755
if(sep === _b_.None){
1757
while(pos < self.length && self.charAt(pos).search(/\s/) > -1){pos++}
1758
if(pos === self.length - 1){return [self]}
1759
var name = ""
1761
if(self.charAt(pos).search(/\s/) == -1){
1762
if(name == ""){name = self.charAt(pos)}
1763
else{name += self.charAt(pos)}
1783
var res = [],
1784
s = "",
1785
seplen = sep.length
1786
if(maxsplit == 0){return [self]}
1787
while(pos < self.length){
1788
if(self.substr(pos, seplen) == sep){
1808
["self", "keepends"], arguments, {keepends: false}, null, null)
1809
if(! _b_.isinstance($.keepends, [_b_.bool, _b_.int])){
1810
throw _b_.TypeError.$factory("integer argument expected, got " +
1817
start = pos,
1818
pos = 0,
1819
self = $.self
1820
while(pos < self.length){
1821
if(self.substr(pos, 2) == "\r\n"){
1822
res.push(self.substring(start, pos + 2))
1823
start = pos + 2
1825
}else if(self.charAt(pos) == "\r" || self.charAt(pos) == "\n"){
1826
res.push(self.substring(start, pos + 1))
1827
start = pos + 1
1828
pos = start
1829
}else{pos++}
1830
}
1831
var rest = self.substr(start)
1832
if(rest){res.push(rest)}
1833
return res
1834
}else{
1841
// Return True if string starts with the prefix, otherwise return False.
1842
// prefix can also be a tuple of prefixes to look for. With optional
1843
// start, test string beginning at that position. With optional end,
1845
var $ = $B.args("startswith", 4,
1846
{self: null, prefix: null, start: null, end: null},
1847
["self", "prefix", "start", "end"],
1848
arguments, {start: 0, end: null}, null, null)
1855
var s = $.self.substring($.start, $.end)
1856
for(var i = 0, len = prefixes.length; i < len; i++){
1867
var $ = $B.args("strip", 2, {self: null, chars: null}, ["self", "chars"],
1868
arguments, {chars: _b_.None}, null, null)
1869
if($.chars === _b_.None){return $.self.trim()}
1870
for(var i = 0; i < $.self.length; i++){
1871
if($.chars.indexOf($.self.charAt(i)) == -1){
1872
break
1875
for(var j = $.self.length - 1; j >= i; j--){
1876
if($.chars.indexOf($.self.charAt(j)) == -1){
1877
break
1883
str.swapcase = function(self){
1884
var $ = $B.args("swapcase", 1, {self}, ["self"],
1885
arguments, {}, null, null),
1886
res = "",
1887
char
1888
1889
for(var i = 0, len = self.length; i < len; i++){
1890
char = self.charCodeAt(i)
1891
if(unicode_tables.Ll[char]){
1892
res += self.charAt(i).toUpperCase()
1893
}else if(unicode_tables.Lu[char]){
1894
res += self.charAt(i).toLowerCase()
1895
}else{
1896
res += self.charAt(i)
1897
}
1898
}
1899
return res
1900
}
1901
1902
str.title = function(self){
1903
var $ = $B.args("title", 1, {self}, ["self"],
1904
arguments, {}, null, null),
1905
state,
1906
char,
1907
res = ""
1908
for(var i = 0, len = self.length; i < len; i++){
1909
char = self.charCodeAt(i)
1910
if(unicode_tables.Ll[char]){
1911
if(! state){
1912
res += self.charAt(i).toUpperCase()
1913
state = "word"
1914
}else{
1915
res += self.charAt(i)
1916
}
1917
}else if(unicode_tables.Lu[char] || unicode_tables.Lt[char]){
1918
res += state ? self.charAt(i).toLowerCase() : self.charAt(i)
1919
state = "word"
1920
}else{
1921
state = null
1922
res += self.charAt(i)
1923
}
1924
}
1925
return res
1926
}
1927
1930
getitem = $B.$getattr(table, "__getitem__")
1931
for(var i = 0, len = self.length; i < len; i++){
1932
try{
1933
var repl = getitem(self.charCodeAt(i))
1934
if(repl !== _b_.None){
1944
str.upper = function(self){
1945
var $ = $B.args("upper", 1, {self: null}, ["self"],
1946
arguments, {}, null, null)
1947
return self.toUpperCase()
1948
}
1949
1952
["self", "width"], arguments, {}, null, null)
1953
if($.width <= self.length){return self}
1955
case "+":
1956
case "-":
1957
return self.charAt(0) +
1958
"0".repeat($.width - self.length) + self.substr(1)
1966
if(arg === undefined){
1967
throw _b_.TypeError.$factory("str() argument is undefined")
1968
}
1969
if(encoding !== undefined){
1970
// Arguments may be passed as keywords (cf. issue #1060)
1971
var $ = $B.args("str", 3, {arg: null, encoding: null, errors: null},
1972
["arg", "encoding", "errors"], arguments,
1973
{encoding: "utf-8", errors: "strict"}, null, null),
1974
encoding = $.encoding,
1975
errors = $.errors
1976
}
1987
// class or its subclasses, but the attribute __str__ of the
1988
// class metaclass (usually "type") or its subclasses (usually
1989
// "object")
1990
// The metaclass is the attribute __class__ of the class dictionary
1995
if(arg.__class__ && arg.__class__ === _b_.bytes &&
1996
encoding !== undefined){
1997
// str(bytes, encoding, errors) is equal to
1998
// bytes.decode(encoding, errors)
2001
// Implicit invocation of __str__ uses method __str__ on the class,
2002
// even if arg has an attribute __str__
2003
var klass = arg.__class__ || $B.get_class(arg)
2004
var method = $B.$getattr(klass , "__str__", null)
2005
if(method === null ||
2006
// if not better than object.__str__, try __repr__
2007
(arg.__class__ && arg.__class__ !== _b_.object &&
2008
method.$infos && method.$infos.__func__ === _b_.object.__str__)){
2009
var method = $B.$getattr(klass, "__repr__")
2015
if($B.debug > 1){console.log(err)}
2016
console.log("Warning - no method __str__ or __repr__, " +
2017
"default to toString", arg)
2024
if(cls === undefined){
2025
throw _b_.TypeError.$factory("str.__new__(): not enough arguments")
2049
var args = [],
2050
pos = 0
2051
if(arguments.length > 0){
2052
var args = [arguments[0].valueOf()],
2053
pos = 1
2054
for(var i = 1, len = arguments.length; i < len; i++){
2055
args[pos++] = arguments[i]
2071
// Function to parse the 2nd argument of format()
2072
$B.parse_format_spec = function(spec){
2075
var pos = 0,
2076
aligns = "<>=^",
2077
digits = "0123456789",
2078
types = "bcdeEfFgGnosxX%",
2080
if(align_pos != -1){
2081
if(spec.charAt(1) && aligns.indexOf(spec.charAt(1)) != -1){
2082
// If the second char is also an alignment specifier, the
2083
// first char is the fill value
2084
this.fill = spec.charAt(0)
2085
this.align = spec.charAt(1)
2086
pos = 2
2087
}else{
2088
// The first character defines alignment : fill defaults to ' '
2103
if(car == "+" || car == "-" || car == " "){
2104
this.sign = car
2105
pos++
2106
car = spec.charAt(pos)
2108
if(car == "#"){this.alternate = true; pos++; car = spec.charAt(pos)}
2109
if(car == "0"){
2118
while(car && digits.indexOf(car) > -1){
2119
if(this.width === undefined){this.width = car}
2120
else{this.width += car}
2121
pos++
2122
car = spec.charAt(pos)
2125
if(this.width === undefined && car == "{"){
2126
// Width is determined by a parameter
2127
var end_param_pos = spec.substr(pos).search("}")
2128
this.width = spec.substring(pos, end_param_pos)
2129
console.log("width", "[" + this.width + "]")
2130
pos += end_param_pos + 1
2131
}
2132
if(car == ","){this.comma = true; pos++; car = spec.charAt(pos)}
2133
if(car == "."){
2134
if(digits.indexOf(spec.charAt(pos + 1)) == -1){
2135
throw _b_.ValueError.$factory(
2136
"Missing precision in format spec")
2138
this.precision = spec.charAt(pos + 1)
2139
pos += 2
2140
car = spec.charAt(pos)
2141
while(car && digits.indexOf(car) > -1){
2148
if(car && types.indexOf(car) > -1){
2149
this.type = car
2150
pos++
2151
car = spec.charAt(pos)
2152
}
2153
if(pos !== spec.length){
2159
return (this.fill === undefined ? "" : _b_.str.$factory(this.fill)) +
2160
(this.align || "") +
2161
(this.sign || "") +
2162
(this.alternate ? "#" : "") +
2163
(this.sign_aware ? "0" : "") +
2164
(this.width || "") +
2165
(this.comma ? "," : "") +
2166
(this.precision ? "." + this.precision : "") +
2167
(this.type || "")
2172
if(fmt.width && s.length < fmt.width){
2173
var fill = fmt.fill || " ",
2174
align = fmt.align || "<",
2175
missing = fmt.width - s.length
2177
case "<":
2178
return s + fill.repeat(missing)
2179
case ">":
2180
return fill.repeat(missing) + s
2181
case "=":
2182
if("+-".indexOf(s.charAt(0)) > -1){
2183
return s.charAt(0) + fill.repeat(missing) + s.substr(1)
2187
case "^":
2188
var left = parseInt(missing / 2)
2189
return fill.repeat(left) + s + fill.repeat(missing - left)
2202
$B.parse_fstring = function(string){
2203
// Parse a f-string
2204
var elts = [],
2205
pos = 0,
2229
}else{
2230
throw Error(" f-string: single '}' is not allowed")
2231
}
2232
}else{
2254
current += car
2255
i += 2
2256
}else{
2257
throw Error(" f-string: single '}' is not allowed")
2258
}
2259
}else{
2260
current += car
2261
i++
2262
}
2263
}
2265
}else if(ctype == "debug"){
2266
// after the equal sign, whitespace are ignored and the only
2267
// valid characters are } and :
2268
while(string.charAt(i) == " "){i++}
2269
if(string.charAt(i) == "}"){
2270
// end of debug expression
2271
elts.push(current)
2272
ctype = null
2273
current = ""
2274
pos = i + 1
2275
}
2276
}else{
2277
// End of expression is the } matching the opening {
2278
// There may be nested braces
2279
var i = pos,
2280
nb_braces = 1,
2302
// backslash is not allowed in expressions
2303
throw Error("f-string expression part cannot include a" +
2304
" backslash")
2311
throw Error("f-string: invalid conversion character:" +
2312
" expected 's', 'r', or 'a'")
2313
}else{
2327
if(string.substr(i, 3) == '"""'){
2328
var end = string.indexOf('"""', i + 3)
2329
if(end == -1){
2330
throw Error("f-string: unterminated string")
2331
}else{
2332
var trs = string.substring(i, end + 3)
2333
trs = trs.replace("\n", "\\n\\")
2338
var end = string.indexOf('"', i + 1)
2339
if(end == -1){
2340
throw Error("f-string: unterminated string")
2341
}else{
2342
current.expression += string.substring(i, end + 1)
2343
i = end + 1
2350
}else if(car == "="){
2351
// might be a "debug expression", eg f"{x=}"
2352
var ce = current.expression
2353
if(ce.length == 0 ||
2355
current.expression += car
2356
i++
2357
}else{
2358
// add debug string
2359
tail = car
2360
while(string.charAt(i + 1).match(/\s/)){
2361
tail += string.charAt(i + 1)
2362
i++
2363
}
2364
elts.push(current.expression + tail)
2365
// remove trailing whitespace from expression
2366
while(ce.match(/\s$/)){
2367
ce = ce.substr(0, ce.length - 1)
2368
}
2369
current.expression = ce
2370
ctype = "debug"
2371
i++
2372
}