1implement Ecmascript; 2 3include "sys.m"; 4include "math.m"; 5include "string.m"; 6include "daytime.m"; 7include "ecmascript.m"; 8 9include "pprint.b"; 10include "obj.b"; 11include "exec.b"; 12include "date.b"; 13include "builtin.b"; 14include "regexp.b"; 15include "uri.b"; 16 17FF: con '\u000c'; 18LS: con '\u2028'; 19PS: con '\u2029'; 20 21islt(c: int): int 22{ 23 return c == '\n' || c == '\r' || c == LS || c == PS; 24} 25 26me: ESHostobj; 27 28sys: Sys; 29print, sprint: import sys; 30stdout: ref Sys->FD; 31 32math: Math; 33 isnan, floor, copysign, fabs, fmod, NaN, Infinity: import math; 34 35str: String; 36 37daytime: Daytime; 38 Tm: import daytime; 39 40labrec: adt{ 41 s: string; # name 42 k: int; # kind 43}; 44 45HashSize: con 1024; 46 47Parser: adt 48{ 49 ex: ref Exec; 50 51 code: ref Code; 52 53 inloop: int; # parser state 54 incase: int; 55 infunc: int; 56 lastnl: int; # parser state for inserting ; 57 notin: int; # don't allow `in' in expression 58 59 token: int; # lexical token 60 token1: int; # lexical token 61 id: int; # associated value 62 lineno: int; 63 64 src: string; # lexical input state 65 esrc: int; 66 srci: int; 67 68 errors: int; 69 labs: list of ref labrec; 70}; 71 72Keywd: adt 73{ 74 name: string; 75 token: int; 76}; 77 78# 79# lexical tokens and ops 80# 81 Lbase: con 128; 82 83 Leos, 84 85 Landas, 86 Loras, 87 Lxoras, 88 Llshas, 89 Lrshas, 90 Lrshuas, 91 Laddas, 92 Lsubas, 93 Lmulas, 94 Ldivas, 95 Lmodas, 96 Loror, 97 Landand, 98 Leq, 99 Lneq, 100 Lleq, 101 Lgeq, 102 Llsh, 103 Lrsh, 104 Lrshu, 105 Linc, 106 Ldec, 107 Lnum, 108 Lid, 109 Lstr, 110 Lthis, 111 Ltypeof, 112 Ldelete, 113 Lvoid, 114 Lwhile, 115 Lfor, 116 Lbreak, 117 Lcontinue, 118 Lwith, 119 Lreturn, 120 Lfunction, 121 Lvar, 122 Lif, 123 Lelse, 124 Lin, 125 Lnew, 126 Lcase, 127 Ldefault, 128 Lswitch, 129 Ldo, 130 Linstanceof, 131 Lcatch, 132 Lfinally, 133 Lthrow, 134 Ltry, 135 Lregexp, 136 Lseq, 137 Lsne, 138 Lprint, 139 140 Lpostinc, # ops that aren't lexical tokens 141 Lpostdec, 142 Lpresub, 143 Lpreadd, 144 Lcall, 145 Lnewcall, 146 Lgetval, 147 Las, 148 Lasop, 149 Lforin, 150 Lforvar, 151 Lforvarin, 152 Larrinit, 153 Lobjinit, 154 Lnoval, 155 Llabel, 156 Lbreaklab, 157 Lcontinuelab, 158 159 # 160 # reserved words 161 # 162 Labstract, 163 Lboolean, 164 Lbyte, 165 Lchar, 166 Lclass, 167 Lconst, 168 Ldebugger, 169 Ldouble, 170 Lenum, 171 Lexport, 172 Lextends, 173 Lfinal, 174 Lfloat, 175 Lgoto, 176 Limplements, 177 Limport, 178 Lint, 179 Linterface, 180 Llong, 181 Lnative, 182 Lpackage, 183 Lprivate, 184 Lprotected, 185 Lpublic, 186 Lshort, 187 Lstatic, 188 Lsuper, 189 Lsynchronized, 190 Lthrows, 191 Ltransient, 192 Lvolatile: con Lbase + iota; 193 194 195# 196# internals 197# 198 199Mlower, Mupper, Munder, Mdigit, Msign, Mexp, Mhex, Moct: con byte 1 << iota; 200Malpha: con Mupper|Mlower|Munder; 201map := array[256] of 202{ 203 '_' or '$' => Munder, 204 '-' or '+' => Msign, 205 'a' to 'd' or 'f' => Mlower | Mhex, 206 'e' => Mlower | Mhex | Mexp, 207 'g' to 'z' => Mlower, 208 'A' to 'D' or 'F' => Mupper | Mhex, 209 'E' => Mupper | Mhex | Mexp, 210 'G' to 'Z' => Mupper, 211 '0' to '7' => Mdigit | Mhex | Moct, 212 '8' to '9' => Mdigit | Mhex, 213 * => byte 0 214}; 215 216maxerr: int; 217toterrors: int; 218fabort: int; 219 220escmap := array[] of 221{ 222 '\'' => byte '\'', 223 '"' => byte '"', 224 '\\' => byte '\\', 225 'b' => byte '\b', 226 'f' => byte FF, 227 'n' => byte '\n', 228 'r' => byte '\r', 229 't' => byte '\t', 230 'v' => byte FF, 231 232 * => byte 255 233}; 234 235# 236# must be sorted 237# 238keywords := array [] of 239{ 240 Keywd("abstract", Labstract), 241 Keywd("boolean", Lboolean), 242 Keywd("byte", Lbyte), 243 Keywd("break", Lbreak), 244 Keywd("case", Lcase), 245 Keywd("catch", Lcatch), 246 Keywd("char", Lchar), 247 Keywd("class", Lclass), 248 Keywd("const", Lconst), 249 Keywd("continue", Lcontinue), 250 Keywd("debugger", Ldebugger), 251 Keywd("default", Ldefault), 252 Keywd("delete", Ldelete), 253 Keywd("do", Ldo), 254 Keywd("double", Ldouble), 255 Keywd("else", Lelse), 256 Keywd("enum", Lenum), 257 Keywd("export", Lexport), 258 Keywd("extends ", Lextends), 259 Keywd("final", Lfinal), 260 Keywd("finally", Lfinally), 261 Keywd("float", Lfloat), 262 Keywd("for", Lfor), 263 Keywd("function", Lfunction), 264 Keywd("goto", Lgoto), 265 Keywd("if", Lif), 266 Keywd("implements", Limplements), 267 Keywd("import", Limport), 268 Keywd("in", Lin), 269 Keywd("instanceof", Linstanceof), 270 Keywd("int", Lint), 271 Keywd("interface", Linterface), 272 Keywd("long", Llong), 273 Keywd("native", Lnative), 274 Keywd("new", Lnew), 275 Keywd("package", Lpackage), 276 # Keywd("print", Lprint), 277 Keywd("private", Lprivate), 278 Keywd("protected", Lprotected), 279 Keywd("public", Lpublic), 280 Keywd("return", Lreturn), 281 Keywd("short", Lshort), 282 Keywd("static", Lstatic), 283 Keywd("super", Lsuper), 284 Keywd("switch", Lswitch), 285 Keywd("synchronized", Lsynchronized), 286 Keywd("this", Lthis), 287 Keywd("throw", Lthrow), 288 Keywd("throws", Lthrows), 289 Keywd("transient", Ltransient), 290 Keywd("try", Ltry), 291 Keywd("typeof", Ltypeof), 292 Keywd("var", Lvar), 293 Keywd("void", Lvoid), 294 Keywd("volatile", Lvolatile), 295 Keywd("while", Lwhile), 296 Keywd("with", Lwith), 297}; 298 299debug = array[256] of {* => 0}; 300 301glbuiltins := array[] of 302{ 303 Builtin("eval", "eval", array[] of {"src"}, 1), 304 Builtin("parseInt", "parseInt", array[] of {"string", "radix"}, 2), 305 Builtin("parseFloat", "parseFloat", array[] of {"string"}, 1), 306 Builtin("escape", "escape", array[] of {"string"}, 1), 307 Builtin("unescape", "unescape", array[] of {"string"}, 1), 308 Builtin("isNaN", "isNaN", array[] of {"number"}, 1), 309 Builtin("isFinite", "isFinite", array[] of {"number"}, 1), 310 Builtin("decodeURI", "decodeURI", array[] of {"string"}, 1), 311 Builtin("decodeURIComponent", "decodeURIComponent", array[] of {"string"}, 1), 312 Builtin("encodeURI", "encodeURI", array[] of {"string"}, 1), 313 Builtin("encodeURIComponent", "encodeURIComponent", array[] of {"string"}, 1), 314}; 315 316biobj := Builtin("Object", "Object", array[] of {"value"}, 1); 317biobjproto := array[] of 318{ 319 Builtin("toString", "Object.prototype.toString", nil, 0), 320 Builtin("toLocaleString", "Object.prototype.toLocaleString", nil, 0), 321 Builtin("valueOf", "Object.prototype.valueOf", nil, 0), 322 Builtin("hasOwnProperty", "Object.prototype.hasOwnProperty", array[] of {"V"}, 1), 323 Builtin("isPrototypeOf", "Object.prototype.isPrototypeOf", array[] of {"V"}, 1), 324 Builtin("propertyisEnumerable", "Object.prototype.propertyisEnumerable", array[] of {"V"}, 1), 325}; 326 327bifunc := Builtin("Function", "Function", array[] of {"body"}, 1); 328bifuncproto := array[] of 329{ 330 Builtin("toString", "Function.prototype.toString", nil, 0), 331 Builtin("apply", "Function.prototype.apply", array[] of {"this", "array"}, 2), 332 Builtin("call", "Function.prototype.call", array[] of {"this", "arg"}, 1), 333}; 334 335bierr := Builtin("Error", "Error", array[] of {"message"}, 1); 336bierrproto := array[] of 337{ 338 Builtin("toString", "Error.prototype.toString", nil , 0), 339}; 340 341biarray := Builtin("Array", "Array", array[] of {"length"}, 1); 342biarrayproto := array[] of 343{ 344 Builtin("toString", "Array.prototype.toString", nil, 0), 345 Builtin("toLocaleString", "Array.prototype.toLocaleString", nil, 0), 346 Builtin("concat", "Array.prototype.concat", array[] of {"item"}, 1), 347 Builtin("join", "Array.prototype.join", array[] of {"separator"}, 1), 348 Builtin("pop", "Array.prototype.pop", nil, 0), 349 Builtin("push", "Array.prototype.push", array[] of {"item"} , 1), 350 Builtin("reverse", "Array.prototype.reverse", nil, 0), 351 Builtin("shift", "Array.prototype.shift", nil, 0), 352 Builtin("slice", "Array.prototype.slice", array[] of {"start", "end"}, 2), 353 Builtin("splice", "Array.prototype.splice", array[] of {"start", "delcnt", "item"}, 2), 354 Builtin("sort", "Array.prototype.sort", array[] of {"comparefunc"}, 1), 355 Builtin("unshift", "Array.prototype.unshift", array[] of {"item"}, 1), 356}; 357 358bistr := Builtin("String", "String", array[] of {"value"}, 1); 359bistrproto := array[] of 360{ 361 Builtin("toString", "String.prototype.toString", nil, 0), 362 Builtin("valueOf", "String.prototype.valueOf", nil, 0), 363 Builtin("charAt", "String.prototype.charAt", array[] of {"pos"}, 1), 364 Builtin("charCodeAt", "String.prototype.charCodeAt", array[] of {"pos"}, 1), 365 Builtin("concat", "String.prototype.concat", array[] of {"string"}, 1), 366 Builtin("indexOf", "String.prototype.indexOf", array[] of {"string", "pos"}, 2), 367 Builtin("lastIndexOf", "String.prototype.lastIndexOf", array[] of {"string", "pos"}, 2), 368 Builtin("localeCompare", "String.prototype.localeCompare", array[] of {"that"}, 1), 369 Builtin("slice", "String.prototype.slice", array[] of {"start", "end"}, 2), 370 Builtin("split", "String.prototype.split", array[] of {"separator"}, 2), 371 Builtin("substr", "String.prototype.substr", array[] of {"start", "length"}, 2), 372 Builtin("substring", "String.prototype.substring", array[] of {"start", "end"}, 2), 373 Builtin("toLowerCase", "String.prototype.toLowerCase", nil, 0), 374 Builtin("toUpperCase", "String.prototype.toUpperCase", nil, 0), 375 Builtin("toLocaleLowerCase", "String.prototype.toLocaleLowerCase", nil, 0), 376 Builtin("toLocaleUpperCase", "String.prototype.toLocaleUpperCase", nil, 0), 377# JavaScript 1.0 378 Builtin("anchor", "String.prototype.anchor", array[] of {"name"}, 1), 379 Builtin("big", "String.prototype.big", nil, 0), 380 Builtin("blink", "String.prototype.blink", nil, 0), 381 Builtin("bold", "String.prototype.bold", nil, 0), 382 Builtin("fixed", "String.prototype.fixed", nil, 0), 383 Builtin("fontcolor", "String.prototype.fontcolor", array[] of {"color"}, 1), 384 Builtin("fontsize", "String.prototype.fontsize", array[] of {"size"}, 1), 385 Builtin("italics", "String.prototype.italics", nil, 0), 386 Builtin("link", "String.prototype.link", array[] of {"href"}, 1), 387 Builtin("small", "String.prototype.small", nil, 0), 388 Builtin("strike", "String.prototype.strike", nil, 0), 389 Builtin("sub", "String.prototype.sub", nil, 0), 390 Builtin("sup", "String.prototype.sup", nil, 0), 391 Builtin("match", "String.prototype.match", array[] of {"regexp"}, 1), 392 Builtin("replace", "String.prototype.replace", array[] of {"searchval", "replaceval"}, 2), 393 Builtin("search", "String.prototype.search", array[] of {"regexp"}, 1), 394}; 395bistrctor := Builtin("fromCharCode", "String.fromCharCode", array[] of {"characters"}, 1); 396 397bibool := Builtin("Boolean", "Boolean", array[] of {"value"}, 1); 398biboolproto := array[] of 399{ 400 Builtin("toString", "Boolean.prototype.toString", nil, 0), 401 Builtin("valueOf", "Boolean.prototype.valueOf", nil, 0), 402}; 403 404binum := Builtin("Number", "Number", array[] of {"value"}, 1); 405binumproto := array[] of 406{ 407 Builtin("toString", "Number.prototype.toString", nil, 0), 408 Builtin("toLocaleString", "Number.prototype.toLocaleString", nil, 0), 409 Builtin("valueOf", "Number.prototype.valueOf", nil, 0), 410 Builtin("toFixed", "Number.prototype.toFixed", array[] of {"digits"}, 1), 411 Builtin("toExponential", "Number.prototype.toExponential", array[] of {"digits"}, 1), 412 Builtin("toPrecision", "Number.prototype.toPrecision", array[] of {"digits"}, 1), 413}; 414 415biregexp := Builtin("RegExp", "RegExp", array[] of {"pattern", "flags"}, 2); 416biregexpproto := array[] of 417{ 418 Builtin("exec", "RegExp.prototype.exec", array[] of {"string"}, 1), 419 Builtin("test", "RegExp.prototype.test", array[] of {"string"}, 1), 420 Builtin("toString", "RegExp.prototype.toString", nil, 0), 421}; 422 423bidate := Builtin("Date", "Date", array[] of {"value"}, 1); 424bidateproto := array[] of 425{ 426 Builtin("toString", "Date.prototype.toString", nil, 0), 427 Builtin("toDateString", "Date.prototype.toDateString", nil, 0), 428 Builtin("toTimeString", "Date.prototype.toTimeString", nil, 0), 429 Builtin("toLocaleString", "Date.prototype.toLocalString", nil, 0), 430 Builtin("toLocaleDateString", "Date.prototype.toLocaleDateString", nil, 0), 431 Builtin("toLocaleTimeString", "Date.prototype.toLocaleTimeString", nil, 0), 432 Builtin("valueOf", "Date.prototype.valueOf", nil, 0), 433 Builtin("getTime", "Date.prototype.getTime", nil, 0), 434 Builtin("getYear", "Date.prototype.getYear", nil, 0), 435 Builtin("getFullYear", "Date.prototype.getFullYear", nil, 0), 436 Builtin("getUTCFullYear", "Date.prototype.getUTCFullYear", nil, 0), 437 Builtin("getMonth", "Date.prototype.getMonth", nil, 0), 438 Builtin("getUTCMonth", "Date.prototype.getUTCMonth", nil, 0), 439 Builtin("getDate", "Date.prototype.getDate", nil, 0), 440 Builtin("getUTCDate", "Date.prototype.getUTCDate", nil, 0), 441 Builtin("getDay", "Date.prototype.getDay", nil, 0), 442 Builtin("getUTCDay", "Date.prototype.getUTCDay", nil, 0), 443 Builtin("getHours", "Date.prototype.getHours", nil, 0), 444 Builtin("getUTCHours", "Date.prototype.getUTCHours", nil, 0), 445 Builtin("getMinutes", "Date.prototype.getMinutes", nil, 0), 446 Builtin("getUTCMinutes", "Date.prototype.getUTCMinutes", nil, 0), 447 Builtin("getSeconds", "Date.prototype.getSeconds", nil, 0), 448 Builtin("getUTCSeconds", "Date.prototype.getUTCSeconds", nil, 0), 449 Builtin("getMilliseconds", "Date.prototype.getMilliseconds", nil, 0), 450 Builtin("getUTCMilliseconds", "Date.prototype.getUTCMilliseconds", nil, 0), 451 Builtin("getTimezoneOffset", "Date.prototype.getTimezoneOffset", nil, 0), 452 Builtin("setTime", "Date.prototype.setTime", array[] of {"time"}, 1), 453 Builtin("setMilliseconds", "Date.prototype.setMilliseconds", array[] of {"ms"}, 1), 454 Builtin("setUTCMilliseconds", "Date.prototype.setUTCMilliseconds", array[] of {"ms"}, 1), 455 Builtin("setSeconds", "Date.prototype.setSeconds", array[] of {"sec", "ms"}, 2), 456 Builtin("setUTCSeconds", "Date.prototype.setUTCSeconds", array[] of {"sec", "ms"}, 2), 457 Builtin("setMinutes", "Date.prototype.setMinutes", array[] of {"min", "sec", "ms"}, 3), 458 Builtin("setUTCMinutes", "Date.prototype.setUTCMinutes", array[] of {"min", "sec", "ms"}, 3), 459 Builtin("setHours", "Date.prototype.setHours", array[] of {"hour", "min", "sec", "ms"}, 4), 460 Builtin("setUTCHours", "Date.prototype.setUTCHours", array[] of {"hour", "min", "sec", "ms"}, 4), 461 Builtin("setDate", "Date.prototype.setDate", array[] of {"date"}, 1), 462 Builtin("setUTCDate", "Date.prototype.setUTCDate", array[] of {"date"}, 1), 463 Builtin("setMonth", "Date.prototype.setMonth", array[] of {"mon", "date"}, 2), 464 Builtin("setUTCMonth", "Date.prototype.setUTCMonth", array[] of {"mon", "date"}, 2), 465 Builtin("setFullYear", "Date.prototype.setFullYear", array[] of {"year", "mon", "date"}, 3), 466 Builtin("setUTCFullYear", "Date.prototype.setUTCFullYear", array[] of {"year", "mon", "date"}, 3), 467 Builtin("setYear", "Date.prototype.setYear", array[] of {"year"}, 1), 468 Builtin("toLocaleString", "Date.prototype.toLocaleString", nil, 0), 469 Builtin("toUTCString", "Date.prototype.toUTCString", nil, 0), 470 Builtin("toGMTString", "Date.prototype.toGMTString", nil, 0), 471}; 472bidatector := array[] of 473{ 474 Builtin("parse", "Date.parse", array[] of {"string"}, 1), 475 Builtin("UTC", "Date.UTC", array[] of {"year", "month", "date", "hours", "minutes", "seconds", "ms"}, 7), 476}; 477 478bimath := array[] of 479{ 480 Builtin("abs", "Math.abs", array[] of {"x"}, 1), 481 Builtin("acos", "Math.acos", array[] of {"x"}, 1), 482 Builtin("asin", "Math.asin", array[] of {"x"}, 1), 483 Builtin("atan", "Math.atan", array[] of {"x"}, 1), 484 Builtin("atan2", "Math.atan2", array[] of {"y", "x"}, 2), 485 Builtin("ceil", "Math.ceil", array[] of {"x"}, 1), 486 Builtin("cos", "Math.cos", array[] of {"x"}, 1), 487 Builtin("exp", "Math.exp", array[] of {"x"}, 1), 488 Builtin("floor", "Math.floor", array[] of {"x"}, 1), 489 Builtin("log", "Math.log", array[] of {"x"}, 1), 490 Builtin("max", "Math.max", array[] of {"x", "y"}, 2), 491 Builtin("min", "Math.min", array[] of {"x", "y"}, 2), 492 Builtin("pow", "Math.pow", array[] of {"x", "y"}, 2), 493 Builtin("random", "Math.random", nil, 0), 494 Builtin("round", "Math.round", array[] of {"x"}, 1), 495 Builtin("sin", "Math.sin", array[] of {"x"}, 1), 496 Builtin("sqrt", "Math.sqrt", array[] of {"x"}, 1), 497 Builtin("tan", "Math.tan", array[] of {"x"}, 1), 498}; 499 500init(): string 501{ 502 sys = load Sys Sys->PATH; 503 math = load Math Math->PATH; 504 if(math == nil) 505 return sys->sprint("can't load module %s: %r", Math->PATH); 506 507 str = load String String->PATH; 508 if(str == nil) 509 return sys->sprint("can't load module %s: %r", String->PATH); 510 511 daytime = load Daytime Daytime->PATH; 512 if(daytime == nil) 513 return sys->sprint("can't load module %s: %r", Daytime->PATH); 514 515 me = load ESHostobj SELF; 516 if(me == nil) 517 return "can't load builtin functions"; 518 519 randinit(big sys->millisec()); 520 stdout = sys->fildes(1); 521 # 522 # maximum number of syntax errors reported 523 # 524 maxerr = 1; 525 526 undefined = ref Val(TUndef, 0., nil, nil, nil); 527 null = ref Val(TNull, 0., nil, nil, nil); 528 true = ref Val(TBool, 1., nil, nil, nil); 529 false = ref Val(TBool, 0., nil, nil, nil); 530 return ""; 531} 532 533mkcall(ex : ref Exec, p: array of string): ref Call 534{ 535 return ref Call(p, nil, ex); 536} 537 538mkbiobj(ex: ref Exec, meth: Builtin, proto: ref Obj): ref Obj 539{ 540 o := biinst(ex.global, meth, ex.funcproto, me); 541 o.construct = o.call; 542 valinstant(o, DontEnum|DontDelete|ReadOnly, "prototype", objval(proto)); 543 valinstant(proto, DontEnum, "constructor", objval(o)); 544 return o; 545} 546 547mkexec(go: ref Obj): ref Exec 548{ 549 o: ref Obj; 550 if(go == nil) 551 go = mkobj(nil, "global"); 552 ex := ref Exec; 553 ex.this = go; 554 ex.scopechain = go :: nil; 555 ex.stack = array[4] of ref Ref; 556 ex.sp = 0; 557 ex.global = go; 558 559 # 560 # builtin object prototypes 561 # 562 ex.objproto = mkobj(nil, "Object"); 563 ex.funcproto = mkobj(ex.objproto, "Function"); 564 ex.arrayproto = mkobj(ex.objproto, "Array"); 565 ex.strproto = mkobj(ex.objproto, "String"); 566 ex.numproto = mkobj(ex.objproto, "Number"); 567 ex.boolproto = mkobj(ex.objproto, "Boolean"); 568 ex.dateproto = mkobj(ex.objproto, "Date"); 569 ex.regexpproto = mkobj(ex.objproto, "RegExp"); 570 ex.errproto = mkobj(ex.objproto, "Error"); 571 572 biminst(ex.objproto, biobjproto, ex.funcproto, me); 573 574 biminst(ex.funcproto, bifuncproto, ex.funcproto, me); 575 ex.funcproto.call = mkcall(ex, nil); 576 ex.funcproto.val = strval("Function.prototype"); 577 valinstant(ex.funcproto, DontEnum|DontDelete|ReadOnly, "length", numval(real 0)); 578 579 biminst(ex.arrayproto, biarrayproto, ex.funcproto, me); 580 valinstant(ex.arrayproto, DontEnum|DontDelete, "length", numval(real 0)); 581 582 biminst(ex.errproto, bierrproto, ex.funcproto, me); 583 ex.errproto.val = strval(""); 584 valinstant(ex.errproto, DontEnum|DontDelete, "length", numval(real 0)); 585 valinstant(ex.errproto, DontEnum|DontDelete, "name", strval("")); 586 valinstant(ex.errproto, DontEnum|DontDelete, "message", strval("Error")); 587 588 biminst(ex.strproto, bistrproto, ex.funcproto, me); 589 ex.strproto.val = strval(""); 590 valinstant(ex.strproto, DontEnum|DontDelete|ReadOnly, "length", numval(real 0)); 591 592 biminst(ex.boolproto, biboolproto, ex.funcproto, me); 593 ex.boolproto.val = false; 594 595 biminst(ex.numproto, binumproto, ex.funcproto, me); 596 ex.numproto.val = numval(real +0); 597 598 biminst(ex.regexpproto, biregexpproto, ex.funcproto, me); 599 ex.regexpproto.val = strval(""); 600 valinstant(ex.regexpproto, DontEnum|DontDelete|ReadOnly, "length", numval(real 2)); 601 valinstant(ex.regexpproto, DontEnum|DontDelete|ReadOnly, "source", strval("")); 602 valinstant(ex.regexpproto, DontEnum|DontDelete|ReadOnly, "global", false); 603 valinstant(ex.regexpproto, DontEnum|DontDelete|ReadOnly, "ignoreCase", false); 604 valinstant(ex.regexpproto, DontEnum|DontDelete|ReadOnly, "multiline", false); 605 valinstant(ex.regexpproto, DontEnum|DontDelete, "lastIndex", numval(real 0)); 606 607 biminst(ex.dateproto, bidateproto, ex.funcproto, me); 608 ex.dateproto.val = numval(Math->NaN); 609 valinstant(ex.dateproto, DontEnum|DontDelete|ReadOnly, "length", numval(real 7)); 610 611 # 612 # simple builtin functions and values 613 # 614 valinstant(go, DontEnum, "NaN", numval(Math->NaN)); 615 valinstant(go, DontEnum, "Infinity", numval(Math->Infinity)); 616 617 biminst(go, glbuiltins, ex.funcproto, me); 618 619 # 620 # builtin objects, and cross-link them to their prototypes 621 # 622 mkbiobj(ex, biobj, ex.objproto); 623 mkbiobj(ex, bifunc, ex.funcproto); 624 mkbiobj(ex, biarray, ex.arrayproto); 625 o = mkbiobj(ex, bistr, ex.strproto); 626 biinst(o, bistrctor, ex.funcproto, me); 627 mkbiobj(ex, bibool, ex.boolproto); 628 o = mkbiobj(ex, binum, ex.numproto); 629 mkbiobj(ex, biregexp, ex.regexpproto); 630 mkbiobj(ex, bierr, ex.errproto); 631 632 math->FPcontrol(0, Math->INVAL|Math->ZDIV|Math->OVFL|Math->UNFL|Math->INEX); 633 634 valinstant(o, DontEnum|DontDelete|ReadOnly, "MAX_VALUE", numval(math->nextafter(Math->Infinity, 0.))); 635 valinstant(o, DontEnum|DontDelete|ReadOnly, "MIN_VALUE", numval(math->nextafter(0., 1.))); 636 valinstant(o, DontEnum|DontDelete|ReadOnly, "NaN", numval(Math->NaN)); 637 valinstant(o, DontEnum|DontDelete|ReadOnly, "NEGATIVE_INFINITY", numval(-Math->Infinity)); 638 valinstant(o, DontEnum|DontDelete|ReadOnly, "POSITIVE_INFINITY", numval(+Math->Infinity)); 639 o = mkbiobj(ex, bidate, ex.dateproto); 640 biminst(o, bidatector, ex.funcproto, me); 641 642 # 643 # the math object is a little different 644 # 645 o = mkobj(ex.objproto, "Object"); 646 valinstant(go, DontEnum, "Math", objval(o)); 647 biminst(o, bimath, ex.funcproto, me); 648 649 # 650 # these are computed so they are consistent with numbers ecma might calculate 651 # 652 mathe := math->exp(1.); 653 valinstant(o, DontEnum|DontDelete|ReadOnly, "E", numval(mathe)); 654 valinstant(o, DontEnum|DontDelete|ReadOnly, "LN10", numval(math->log(10.))); 655 valinstant(o, DontEnum|DontDelete|ReadOnly, "LN2", numval(math->log(2.))); 656 valinstant(o, DontEnum|DontDelete|ReadOnly, "LOG2E", numval(1./math->log(2.))); 657 valinstant(o, DontEnum|DontDelete|ReadOnly, "LOG10E", numval(1./math->log(10.))); 658 valinstant(o, DontEnum|DontDelete|ReadOnly, "PI", numval(Math->Pi)); 659 valinstant(o, DontEnum|DontDelete|ReadOnly, "SQRT1_2", numval(math->sqrt(1./2.))); 660 valinstant(o, DontEnum|DontDelete|ReadOnly, "SQRT2", numval(math->sqrt(2.))); 661 662 (EvalError, ex.evlerrproto) = mkerr(ex, "EvalError"); 663 (RangeError, ex.ranerrproto) = mkerr(ex, "RangeError"); 664 (ReferenceError, ex.referrproto) = mkerr(ex, "ReferenceError"); 665 (SyntaxError, ex.synerrproto) = mkerr(ex, "SyntaxError"); 666 (TypeError, ex.typerrproto) = mkerr(ex, "TypeError"); 667 (URIError, ex.urierrproto) = mkerr(ex, "URIError"); 668 (InternalError, ex.interrproto) = mkerr(ex, "InternalError"); 669 670 return ex; 671} 672 673mkerr(ex: ref Exec, e: string): (ref Obj, ref Obj) 674{ 675 errproto := mkobj(ex.objproto, e); 676 biminst(errproto, array[] of { Builtin("toString", e+".prototype.toString", nil, 0) }, ex.funcproto, me); 677 errproto.val = strval(""); 678 valinstant(errproto, DontEnum|DontDelete, "length", numval(real 0)); 679 valinstant(errproto, DontEnum|DontDelete, "name", strval(e)); 680 valinstant(errproto, DontEnum|DontDelete, "message", strval(e)); 681 eo := mkbiobj(ex, Builtin(e, e, array[] of {"message"}, 1), errproto); 682 # return (eo, errproto); 683 return (nerr(ex, eo, array[] of {strval(e)}, errproto), errproto); 684} 685 686mkparser(ex: ref Exec, src: string): ref Parser 687{ 688 p := ref Parser; 689 p.ex = ex; 690 p.src = src; 691 p.esrc = len src; 692 p.srci = 0; 693 p.errors = 0; 694 p.lineno = 1; 695 p.token = -1; 696 p.token1 = -1; 697 p.lastnl = 0; 698 p.inloop = 0; 699 p.incase = 0; 700 p.infunc = 0; 701 p.notin = 0; 702 p.code = mkcode(); 703 return p; 704} 705 706eval(ex: ref Exec, src: string): Completion 707{ 708 { 709 p := mkparser(ex, src); 710 711 if(debug['t']) 712 parset := sys->millisec(); 713 714 prog(ex, p); 715 716 toterrors += p.errors; 717 718 if(p.errors) 719 runtime(ex, SyntaxError, ex.error); 720 if(debug['p']){ 721 s := array of byte pprint(ex, p.code, ""); 722 if(len s) 723 sys->write(stdout, s, len s); 724 } 725 726 if(debug['t']) 727 xect := sys->millisec(); 728 729 globalinstant(hd ex.scopechain, p.code.vars); 730 c := exec(ex, p.code); 731 732 if(debug['t']) 733 print("parse time %d exec time %d\n", xect - parset, sys->millisec() - xect); 734 735 return c; 736 }exception{ 737 "throw" => 738 return (CThrow, ex.errval, nil); 739 } 740} 741 742#prog : selems 743# ; 744# 745#selems : selem 746# | selems selem 747# ; 748#selem : stmt 749# | fundecl 750# ; 751prog(ex: ref Exec, p: ref Parser) 752{ 753 while(look(p) != Leos) 754 if(look(p) == Lfunction) 755 fundecl(ex, p, 0); 756 else 757 stmt(p); 758} 759 760#fundecl : Lfunction Lid '(' zplist ')' '{' stmts '}' 761# ; 762#zplist : 763# | plist 764# ; 765# 766#plist : Lid 767# | plist ',' Lid 768# ; 769fundecl(ex: ref Exec, p: ref Parser, expr: int): ref Obj 770{ 771 jp: ref Prop; 772 773 c := p.code; 774 labs := p.labs; 775 p.labs = nil; 776 mustbe(p, Lfunction); 777 if(!expr || look(p) == Lid){ 778 mustbe(p, Lid); 779 jp = codevar(p, expr); 780 } 781 p.code = mkcode(); 782 mustbe(p, '('); 783 if(look(p) != ')'){ 784 for(;;){ 785 mustbe(p, Lid); 786 codevar(p, 1); 787 if(look(p) == ')') 788 break; 789 mustbe(p, ','); 790 } 791 } 792 params := p.code.vars; 793 p.code.vars = nil; 794 mustbe(p, ')'); 795 mustbe(p, '{'); 796 p.infunc++; 797 stmts(p); 798 p.infunc--; 799 mustbe(p, '}'); 800 801 # 802 # override any existing value, 803 # as per sec. 10.1.3 Variable instantiation 804 # 805 sparams := array[len params] of string; 806 for(i := 0; i < len sparams; i++) 807 sparams[i] = params[i].name; 808 809 # 810 # construct a function object; 811 # see section 15.3.21 812 o := mkobj(ex.funcproto, "Function"); 813 o.call = ref Call(sparams, p.code, ex); 814 o.construct = o.call; 815 if(jp != nil) 816 o.val = strval(jp.name); 817 else 818 o.val = strval(""); 819 valinstant(o, DontDelete|DontEnum|ReadOnly, "length", numval(real len sparams)); 820 po := nobj(ex, nil, nil); 821 valinstant(o, DontEnum, "prototype", objval(po)); 822 valinstant(po, DontEnum, "constructor", objval(o)); 823 valinstant(o, DontDelete|DontEnum|ReadOnly, "arguments", null); 824 if(jp != nil) 825 jp.val.val = objval(o); 826 827 if(debug['p']){ 828 s := array of byte (funcprint(ex, o) + "\n"); 829 sys->write(stdout, s, len s); 830 } 831 832 p.code = c; 833 p.labs = labs; 834 if(expr && jp != nil) 835 popvar(p); 836 return o; 837} 838 839# 840# install a variable for the id just lexed 841# 842codevar(p: ref Parser, forcenew: int): ref Prop 843{ 844 name := p.code.strs[p.id]; 845 vs := p.code.vars; 846 i : int; 847 if(!forcenew){ 848 for(i = 0; i < len vs; i++) 849 if(vs[i].name == name) 850 return vs[i]; 851 }else{ 852 i = len vs; 853 } 854 vs = array[i+1] of ref Prop; 855 vs[:] = p.code.vars; 856 p.code.vars = vs; 857 vs[i] = ref Prop(0, name, ref RefVal(undefined)); 858 return vs[i]; 859} 860 861popvar(p: ref Parser) 862{ 863 vs := p.code.vars; 864 p.code.vars = vs[0: len vs - 1]; 865} 866 867#stmts : 868# | stmts stmt 869# ; 870stmts(p: ref Parser) 871{ 872 while((op := look(p)) != '}' && op != Leos) 873 stmt(p); 874} 875 876#stmt : '{' stmts '}' 877# | Lvar varlist ';' 878# | exp ';' 879# | ';' 880# | Lif '(' exp ')' stmt 881# | Lif '(' exp ')' stmt Lelse stmt 882# | Lwhile '(' exp ')' stmt 883# | Ldo stmt Lwhile '(' exp ')' 884# | Lfor '(' zexp-notin ';' zexp ';' zexp ')' stmt 885# | Lfor '(' Lvar varlist-notin ';' zexp ';' zexp ')' stmt 886# | Lfor '(' lhsexp Lin exp ')' stmt 887# | Lfor '(' Lvar Lid [init] Lin exp ')' stmt 888# | Lcontinue ';' 889# | Lbreak ';' 890# | Lreturn zexp ';' # no line term after return 891# | Lwith '(' exp ')' stmt 892# | Lswitch '(' exp ')' '{' caseblk '}' 893# | Lthrow exp ';' 894# | Ltry block Lcatch '(' Lid ')' block 895# | Ltry block finally block 896# | Ltry block Lcatch '(' Lid ')' block finally block 897# ; 898stmt(p: ref Parser) 899{ 900 pc: int; 901 902 seenlabs := 0; 903 while(look(p) == Lid && look2(p) == ':'){ 904 pushlab(p, p.code.strs[p.id]); 905 emitconst(p, Llabel, p.id); 906 lex(p); 907 lex(p); 908 seenlabs++; 909 } 910 911 op := look(p); 912 if(seenlabs) 913 setkindlab(p, op, seenlabs); 914 case op{ 915 ';' => 916 lexemit(p); 917 '{' => 918 if(seenlabs == 0){ 919 lex(p); 920 stmts(p); 921 } 922 else{ 923 lexemit(p); 924 pc = epatch(p); 925 stmts(p); 926 patch(p, pc); 927 } 928 mustbe(p, '}'); 929 Lvar => 930 lexemit(p); 931 pc = epatch(p); 932 varlist(p); 933 semi(p); 934 patch(p, pc); 935 * => 936 exp(p); 937 semi(p); 938 emit(p, ';'); 939 Lif => 940 lexemit(p); 941 pc = epatch(p); 942 mustbe(p, '('); 943 exp(p); 944 mustbe(p, ')'); 945 patch(p, pc); 946 pc = epatch(p); 947 stmt(p); 948 patch(p, pc); 949 pc = epatch(p); 950 if(look(p) == Lelse){ 951 lex(p); 952 stmt(p); 953 } 954 patch(p, pc); 955 Lwhile or 956 Lwith => 957 lexemit(p); 958 pc = epatch(p); 959 mustbe(p, '('); 960 exp(p); 961 mustbe(p, ')'); 962 patch(p, pc); 963 if(op == Lwhile) 964 p.inloop++; 965 pc = epatch(p); 966 stmt(p); 967 patch(p, pc); 968 if(op == Lwhile) 969 p.inloop--; 970 Ldo => 971 p.inloop++; 972 lexemit(p); 973 pc = epatch(p); 974 stmt(p); 975 patch(p, pc); 976 mustbe(p, Lwhile); 977 mustbe(p, '('); 978 pc = epatch(p); 979 exp(p); 980 patch(p, pc); 981 mustbe(p, ')'); 982 mustbe(p, ';'); 983 p.inloop--; 984 Lfor => 985 fpc := p.code.npc; 986 lexemit(p); 987 mustbe(p, '('); 988 p.notin++; 989 if(look(p) == Lvar){ 990 lex(p); 991 pc = epatch(p); 992 varlist(p); 993 patch(p, pc); 994 p.notin--; 995 if(look(p) == Lin){ 996 check1var(p); 997 p.code.ops[fpc] = byte Lforvarin; 998 lex(p); 999 pc = epatch(p); 1000 exp(p); 1001 patch(p, pc); 1002 }else{ 1003 p.code.ops[fpc] = byte Lforvar; 1004 mustbe(p, ';'); 1005 pc = epatch(p); 1006 zexp(p); 1007 patch(p, pc); 1008 mustbe(p, ';'); 1009 pc = epatch(p); 1010 zexp(p); 1011 patch(p, pc); 1012 } 1013 }else{ 1014 pc = epatch(p); 1015 lhspc := p.code.npc; 1016 zexp(p); 1017 patch(p, pc); 1018 p.notin--; 1019 if(look(p) == Lin){ 1020 p.code.ops[fpc] = byte Lforin; 1021 checklhsexp(p, lhspc); 1022 lex(p); 1023 pc = epatch(p); 1024 exp(p); 1025 patch(p, pc); 1026 }else{ 1027 mustbe(p, ';'); 1028 pc = epatch(p); 1029 zexp(p); 1030 patch(p, pc); 1031 mustbe(p, ';'); 1032 pc = epatch(p); 1033 zexp(p); 1034 patch(p, pc); 1035 } 1036 } 1037 mustbe(p, ')'); 1038 p.inloop++; 1039 pc = epatch(p); 1040 stmt(p); 1041 patch(p, pc); 1042 p.inloop--; 1043 Lcontinue or 1044 Lbreak => 1045 lex(p); 1046 lab := 0; 1047 if(look(p) == Lid){ 1048 if((lr := findlab(p, p.code.strs[p.id])) == nil) 1049 error(p, "missing label"); 1050 if(op == Lcontinue && !itstmt(lr.k)) 1051 error(p, "continue label not on iteration statement"); 1052 if(op == Lbreak) 1053 nop := Lbreaklab; 1054 else 1055 nop = Lcontinuelab; 1056 if(!inlocallabs(p, lr, seenlabs)) # otherwise noop 1057 emitconst(p, nop, p.id); 1058 lex(p); 1059 lab = 1; 1060 } 1061 else 1062 emit(p, op); 1063 semi(p); 1064 if(op == Lbreak && !lab && !p.inloop && !p.incase) 1065 error(p, "break not in a do or for or while or case"); 1066 if(op == Lcontinue && !p.inloop) 1067 error(p, "continue not in a do or for or while"); 1068 Lreturn => 1069 lexemit(p); 1070 nextop := look(p); 1071 if(nextop != ';' && nextop != '}' && !p.lastnl) 1072 exp(p); 1073 semi(p); 1074 emit(p, ';'); 1075 if(!p.infunc) 1076 error(p, tokname(op)+" not in a function"); 1077 Lswitch => 1078 lexemit(p); 1079 mustbe(p, '('); 1080 pc = epatch(p); 1081 exp(p); 1082 patch(p, pc); 1083 mustbe(p, ')'); 1084 mustbe(p, '{'); 1085 pc = epatch(p); 1086 caseblk(p); 1087 patch(p, pc); 1088 mustbe(p, '}'); 1089 Lthrow => 1090 lexemit(p); 1091 nextop := look(p); 1092 if(!p.lastnl) 1093 exp(p); 1094 mustbe(p, ';'); 1095 emit(p, ';'); 1096 Lprint => 1097 lexemit(p); 1098 nextop := look(p); 1099 if(!p.lastnl) 1100 exp(p); 1101 mustbe(p, ';'); 1102 emit(p, ';'); 1103 Ltry => 1104 lexemit(p); 1105 pc = epatch(p); 1106 block(p); 1107 patch(p, pc); 1108 pc = epatch(p); 1109 if(look(p) == Lcatch){ 1110 lex(p); 1111 mustbe(p, '('); 1112 mustbe(p, Lid); 1113 emitconst(p, Lid, p.id); 1114 mustbe(p, ')'); 1115 block(p); 1116 } 1117 patch(p, pc); 1118 pc = epatch(p); 1119 if(look(p) == Lfinally){ 1120 lex(p); 1121 block(p); 1122 } 1123 patch(p, pc); 1124 } 1125 while(--seenlabs >= 0) 1126 poplab(p); 1127} 1128 1129block(p : ref Parser) 1130{ 1131 mustbe(p, '{'); 1132 stmts(p); 1133 mustbe(p, '}'); 1134} 1135 1136caseblk(p : ref Parser) 1137{ 1138 pc, defaultpc, clausepc : int; 1139 gotdef := 0; 1140 p.incase++; 1141 1142 defaultpc = epatch(p); 1143 while((op := look(p)) != '}' && op != Leos) { 1144 if (op != Lcase && op != Ldefault) { 1145 err := "expected " + tokname(Lcase) 1146 + " or " + tokname(Ldefault) 1147 + " found " + tokname(op); 1148 error(p, err); 1149 } 1150 if (op == Ldefault) { 1151 if (gotdef) 1152 error(p, "default case already defined"); 1153 gotdef = 1; 1154 1155 patch(p, defaultpc); 1156 } 1157 lex(p); 1158 clausepc = epatch(p); 1159 if (op == Lcase) { 1160 pc = epatch(p); 1161 exp(p); 1162 patch(p, pc); 1163 } 1164 mustbe(p, ':'); 1165 casestmts(p); 1166 patch(p, clausepc); 1167 } 1168 clausepc = epatch(p); 1169 patch(p, clausepc); 1170 if (!gotdef) 1171 patch(p, defaultpc); 1172 p.incase--; 1173} 1174 1175casestmts(p : ref Parser) 1176{ 1177 while((op := look(p)) != '}' && op != Lcase && op != Ldefault && op != Leos) 1178 stmt(p); 1179} 1180 1181semi(p: ref Parser) 1182{ 1183 op := look(p); 1184 if(op == ';'){ 1185 lex(p); 1186 return; 1187 } 1188 if(op == '}' || op == Leos || p.lastnl) 1189 return; 1190 mustbe(p, ';'); 1191} 1192 1193#varlist : vardecl 1194# | varlist ',' vardecl 1195# ; 1196# 1197#vardecl : Lid init 1198# ; 1199# 1200#init : 1201# | '=' asexp 1202# ; 1203varlist(p: ref Parser) 1204{ 1205 # 1206 # these declaration aren't supposed 1207 # to override current definitions 1208 # 1209 mustbe(p, Lid); 1210 codevar(p, 0); 1211 emitconst(p, Lid, p.id); 1212 if(look(p) == '='){ 1213 lex(p); 1214 asexp(p); 1215 emit(p, '='); 1216 } 1217 if(look(p) != ',') 1218 return; 1219 emit(p, Lgetval); 1220 lex(p); 1221 varlist(p); 1222 emit(p, ','); 1223} 1224 1225# 1226# check that only 1 id is declared in the var list 1227# 1228check1var(p: ref Parser) 1229{ 1230 if(p.code.ops[p.code.npc-1] == byte ',') 1231 error(p, "only one identifier allowed"); 1232} 1233 1234#zexp : 1235# | exp 1236# ; 1237zexp(p: ref Parser) 1238{ 1239 op := look(p); 1240 if(op == ';' || op == ')') 1241 return; 1242 exp(p); 1243} 1244 1245#exp : asexp 1246# | exp ',' asexp 1247# ; 1248exp(p: ref Parser) 1249{ 1250 asexp(p); 1251 while(look(p) == ','){ 1252 lex(p); 1253 emit(p, Lgetval); 1254 asexp(p); 1255 emit(p, ','); 1256 } 1257} 1258 1259#asexp : condexp 1260# | lhsexp asop asexp 1261# ; 1262# 1263#asop : '=' | Lmulas | Ldivas | Lmodas | Laddas | Lsubas 1264# | Llshas | Lrshas | Lrshuas | Landas | Lxoras | Loras 1265# ; 1266asops := array[] of { '=', Lmulas, Ldivas, Lmodas, Laddas, Lsubas, 1267 Llshas, Lrshas, Lrshuas, Landas, Lxoras, Loras }; 1268asbaseops := array[] of { '=', '*', '/', '%', '+', '-', 1269 Llsh, Lrsh, Lrshu, '&', '^', '|' }; 1270asexp(p: ref Parser) 1271{ 1272 lhspc := p.code.npc; 1273 condexp(p); 1274 i := inops(look(p), asops); 1275 if(i >= 0){ 1276 op := lex(p); 1277 checklhsexp(p, lhspc); 1278 if(op != '=') 1279 emit(p, Lasop); 1280 asexp(p); 1281 emit(p, asbaseops[i]); 1282 if(op != '=') 1283 emit(p, Las); 1284 } 1285} 1286 1287#condexp : ororexp 1288# | ororexp '?' asexp ':' asexp 1289# ; 1290condexp(p: ref Parser) 1291{ 1292 ororexp(p); 1293 if(look(p) == '?'){ 1294 lexemit(p); 1295 pc := epatch(p); 1296 asexp(p); 1297 mustbe(p, ':'); 1298 patch(p, pc); 1299 pc = epatch(p); 1300 asexp(p); 1301 patch(p, pc); 1302 } 1303} 1304 1305#ororexp : andandexp 1306# | ororexp op andandexp 1307# ; 1308ororexp(p: ref Parser) 1309{ 1310 andandexp(p); 1311 while(look(p) == Loror){ 1312 lexemit(p); 1313 pc := epatch(p); 1314 andandexp(p); 1315 patch(p, pc); 1316 } 1317} 1318 1319#andandexp : laexp 1320# | andandexp op laexp 1321# ; 1322andandexp(p: ref Parser) 1323{ 1324 laexp(p, 0); 1325 while(look(p) == Landand){ 1326 lexemit(p); 1327 pc := epatch(p); 1328 laexp(p, 0); 1329 patch(p, pc); 1330 } 1331} 1332 1333#laexp : unexp 1334# | laexp op laexp 1335# ; 1336prectab := array[] of 1337{ 1338 array[] of { '|' }, 1339 array[] of { '^' }, 1340 array[] of { '&' }, 1341 array[] of { Leq, Lneq, Lseq, Lsne }, 1342 array[] of { '<', '>', Lleq, Lgeq, Lin, Linstanceof }, 1343 array[] of { Llsh, Lrsh, Lrshu }, 1344 array[] of { '+', '-' }, 1345 array[] of { '*', '/', '%' }, 1346}; 1347laexp(p: ref Parser, prec: int) 1348{ 1349 unexp(p); 1350 for(pr := len prectab - 1; pr >= prec; pr--){ 1351 while(inops(look(p), prectab[pr]) >= 0){ 1352 emit(p, Lgetval); 1353 op := lex(p); 1354 laexp(p, pr + 1); 1355 emit(p, op); 1356 } 1357 } 1358} 1359 1360#unexp : postexp 1361# | Ldelete unexp 1362# | Lvoid unexp 1363# | Ltypeof unexp 1364# | Linc unexp 1365# | Ldec unexp 1366# | '+' unexp 1367# | '-' unexp 1368# | '~' unexp 1369# | '!' unexp 1370# ; 1371preops := array[] of { Ldelete, Lvoid, Ltypeof, Linc, Ldec, '+', '-', '~', '!' }; 1372unexp(p: ref Parser) 1373{ 1374 if(inops(look(p), preops) >= 0){ 1375 op := lex(p); 1376 unexp(p); 1377 if(op == '-') 1378 op = Lpresub; 1379 else if(op == '+') 1380 op = Lpreadd; 1381 emit(p, op); 1382 return; 1383 } 1384 postexp(p); 1385} 1386 1387#postexp : lhsexp 1388# | lhsexp Linc # no line terminators before Linc or Ldec 1389# | lhsexp Ldec 1390# ; 1391postexp(p: ref Parser) 1392{ 1393 lhsexp(p, 0); 1394 if(p.lastnl) 1395 return; 1396 op := look(p); 1397 if(op == Linc || op == Ldec){ 1398 if(op == Linc) 1399 op = Lpostinc; 1400 else 1401 op = Lpostdec; 1402 lex(p); 1403 emit(p, op); 1404 } 1405} 1406 1407# 1408# verify that the last expression is actually a lhsexp 1409# 1410checklhsexp(p: ref Parser, pc: int) 1411{ 1412 1413 case int p.code.ops[p.code.npc-1]{ 1414 Lthis or 1415 ')' or 1416 '.' or 1417 '[' or 1418 Lcall or 1419 Lnew or 1420 Lnewcall => 1421 return; 1422 } 1423 1424 case int p.code.ops[pc]{ 1425 Lid or 1426 Lnum or 1427 Lstr or 1428 Lregexp => 1429 npc := pc + 1; 1430 (npc, nil) = getconst(p.code.ops, npc); 1431 if(npc == p.code.npc) 1432 return; 1433 } 1434 1435 (nil, e) := pexp(mkpprint(p.ex, p.code), pc, p.code.npc); 1436 error(p, "only left-hand-side expressions allowed: "+e); 1437} 1438 1439#lhsexp : newexp 1440# | callexp 1441# ; 1442#callexp: memexp args 1443# | callexp args 1444# | callexp '[' exp ']' 1445# | callexp '.' Lid 1446# ; 1447#newexp : memexp 1448# | Lnew newexp 1449# ; 1450#memexp : primexp 1451# | Lfunction id(opt) '(' zplist ')' '{' stmts '}' 1452# | memexp '[' exp ']' 1453# | memexp '.' Lid 1454# | Lnew memexp args 1455# ; 1456lhsexp(p: ref Parser, hasnew: int): int 1457{ 1458 a: int; 1459 if(look(p) == Lnew){ 1460 lex(p); 1461 hasnew = lhsexp(p, hasnew + 1); 1462 if(hasnew){ 1463 emit(p, Lnew); 1464 hasnew--; 1465 } 1466 return hasnew; 1467 } 1468 if(look(p) == Lfunction){ 1469 o := fundecl(p.ex, p, 1); 1470 emitconst(p, Lfunction, fexplook(p, o)); 1471 return 0; 1472 } 1473 primexp(p); 1474 for(;;){ 1475 op := look(p); 1476 if(op == '('){ 1477 op = Lcall; 1478 if(hasnew){ 1479 hasnew--; 1480 # 1481 # stupid different order of evaluation 1482 # 1483 emit(p, Lgetval); 1484 op = Lnewcall; 1485 } 1486 a = args(p); 1487 emitconst(p, op, a); 1488 }else if(op == '['){ 1489 emit(p, Lgetval); 1490 lex(p); 1491 exp(p); 1492 mustbe(p, ']'); 1493 emit(p, '['); 1494 }else if(op == '.'){ 1495 lex(p); 1496 mustbe(p, Lid); 1497 emitconst(p, Lid, p.id); 1498 emit(p, '.'); 1499 }else 1500 return hasnew; 1501 } 1502} 1503 1504#primexp : Lthis 1505# | Lid 1506# | Lnum 1507# | Lstr 1508# | Lregexp 1509# | '(' exp ')' 1510# | '[' array initializer ']' 1511# | '{' propandval '}' 1512# ; 1513primexp(p: ref Parser) 1514{ 1515 case t := lex(p){ 1516 Lthis => 1517 emit(p, t); 1518 Lid or 1519 Lnum or 1520 Lstr => 1521 emitconst(p, t, p.id); 1522 '/' => 1523 lexregexp(p); 1524 emitconst(p, Lregexp, p.id); 1525 '(' => 1526 emit(p, '('); 1527 exp(p); 1528 mustbe(p, ')'); 1529 emit(p, ')'); 1530 '[' => 1531 a := 0; 1532 if(look(p) == ']') 1533 lex(p); 1534 else{ 1535 for(;;){ 1536 if(look(p) == ']'){ 1537 lex(p); 1538 break; 1539 } 1540 if(look(p) == ',') 1541 emit(p, Lnoval); 1542 else 1543 asexp(p); 1544 emit(p, Lgetval); 1545 a++; 1546 if(look(p) == ']'){ 1547 lex(p); 1548 break; 1549 } 1550 mustbe(p, ','); 1551 } 1552 } 1553 emitconst(p, Larrinit, a); 1554 '{' => 1555 a := 0; 1556 if(look(p) == '}') 1557 lex(p); 1558 else{ 1559 for(;;){ 1560 case(tt := lex(p)){ 1561 Lid => 1562 emitconst(p, Lstr, p.id); 1563 Lnum or 1564 Lstr => 1565 emitconst(p, tt, p.id); 1566 * => 1567 error(p, "expected identifier, number or string"); 1568 } 1569 mustbe(p, ':'); 1570 asexp(p); 1571 emit(p, Lgetval); 1572 a++; 1573 if(look(p) == '}'){ 1574 lex(p); 1575 break; 1576 } 1577 mustbe(p, ','); 1578 } 1579 } 1580 emitconst(p, Lobjinit, a); 1581 * => 1582 error(p, "expected an expression"); 1583 } 1584} 1585 1586#args : '(' ')' 1587# | '(' arglist ')' 1588# ; 1589# 1590#arglist : asexp 1591# | arglist ',' asexp 1592# ; 1593args(p: ref Parser): int 1594{ 1595 mustbe(p, '('); 1596 if(look(p) == ')'){ 1597 lex(p); 1598 return 0; 1599 } 1600 a := 0; 1601 for(;;){ 1602 asexp(p); 1603 emit(p, Lgetval); 1604 a++; 1605 if(look(p) == ')'){ 1606 lex(p); 1607 return a; 1608 } 1609 mustbe(p, ','); 1610 } 1611} 1612 1613inops(tok: int, ops: array of int): int 1614{ 1615 for(i := 0; i < len ops; i++) 1616 if(tok == ops[i]) 1617 return i; 1618 return -1; 1619} 1620 1621mustbe(p: ref Parser, t: int) 1622{ 1623 tt := lex(p); 1624 if(tt != t) 1625 error(p, "expected "+tokname(t)+" found "+tokname(tt)); 1626} 1627 1628toknames := array[] of 1629{ 1630 Leos-Lbase => "end of input", 1631 Landas-Lbase => "&=", 1632 Loras-Lbase => "|=", 1633 Lxoras-Lbase => "^=", 1634 Llshas-Lbase => "<<=", 1635 Lrshas-Lbase => ">>=", 1636 Lrshuas-Lbase => ">>>=", 1637 Laddas-Lbase => "+=", 1638 Lsubas-Lbase => "-=", 1639 Lmulas-Lbase => "*=", 1640 Ldivas-Lbase => "/=", 1641 Lmodas-Lbase => "%=", 1642 Loror-Lbase => "||", 1643 Landand-Lbase => "&&", 1644 Leq-Lbase => "==", 1645 Lneq-Lbase => "!=", 1646 Lleq-Lbase => "<=", 1647 Lgeq-Lbase => ">=", 1648 Llsh-Lbase => "<<", 1649 Lrsh-Lbase => ">>", 1650 Lrshu-Lbase => ">>>", 1651 Linc-Lbase => "++", 1652 Ldec-Lbase => "--", 1653 Lnum-Lbase => "a number", 1654 Lid-Lbase => "an identifier", 1655 Lstr-Lbase => "a string", 1656 Lthis-Lbase => "this", 1657 Ltypeof-Lbase => "typeof", 1658 Ldelete-Lbase => "delete", 1659 Lvoid-Lbase => "void", 1660 Lwhile-Lbase => "while", 1661 Lfor-Lbase => "for", 1662 Lbreak-Lbase => "break", 1663 Lcontinue-Lbase => "continue", 1664 Lwith-Lbase => "with", 1665 Lreturn-Lbase => "return", 1666 Lfunction-Lbase => "function", 1667 Lvar-Lbase => "var", 1668 Lif-Lbase => "if", 1669 Lelse-Lbase => "else", 1670 Lin-Lbase => "in", 1671 Lnew-Lbase => "new", 1672 1673 Lpreadd-Lbase => "+", 1674 Lpresub-Lbase => "-", 1675 Lpostinc-Lbase => "++", 1676 Lpostdec-Lbase => "--", 1677 Lcall-Lbase => "call", 1678 Lnewcall-Lbase => "newcall", 1679 Lgetval-Lbase => "[[GetValue]]", 1680 Las-Lbase => "[[as]]", 1681 Lasop-Lbase => "[[asop]]", 1682 Lforin-Lbase => "forin", 1683 Lforvar-Lbase => "forvar", 1684 Lforvarin-Lbase => "forvarin", 1685 Lcase-Lbase => "case", 1686 Labstract-Lbase => "abstract", 1687 Lboolean-Lbase => "boolean", 1688 Lbyte-Lbase => "byte", 1689 Lcatch-Lbase => "catch", 1690 Lchar-Lbase => "char", 1691 Lclass-Lbase => "class", 1692 Lconst-Lbase => "const", 1693 Ldebugger-Lbase => "debugger", 1694 Ldefault-Lbase => "default", 1695 Ldo-Lbase => "do", 1696 Ldouble-Lbase => "double", 1697 Lenum-Lbase => "enum", 1698 Lexport-Lbase => "export", 1699 Lextends-Lbase => "extends", 1700 Lfinal-Lbase => "final", 1701 Lfinally-Lbase => "finally", 1702 Lfloat-Lbase => "float", 1703 Lgoto-Lbase => "goto", 1704 Limplements-Lbase => "implements", 1705 Limport-Lbase => "import", 1706 Linstanceof-Lbase => "instanceof", 1707 Lint-Lbase => "int", 1708 Linterface-Lbase => "interface", 1709 Llong-Lbase => "long", 1710 Lnative-Lbase => "native", 1711 Lpackage-Lbase => "package", 1712 Lprint-Lbase => "print", 1713 Lprivate-Lbase => "private", 1714 Lprotected-Lbase => "protected", 1715 Lpublic-Lbase => "public", 1716 Lregexp-Lbase => "regexp", 1717 Lseq-Lbase => "===", 1718 Lsne-Lbase => "!==", 1719 Lshort-Lbase => "short", 1720 Lstatic-Lbase => "static", 1721 Lsuper-Lbase => "super", 1722 Lswitch-Lbase => "switch", 1723 Lsynchronized-Lbase => "synchronized", 1724 Lthrow-Lbase => "throw", 1725 Lthrows-Lbase => "throws", 1726 Ltransient-Lbase => "transient", 1727 Ltry-Lbase=> "try", 1728 Lvolatile-Lbase => "volatile", 1729 Larrinit-Lbase => "arrayinit", 1730 Lobjinit-Lbase => "objinit", 1731 Lnoval-Lbase => "novalue", 1732 Llabel-Lbase => "label", 1733 Lbreaklab-Lbase => "break", 1734 Lcontinuelab-Lbase => "continue", 1735}; 1736 1737tokname(t: int): string 1738{ 1739 if(t < Lbase){ 1740 s := ""; 1741 s[0] = t; 1742 return s; 1743 } 1744 if(t-Lbase >= len toknames || toknames[t-Lbase] == "") 1745 return sprint("<%d>", t); 1746 return toknames[t-Lbase]; 1747} 1748 1749lexemit(p: ref Parser) 1750{ 1751 emit(p, lex(p)); 1752 if(debug['s']) 1753 sys->print("%d: %s\n", p.code.npc-1, tokname(int p.code.ops[p.code.npc-1])); 1754} 1755 1756emit(p: ref Parser, t: int) 1757{ 1758 if(t > 255) 1759 fatal(p.ex, sprint("emit too big: %d\n", t)); 1760 if(p.code.npc >= len p.code.ops){ 1761 ops := array[2 * len p.code.ops] of byte; 1762 ops[:] = p.code.ops; 1763 p.code.ops = ops; 1764 } 1765 p.code.ops[p.code.npc++] = byte t; 1766} 1767 1768emitconst(p: ref Parser, op, c: int) 1769{ 1770 emit(p, op); 1771 if(c < 0) 1772 fatal(p.ex, "emit negative constant"); 1773 if(c >= 255){ 1774 if(c >= 65536) 1775 fatal(p.ex, "constant too large"); 1776 emit(p, 255); 1777 emit(p, c & 16rff); 1778 c >>= 8; 1779 } 1780 emit(p, c); 1781} 1782 1783epatch(p: ref Parser): int 1784{ 1785 pc := p.code.npc; 1786 emit(p, 0); 1787 emit(p, 0); 1788 return pc; 1789} 1790 1791patch(p: ref Parser, pc: int) 1792{ 1793 val := p.code.npc - pc; 1794 if(val >= 65536) 1795 fatal(p.ex, "patch constant too large"); 1796 p.code.ops[pc] = byte val; 1797 p.code.ops[pc+1] = byte(val >> 8); 1798} 1799 1800getconst(ops: array of byte, pc: int): (int, int) 1801{ 1802 c := int ops[pc++]; 1803 if(c == 255){ 1804 c = int ops[pc] + (int ops[pc+1] << 8); 1805 pc += 2; 1806 } 1807 return (pc, c); 1808} 1809 1810getjmp(ops: array of byte, pc: int): (int, int) 1811{ 1812 c := int ops[pc] + (int ops[pc+1] << 8) + pc; 1813 pc += 2; 1814 return (pc, c); 1815} 1816 1817mkcode(): ref Code 1818{ 1819 return ref Code(array[16] of byte, 0, nil, nil, nil, nil, nil); 1820} 1821 1822look(p: ref Parser): int 1823{ 1824 if(p.token == -1) 1825 p.token = lex(p); 1826 if(p.notin && p.token == Lin) 1827 return ~Lin; 1828 return p.token; 1829} 1830 1831look2(p: ref Parser): int 1832{ 1833 look(p); 1834 if(p.token1 == -1){ 1835 # fool lex() 1836 t := p.token; 1837 p.token = -1; 1838 p.token1 = lex(p); 1839 p.token = t; 1840 } 1841 return p.token1; 1842} 1843 1844lex(p: ref Parser): int 1845{ 1846 t := lex0(p); 1847 if(0) 1848 sys->print("tok=%d %s\n", t, tokname(t)); 1849 return t; 1850} 1851 1852lex0(p: ref Parser): int 1853{ 1854 t := p.token; 1855 if(t != -1){ 1856 p.token = p.token1; 1857 p.token1 = -1; 1858 return t; 1859 } 1860 1861 p.lastnl = 0; 1862 while(p.srci < p.esrc){ 1863 c := p.src[p.srci++]; 1864 case c{ 1865 '\r' or LS or PS => 1866 p.lastnl = 1; 1867 '\n' => 1868 p.lineno++; 1869 p.lastnl = 1; 1870 ' ' or 1871 '\t' or 1872 '\v' or 1873 FF or # form feed 1874 '\u00a0' => # no-break space 1875 ; 1876 '"' or 1877 '\''=> 1878 return lexstring(p, c); 1879 '(' or 1880 ')' or 1881 '[' or 1882 ']' or 1883 '{' or 1884 '}' or 1885 ',' or 1886 ';' or 1887 '~' or 1888 '?' or 1889 ':' => 1890 return c; 1891 '.' => 1892 if(p.srci < p.esrc && (map[p.src[p.srci]] & Mdigit) != byte 0){ 1893 p.srci--; 1894 return lexnum(p); 1895 } 1896 return '.'; 1897 '^' => 1898 if(p.srci < p.esrc && p.src[p.srci] == '='){ 1899 p.srci++; 1900 return Lxoras; 1901 } 1902 return '^'; 1903 '*' => 1904 if(p.srci < p.esrc && p.src[p.srci] == '='){ 1905 p.srci++; 1906 return Lmulas; 1907 } 1908 return '*'; 1909 '%' => 1910 if(p.srci < p.esrc && p.src[p.srci] == '='){ 1911 p.srci++; 1912 return Lmodas; 1913 } 1914 return '%'; 1915 '=' => 1916 if(p.srci < p.esrc && p.src[p.srci] == '='){ 1917 p.srci++; 1918 if(p.srci < p.esrc && p.src[p.srci] == '='){ 1919 p.srci++; 1920 return Lseq; 1921 } 1922 return Leq; 1923 } 1924 return '='; 1925 '!' => 1926 if(p.srci < p.esrc && p.src[p.srci] == '='){ 1927 p.srci++; 1928 if(p.srci < p.esrc && p.src[p.srci] == '='){ 1929 p.srci++; 1930 return Lsne; 1931 } 1932 return Lneq; 1933 } 1934 return '!'; 1935 '+' => 1936 if(p.srci < p.esrc){ 1937 c = p.src[p.srci]; 1938 if(c == '='){ 1939 p.srci++; 1940 return Laddas; 1941 } 1942 if(c == '+'){ 1943 p.srci++; 1944 return Linc; 1945 } 1946 } 1947 return '+'; 1948 '-' => 1949 if(p.srci < p.esrc){ 1950 c = p.src[p.srci]; 1951 if(c == '='){ 1952 p.srci++; 1953 return Lsubas; 1954 } 1955 if(c == '-'){ 1956 p.srci++; 1957 return Ldec; 1958 } 1959 } 1960 return '-'; 1961 '|' => 1962 if(p.srci < p.esrc){ 1963 c = p.src[p.srci]; 1964 if(c == '='){ 1965 p.srci++; 1966 return Loras; 1967 } 1968 if(c == '|'){ 1969 p.srci++; 1970 return Loror; 1971 } 1972 } 1973 return '|'; 1974 '&' => 1975 if(p.srci < p.esrc){ 1976 c = p.src[p.srci]; 1977 if(c == '='){ 1978 p.srci++; 1979 return Landas; 1980 } 1981 if(c == '&'){ 1982 p.srci++; 1983 return Landand; 1984 } 1985 } 1986 return '&'; 1987 '/' => 1988 if(p.srci < p.esrc){ 1989 c = p.src[p.srci]; 1990 if(c == '='){ 1991 p.srci++; 1992 return Ldivas; 1993 } 1994 if(c == '/'){ 1995 p.srci++; 1996 if(lexcom(p) < 0) 1997 return Leos; 1998 break; 1999 } 2000 if(c == '*'){ 2001 p.srci++; 2002 if(lexmcom(p) < 0) 2003 return Leos; 2004 break; 2005 } 2006 } 2007 return '/'; 2008 '>' => 2009 if(p.srci < p.esrc){ 2010 c = p.src[p.srci]; 2011 if(c == '='){ 2012 p.srci++; 2013 return Lgeq; 2014 } 2015 if(c == '>'){ 2016 p.srci++; 2017 if (p.srci < p.esrc) { 2018 c = p.src[p.srci]; 2019 if(c == '='){ 2020 p.srci++; 2021 return Lrshas; 2022 } 2023 if(c == '>'){ 2024 p.srci++; 2025 c = p.src[p.srci]; 2026 if(c == '='){ 2027 p.srci++; 2028 return Lrshuas; 2029 } 2030 return Lrshu; 2031 } 2032 } 2033 return Lrsh; 2034 } 2035 } 2036 return '>'; 2037 '<' => 2038 if(p.srci < p.esrc){ 2039 c = p.src[p.srci]; 2040 case c { 2041 '=' => 2042 p.srci++; 2043 return Lleq; 2044 '<' => 2045 p.srci++; 2046 if (p.srci < p.esrc) { 2047 c = p.src[p.srci]; 2048 if(c == '='){ 2049 p.srci++; 2050 return Llshas; 2051 } 2052 } 2053 return Llsh; 2054 '!' => 2055 # HTML comment - consume to end of line or end of comment 2056 # No way of having the HTML parser do this 2057 if (p.srci+2 >= p.esrc) 2058 return Leos; 2059 2060 if (p.src[p.srci+1] != '-' || p.src[p.srci+2] != '-') 2061 # don't treat as a comment, let the parser report syntax error 2062 return '<'; 2063 # consume "!--" 2064 p.srci += 3; 2065 if(lexhtmlcom(p) < 0) 2066 return Leos; 2067 continue; 2068 } 2069 } 2070 return '<'; 2071 '0' to '9' => 2072 p.srci--; 2073 return lexnum(p); 2074 '\\' => 2075 return lexid(p); 2076 * => 2077 if((map[c] & Malpha) != byte 0) 2078 return lexid(p); 2079 s := ""; 2080 s[0] = c; 2081 error(p, "unknown character '"+s+"'"); 2082 } 2083 } 2084 return Leos; 2085} 2086 2087# 2088# single line comment 2089# 2090lexcom(p: ref Parser): int 2091{ 2092 while(p.srci < p.esrc){ 2093 c := p.src[p.srci]; 2094 if(islt(c)) 2095 return 0; 2096 p.srci++; 2097 } 2098 return -1; 2099} 2100 2101# 2102# multi-line comment 2103# 2104lexmcom(p: ref Parser): int 2105{ 2106 star := 0; 2107 while(p.srci < p.esrc){ 2108 c := p.src[p.srci++]; 2109 if(c == '/' && star) 2110 return 0; 2111 star = c == '*'; 2112 } 2113 return -1; 2114} 2115 2116# HTML comment 2117# consume to end of line or end of comment (-->), whichever we see first. 2118# [not strict HTML comment semantics because of 2119# the way in which HTML comments are used in JavaScript] 2120# 2121lexhtmlcom(p: ref Parser): int 2122{ 2123 nmin := 0; 2124 for (;p.srci < p.esrc;) { 2125 c := p.src[p.srci++]; 2126 if (c == '-') { 2127 nmin++; 2128 continue; 2129 } 2130 if (c == '>' && nmin >= 2) 2131 return 0; 2132 if (islt(c)) 2133 return 0; 2134 nmin = 0; 2135 } 2136 return -1; 2137} 2138 2139lexid(p: ref Parser): int 2140{ 2141 p.srci--; 2142 id := ""; 2143 ch := "Z"; 2144 while(p.srci < p.esrc){ 2145 c := p.src[p.srci]; 2146 if(c == '\\'){ 2147 p.srci++; 2148 c = uniescchar(p); 2149 if(c == -1) 2150 error(p, "malformed unicode escape sequence in identifier"); 2151 else 2152 ; 2153 } 2154 else{ 2155 if(c >= 0 && c < 256 && (map[c] & (Malpha|Mdigit)) == byte 0) 2156 # if(c >= 256 || (map[c] & (Malpha|Mdigit)) == byte 0) 2157 break; 2158 p.srci++; 2159 } 2160 ch[0] = c; 2161 id += ch; 2162 } 2163 # id := p.src[srci:p.srci]; 2164 t := keywdlook(id); 2165 if(t != -1) 2166 return t; 2167 p.id = strlook(p, id); 2168 return Lid; 2169} 2170 2171ParseReal, ParseHex, ParseOct, ParseTrim, ParseEmpty: con 1 << iota; 2172 2173# 2174# parse a numeric identifier 2175# format [0-9]+(r[0-9A-Za-z]+)? 2176# or ([0-9]+(\.[0-9]*)?|\.[0-9]+)([eE][+-]?[0-9]+)? 2177# 2178lexnum(p: ref Parser): int 2179{ 2180 v: real; 2181 (p.srci, v) = parsenum(p.ex, p.src, p.srci, ParseReal|ParseHex|ParseOct); 2182 p.id = numlook(p, v); 2183 return Lnum; 2184} 2185 2186parsenum(ex: ref Exec, s: string, si, how: int): (int, real) 2187{ 2188 Inf: con "Infinity"; 2189 2190 osi := si; 2191 lens := len s; 2192 if (how & ParseTrim) { 2193 while(si < lens && iswhite(s[si])) 2194 si++; 2195 } 2196 if(si >= lens) { 2197 if (how & ParseEmpty) 2198 return (si, 0.); 2199 return (osi, Math->NaN); 2200 } 2201 c := s[si]; 2202 neg := 0; 2203 if(c == '+') 2204 si++; 2205 else if(c == '-'){ 2206 si++; 2207 neg = 1; 2208 } 2209 v := 0.; 2210 if((how & ParseReal) && si + len Inf <= lens && s[si:si+len Inf] == Inf){ 2211 si += len Inf; 2212 v = Math->Infinity; 2213 }else{ 2214 nsi := si; 2215 (si, v) = parsenumval(ex, s, si, how); 2216 if(si == nsi) 2217 return (osi, Math->NaN); 2218 } 2219 if(neg) 2220 v = -v; 2221 if (how & ParseTrim) { 2222 while(si < lens && iswhite(s[si])) 2223 si++; 2224 } 2225 return (si, v); 2226} 2227 2228# 2229# parse a bunch of difference subsets of numbers 2230# 2231parsenumval(ex: ref Exec, s: string, si, how: int): (int, real) 2232{ 2233 Int, Oct, Hex, FracSeen, Frac, ExpSeen, ExpSignSeen, Exp: con iota; 2234 2235 lens := len s; 2236 if(si >= lens) 2237 return (si, Math->NaN); 2238 ssi := si; 2239 c := s[si]; 2240 state := Int; 2241 if(c == '.' && (how & ParseReal)){ 2242 state = FracSeen; 2243 si++; 2244 }else if(c == '0'){ 2245 if(si+1 >= lens) 2246 return (si+1, 0.); 2247 c = s[si+1]; 2248 if(c == '.' && (how & ParseReal)){ 2249 state = Frac; 2250 si += 2; 2251 }else if((c == 'x' || c == 'X') && (how & ParseHex)){ 2252 state = Hex; 2253 ssi += 2; 2254 si += 2; 2255 }else if(how & ParseOct) 2256 state = Oct; 2257 } 2258 2259done: while(si < lens){ 2260 c = s[si]; 2261 case state{ 2262 Int => 2263 if((map[c] & Mdigit) != byte 0) 2264 break; 2265 if((map[c] & Mexp) != byte 0 && (how & ParseReal)) 2266 state = ExpSeen; 2267 else if(c == '.' && (how & ParseReal)) 2268 state = Frac; 2269 else 2270 break done; 2271 Hex => 2272 if((map[c] & Mhex) == byte 0) 2273 break done; 2274 Oct => 2275 if((map[c] & Moct) == byte 0) 2276 break done; 2277 FracSeen or 2278 Frac => 2279 if((map[c] & Mdigit) != byte 0) 2280 state = Frac; 2281 else if((map[c] & Mexp) != byte 0) 2282 state = ExpSeen; 2283 else 2284 break done; 2285 ExpSeen => 2286 if((map[c] & Msign) != byte 0) 2287 state = ExpSignSeen; 2288 else if((map[c] & Mdigit) != byte 0) 2289 state = Exp; 2290 else 2291 break done; 2292 ExpSignSeen or 2293 Exp => 2294 if((map[c] & Mdigit) != byte 0) 2295 state = Exp; 2296 else 2297 break done; 2298 } 2299 si++; 2300 } 2301 2302 esi := si; 2303 if(state == FracSeen) 2304 return (si - 1, Math->NaN); 2305 if(state == ExpSeen){ 2306 state = Frac; 2307 esi--; 2308 }else if(state == ExpSignSeen){ 2309 state = Frac; 2310 esi -= 2; 2311 } 2312 buf := s[ssi:esi]; 2313 v: real; 2314 case state{ 2315 * => 2316 # only if the above lexing code is wrong 2317 fatal(ex, "bad parse of numerical constant '"+buf+"'"); 2318 v = 0.; 2319 Oct => 2320 v = strtoi(ex, buf, 8); 2321 Hex => 2322 v = strtoi(ex, buf, 16); 2323 Int or 2324 Frac or 2325 Exp => 2326 v = real buf; 2327 } 2328 return (si, v); 2329} 2330 2331# 2332# called only from parsenumval 2333# can never fatal error if that routine works correctly 2334# 2335strtoi(ex: ref Exec, t: string, base: int): real 2336{ 2337 if(len t == 0) 2338 return Math->NaN; 2339 2340 v := 0.; 2341 for(i := 0; i < len t; i++){ 2342 c := t[i]; 2343 if(c >= '0' && c <= '9') 2344 c -= '0'; 2345 else if(c >= 'a' && c <= 'z') 2346 c -= 'a' - 10; 2347 else 2348 c -= 'A' - 10; 2349 if(c >= base){ 2350 fatal(ex, "digit '"+t[i:i+1]+"' is not radix "+string base); 2351 return Math->NaN; 2352 } 2353 v = v * real base + real c; 2354 } 2355 return v; 2356} 2357 2358lexstring(p: ref Parser, end: int): int 2359{ 2360 s := ""; 2361 i := 0; 2362 for(;;){ 2363 if(p.srci >= p.esrc){ 2364 error(p, "end of file in string constant"); 2365 break; 2366 } 2367 c := p.src[p.srci]; 2368 if(islt(c)){ 2369 error(p, "newline in string constant"); 2370 break; 2371 } 2372 p.srci++; 2373 if(c == end) 2374 break; 2375 if(c == '\\'){ 2376 c = escchar(p); 2377 if(c == Leos) 2378 continue; 2379 } 2380 s[i++] = c; 2381 } 2382 p.id = strlook(p, s); 2383 return Lstr; 2384} 2385 2386lexregexp(p: ref Parser): int 2387{ 2388 c := esc := 0; 2389 s := ""; 2390 i := 0; 2391 s[i++] = '/'; 2392 for(;;){ 2393 if(p.srci >= p.esrc){ 2394 error(p, "end of file in regexp constant"); 2395 break; 2396 } 2397 c = p.src[p.srci]; 2398 if(islt(c)){ 2399 error(p, "newline in regexp constant"); 2400 break; 2401 } 2402 p.srci++; 2403 s[i++] = c; 2404 if(!esc && c == '/') 2405 break; 2406 esc = !esc && c == '\\'; 2407 } 2408 if(esc) 2409 error(p, "missing escaped character"); 2410 if(i == 2) 2411 error(p, "missing regexp"); 2412 while(p.srci < p.esrc){ 2413 c = p.src[p.srci]; 2414 if(c >= 256 || (map[c] & (Malpha|Mdigit)) == byte 0) 2415 break; 2416 p.srci++; 2417 s[i++] = c; 2418 } 2419 p.id = strlook(p, s); 2420 return Lregexp; 2421} 2422 2423uniescchar(p: ref Parser): int 2424{ 2425 if(p.srci >= p.esrc) 2426 return -1; 2427 c := p.src[p.srci++]; 2428 if(c != 'u') 2429 return -1; 2430 v := 0; 2431 for(i := 0; i < 4; i++){ 2432 if(p.srci >= p.esrc || (map[c = p.src[p.srci]] & (Mdigit|Mhex)) == byte 0) 2433 return -1; 2434 p.srci++; 2435 if((map[c] & Mdigit) != byte 0) 2436 c -= '0'; 2437 else if((map[c] & Mlower) != byte 0) 2438 c = c - 'a' + 10; 2439 else if((map[c] & Mupper) != byte 0) 2440 c = c - 'A' + 10; 2441 v = v * 16 + c; 2442 } 2443 return v; 2444} 2445 2446escchar(p: ref Parser): int 2447{ 2448 v: int; 2449 if(p.srci >= p.esrc) 2450 return Leos; 2451 c := p.src[p.srci++]; 2452 if(c == 'u' || c == 'x'){ 2453 d := 2; 2454 if(c == 'u') 2455 d = 4; 2456 v = 0; 2457 for(i := 0; i < d; i++){ 2458 if(p.srci >= p.esrc || (map[c = p.src[p.srci]] & (Mdigit|Mhex)) == byte 0){ 2459 error(p, "malformed hex escape sequence"); 2460 break; 2461 } 2462 p.srci++; 2463 if((map[c] & Mdigit) != byte 0) 2464 c -= '0'; 2465 else if((map[c] & Mlower) != byte 0) 2466 c = c - 'a' + 10; 2467 else if((map[c] & Mupper) != byte 0) 2468 c = c - 'A' + 10; 2469 v = v * 16 + c; 2470 } 2471 return v; 2472 } 2473 if(c >= '0' && c <= '7'){ 2474 v = c - '0'; 2475 if(p.srci < p.esrc && (c = p.src[p.srci]) >= '0' && c <= '7'){ 2476 p.srci++; 2477 v = v * 8 + c - '0'; 2478 if(v <= 8r37 && p.srci < p.esrc && (c = p.src[p.srci]) >= '0' && c <= '7'){ 2479 p.srci++; 2480 v = v * 8 + c - '0'; 2481 } 2482 } 2483 return v; 2484 } 2485 2486 if(c < len escmap && (v = int escmap[c]) < 255) 2487 return v; 2488 return c; 2489} 2490 2491keywdlook(s: string): int 2492{ 2493 m: int; 2494 l := 1; 2495 r := len keywords - 1; 2496 while(l <= r){ 2497 m = (r + l) >> 1; 2498 if(keywords[m].name <= s) 2499 l = m + 1; 2500 else 2501 r = m - 1; 2502 } 2503 m = l - 1; 2504 if(keywords[m].name == s) 2505 return keywords[m].token; 2506 return -1; 2507} 2508 2509strlook(p: ref Parser, s: string): int 2510{ 2511 for(i := 0; i < len p.code.strs; i++) 2512 if(p.code.strs[i] == s) 2513 return i; 2514 strs := array[i + 1] of string; 2515 strs[:] = p.code.strs; 2516 strs[i] = s; 2517 p.code.strs = strs; 2518 return i; 2519} 2520 2521numlook(p: ref Parser, r: real): int 2522{ 2523 for(i := 0; i < len p.code.nums; i++) 2524 if(p.code.nums[i] == r) 2525 return i; 2526 nums := array[i + 1] of real; 2527 nums[:] = p.code.nums; 2528 nums[i] = r; 2529 p.code.nums = nums; 2530 return i; 2531} 2532 2533fexplook(p: ref Parser, o: ref Obj): int 2534{ 2535 i := len p.code.fexps; 2536 fexps := array[i+1] of ref Obj; 2537 fexps[:] = p.code.fexps; 2538 fexps[i] = o; 2539 p.code.fexps = fexps; 2540 return i; 2541} 2542 2543iswhite(c: int): int 2544{ 2545 if(islt(c)) 2546 return 1; 2547 case c { 2548 ' ' or 2549 '\t' or 2550 '\v' or 2551 FF or # form feed 2552 '\u00a0' => # no-break space 2553 return 1; 2554 } 2555 return 0; 2556} 2557 2558error(p: ref Parser, s: string) 2559{ 2560 p.errors++; 2561 p.ex.error += sys->sprint("%d: syntax error: %s\n", p.lineno, s); 2562 if(p.errors >= maxerr) 2563 runtime(p.ex, SyntaxError, p.ex.error); 2564} 2565 2566fatal(ex: ref Exec, msg: string) 2567{ 2568 if(debug['f']){ 2569 print("fatal ecmascript error: %s\n", msg); 2570 if(""[5] == -1); # abort 2571 } 2572 runtime(ex, InternalError, "unrecoverable internal ecmascript error: "+ msg); 2573} 2574 2575# scanb(p: ref Parser, s: string): int 2576# { 2577# n := len s; 2578# for(i := p.srci; i+n > p.esrc || p.src[i: i+n] != s; --i) 2579# ; 2580# return i; 2581# } 2582 2583setkindlab(p: ref Parser, op: int, n: int) 2584{ 2585 l := p.labs; 2586 for(i := 0; i < n; i++){ 2587 (hd l).k = op; 2588 l = tl l; 2589 } 2590} 2591 2592inlocallabs(p: ref Parser, lr: ref labrec, n: int): int 2593{ 2594 l := p.labs; 2595 for(i := 0; i < n; i++){ 2596 if(hd l == lr) 2597 return 1; 2598 l = tl l; 2599 } 2600 return 0; 2601} 2602 2603findlab(p: ref Parser, s: string): ref labrec 2604{ 2605 for(l := p.labs; l != nil; l = tl l) 2606 if((hd l).s == s) 2607 return hd l; 2608 return nil; 2609} 2610 2611pushlab(p: ref Parser, s: string) 2612{ 2613 if(findlab(p, s) != nil) 2614 error(p, "duplicate labels"); 2615 p.labs = ref labrec(s, 0) :: p.labs; 2616} 2617 2618poplab(p: ref Parser) 2619{ 2620 p.labs = tl p.labs; 2621} 2622 2623itstmt(k: int): int 2624{ 2625 return k == Lwhile || k == Ldo || k == Lfor; 2626} 2627