xref: /inferno-os/appl/lib/ecmascript/ecmascript.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
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