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