BSD 1 development
[unix-history] / pcs / block.i
procedure block(fsys: symset; isfun: boolean; level: integer);
type conrec =
record case tp: types of
ints,chars,bools: (i: integer);
reals: (r: real)
end ;
var dx: integer; (*data allocation index*)
prt: integer; (*t-index of this procedure*)
prb: integer; (*b-index of this procedure*)
x: integer;
procedure skip(fsys: symset; n: integer);
begin error(n);
while not (sy in fsys) do insymbol
end (*skip*) ;
procedure test(s1,s2: symset; n: integer);
begin if not (sy in s1) then
skip(s1+s2,n)
end (*test*) ;
procedure testsemicolon;
begin
if sy = semicolon then insymbol else
begin error(14);
if sy in [comma,colon] then insymbol
end ;
test([ident]+blockbegsys, fsys, 6)
end (*testsemicolon*) ;
procedure enter(id: alfa; k: object);
var j,l: integer;
begin if t = tmax then fatal(1) else
begin tab[0].name := id;
j := btab[display[level]].last; l := j;
while tab[j].name <> id do j := tab[j].link;
if j <> 0 then error(1) else
begin t := t+1;
with tab[t] do
begin name := id; link := l;
obj := k; typ := notyp; ref := 0; lev := level; adr := 0
end ;
btab[display[level]].last := t
end
end
end (*enter*) ;
function loc(id: alfa): integer;
var i,j: integer; (*locate id in table*)
begin i := level; tab[0].name := id; (*sentinel*)
repeat j := btab[display[i]].last;
while tab[j].name <> id do j := tab[j].link;
i := i-1;
until (i<0) or (j<>0);
if j = 0 then error(0); loc := j
end (*loc*) ;
procedure entervariable;
begin if sy = ident then
begin enter(id,variable); insymbol
end
else error(2)
end (*entervariable*) ;
procedure constant(fsys: symset; var c: conrec);
var x, sign: integer;
begin c.tp := notyp; c.i := 0;
test(constbegsys, fsys, 50);
if sy in constbegsys then
begin
if sy = charcon then
begin c.tp := chars; c.i := inum; insymbol
end
else
begin sign := 1;
if sy in [plus,minus] then
begin if sy = minus then sign := -1;
insymbol
end ;
if sy = ident then
begin x := loc(id);
if x <> 0 then
if tab[x].obj <> konstant then error(25) else
begin c.tp := tab[x].typ;
if c.tp = reals then c.r := sign*rconst[tab[x].adr]
else c.i := sign*tab[x].adr
end ;
insymbol
end
else
if sy = intcon then
begin c.tp := ints; c.i := sign*inum; insymbol
end else
if sy = realcon then
begin c.tp := reals; c.r := sign*rnum; insymbol
end else skip(fsys,50)
end;
test(fsys, [], 6)
end
end (*constant*) ;
procedure typ(fsys: symset; var tp: types; var rf, sz: integer);
var x: integer;
eltp: types; elrf: integer;
elsz, offset, t0,t1: integer;
procedure arraytyp(var aref,arsz: integer);
var eltp: types;
low, high: conrec;
elrf, elsz: integer;
begin constant([colon,rbrack,rparent,ofsy]+fsys, low);
if low.tp = reals then
begin error(27); low.tp := ints; low.i := 0
end ;
if sy = colon then insymbol else error(13);
constant([rbrack,comma,rparent,ofsy]+fsys, high);
if high.tp <> low.tp then
begin error(27); high.i := low.i
end ;
enterarray(low.tp, low.i, high.i); aref := a;
if sy = comma then
begin insymbol; eltp := arrays; arraytyp(elrf,elsz)
end else
begin
if sy = rbrack then insymbol else
begin error(12);
if sy = rparent then insymbol
end ;
if sy = ofsy then insymbol else error(8);
typ(fsys,eltp,elrf,elsz)
end ;
with atab[aref] do
begin arsz := (high-low+1)*elsz; size := arsz;
eltyp := eltp; elref := elrf; elsize := elsz
end ;
end (*arraytyp*) ;
begin (*typ*) tp := notyp; rf := 0; sz := 0;
test(typebegsys, fsys, 10);
if sy in typebegsys then
begin
if sy = ident then
begin x := loc(id);
if x <> 0 then
with tab[x] do
if obj <> type1 then error(29) else
begin tp := typ; rf := ref; sz := adr;
if tp = notyp then error(30)
end ;
insymbol
end else
if sy = arraysy then
begin insymbol;
if sy = lbrack then insymbol else
begin error(11);
if sy = lparent then insymbol
end ;
tp := arrays; arraytyp(rf,sz)
end else
begin (*records*) insymbol;
enterblock; tp := records; rf := b;
if level = lmax then fatal(5);
level := level+1; display[level] := b; offset := 0;
while sy <> endsy do
begin (*field section*)
if sy = ident then
begin t0 := t; entervariable;
while sy = comma do
begin insymbol; entervariable
end ;
if sy = colon then insymbol else error(5);
t1 := t;
typ(fsys+[semicolon,endsy,comma,ident],eltp,elrf,elsz);
while t0 < t1 do
begin t0 := t0+1;
with tab[t0] do
begin typ := eltp; ref := elrf; normal := true;
adr := offset; offset := offset + elsz
end
end
end ;
if sy <> endsy then
begin if sy = semicolon then insymbol else
begin error(14);
if sy = comma then insymbol
end ;
test([ident,endsy,semicolon], fsys, 6)
end
end ;
btab[rf].vsize := offset; sz := offset; btab[rf].psize := 0;
insymbol; level := level-1
end ;
test(fsys, [], 6)
end
end (*typ*) ;
procedure parameterlist; (*formal parameter list*)
var tp: types;
rf, sz, x, t0: integer;
valpar: boolean;
begin insymbol; tp := notyp; rf := 0; sz := 0;
test([ident, varsy], fsys+[rparent], 7);
while sy in [ident,varsy] do
begin if sy <> varsy then valpar := true else
begin insymbol; valpar := false
end ;
t0 := t; entervariable;
while sy = comma do
begin insymbol; entervariable;
end ;
if sy = colon then
begin insymbol;
if sy <> ident then error(2) else
begin x := loc(id); insymbol;
if x <> 0 then
with tab[x] do
if obj <> type1 then error(29) else
begin tp := typ; rf := ref;
if valpar then sz := adr else sz := 1
end ;
end ;
test([semicolon,rparent], [comma,ident]+fsys, 14)
end
else error(5);
while t0 < t do
begin t0 := t0+1;
with tab[t0] do
begin typ := tp; ref := rf;
normal := valpar; adr := dx; lev := level;
dx := dx + sz
end
end ;
if sy <> rparent then
begin if sy = semicolon then insymbol else
begin error(14);
if sy = comma then insymbol
end ;
test([ident,varsy], [rparent]+fsys, 6)
end
end (*while*) ;
if sy = rparent then
begin insymbol;
test([semicolon,colon], fsys, 6)
end
else error(4)
end (*parameterlist*) ;
procedure constantdeclaration;
var c: conrec;
begin insymbol;
test([ident], blockbegsys, 2);
while sy = ident do
begin enter(id,konstant); insymbol;
if sy = eql then insymbol else
begin error(16);
if sy = becomes then insymbol
end ;
constant([semicolon,comma,ident]+fsys,c);
tab[t].typ := c.tp; tab[t].ref := 0;
if c.tp = reals then
begin enterreal(c.r); tab[t].adr := c1 end
else tab[t].adr := c.i;
testsemicolon
end
end (*constantdeclaration*) ;
procedure typedeclaration;
var tp: types; rf, sz, t1: integer;
begin insymbol;
test([ident], blockbegsys, 2);
while sy = ident do
begin enter(id,type1); t1 := t; insymbol;
if sy = eql then insymbol else
begin error(16);
if sy = becomes then insymbol
end ;
typ([semicolon,comma,ident]+fsys, tp, rf, sz);
with tab[t1] do
begin typ := tp; ref := rf; adr := sz
end ;
testsemicolon
end
end (*typedeclaration*) ;
procedure variabledeclaration;
var t0, t1, rf, sz: integer;
tp: types;
begin insymbol;
while sy = ident do
begin t0 := t; entervariable;
while sy = comma do
begin insymbol; entervariable;
end ;
if sy = colon then insymbol else error(5);
t1 := t;
typ([semicolon,comma,ident]+fsys, tp, rf, sz);
while t0 < t1 do
begin t0 := t0+1;
with tab[t0] do
begin typ := tp; ref := rf;
lev := level; adr := dx; normal := true;
dx := dx + sz
end
end ;
testsemicolon
end
end (*variabledeclaration*) ;
procedure procdeclaration;
var isfun: boolean;
begin isfun := sy = functionsy; insymbol;
if sy <> ident then
begin error(2); id := ' '
end ;
if isfun then enter(id,funktion) else enter(id,prozedure);
tab[t].normal := true;
insymbol; block([semicolon]+fsys, isfun, level+1);
if sy = semicolon then insymbol else error(14);
emit(32+ord(isfun)) (*exit*)
end (*proceduredeclaration*) ;
(*---------------------------------------------------------statement--*)
procedure statement(fsys: symset);
var i: integer;
procedure expression(fsys: symset; var x: item); forward;
procedure selector(fsys: symset; var v:item);
var x: item; a,j: integer;
begin (*sy in [lparent, lbrack, period]*)
repeat
if sy = period then
begin insymbol; (*field selector*)
if sy <> ident then error(2) else
begin
if v.typ <> records then error(31) else
begin (*search field identifier*)
j := btab[v.ref] .last; tab[0].name := id;
while tab[j].name <> id do j := tab[j].link;
if j = 0 then error(0);
v.typ := tab[j].typ; v.ref := tab[j].ref;
a := tab[j].adr; if a <> 0 then emit1(9,a)
end ;
insymbol
end
end else
begin (*array selector*)
if sy <> lbrack then error(11);
repeat insymbol;
expression(fsys+[comma,rbrack], x);
if v.typ <> arrays then error(28) else
begin a := v.ref;
if atab[a].inxtyp <> x.typ then error(26) else
if atab[a].elsize = 1 then emit1(20,a) else emit1(21,a);
v.typ := atab[a].eltyp; v.ref := atab[a].elref
end
until sy <> comma;
if sy = rbrack then insymbol else
begin error(12); if sy = rparent then insymbol
end
end
until not (sy in [lbrack,lparent,period]);
test(fsys, [], 6)
end (*selector*) ;
procedure call(fsys: symset; i: integer);
var x: item;
lastp, cp, k: integer;
begin emit1(18,i); (*mark stack*)
lastp := btab[tab[i].ref].lastpar; cp := i;
if sy = lparent then
begin (*actual parameter list*)
repeat insymbol;
if cp >= lastp then error(39) else
begin cp := cp+1;
if tab[cp].normal then
begin (*value parameter*)
expression(fsys+[comma,colon,rparent], x);
if x.typ=tab[cp].typ then
begin
if x.ref <> tab[cp].ref then error(36) else
if x.typ = arrays then emit1(22,atab[x.ref].size) else
if x.typ = records then emit1(22,btab[x.ref].vsize)
end else
if (x.typ=ints) and (tab[cp].typ=reals) then
emit1(26,0) else
if x.typ<>notyp then error(36);
end else
begin (*variable parameter*)
if sy <> ident then error(2) else
begin k := loc(id); insymbol;
if k <> 0 then
begin if tab[k].obj <> variable then error(37);
x.typ := tab[k].typ; x.ref := tab[k].ref;
if tab[k].normal then emit2(0,tab[k].lev,tab[k].adr)
else emit2(1,tab[k].lev,tab[k].adr);
if sy in [lbrack,lparent,period] then
selector(fsys+[comma,colon,rparent], x);
if (x.typ<>tab[cp].typ) or (x.ref<>tab[cp].ref) then
error(36)
end
end
end
end ;
test([comma,rparent], fsys, 6)
until sy <> comma;
if sy = rparent then insymbol else error(4)
end ;
if cp < lastp then error(39); (*too few actual parameters*)
emit1(19, btab[tab[i].ref].psize-1);
if tab[i].lev < level then emit2(3, tab[i].lev, level)
end (*call*) ;
function resulttype(a,b: types): types;
begin
if (a>reals) or (b>reals) then
begin error(33); resulttype := notyp
end else
if (a=notyp) or (b=notyp) then resulttype := notyp else
if a=ints then
if b=ints then resulttype := ints else
begin resulttype := reals; emit1(26,1)
end
else
begin resulttype := reals;
if b=ints then emit1(26,0)
end
end (*resulttype*) ;
procedure expression;
var y:item; op:symbol;
procedure simpleexpression(fsys:symset; var x:item);
var y:item; op:symbol;
procedure term(fsys:symset; var x:item);
var y:item; op:symbol;
procedure factor(fsys:symset; var x:item);
var i,f: integer;
procedure standfct(n: integer);
var ts: typset;
begin (*standard function no. n*)
if sy = lparent then insymbol else error(9);
if n < 17 then
begin expression(fsys+[rparent],x);
case n of
(*abs,sqr*) 0,2: begin ts := [ints,reals]; tab[i].typ := x.typ;
if x.typ = reals then n := n+1
end ;
(*odd,chr*) 4,5: ts := [ints];
(*ord*) 6: begin
if x.typ = ints then n := 19;
ts := [ints,bools,chars];
end;
(*succ,pred*) 7,8: ts := [chars];
(*round,trunc*) 9,10,11,12,13,14,15,16:
(*sin,cos,...*) begin ts := [ints,reals];
if x.typ = ints then emit1(26,0)
end ;
end ;
if x.typ in ts then emit1(8,n) else
if x.typ <> notyp then error(48);
end else
(*eof,eoln*) begin (*n in [17,18]*)
if sy <> ident then error(2) else
if id <> 'input ' then error(0) else insymbol;
emit1(8,n);
end ;
x.typ := tab[i].typ;
if sy = rparent then insymbol else error(4)
end (*standfct*) ;
begin (*factor*) x.typ := notyp; x.ref := 0;
test(facbegsys, fsys, 58);
while sy in facbegsys do
begin
if sy = ident then
begin i := loc(id); insymbol;
with tab[i] do
case obj of
konstant: begin x.typ := typ; x.ref := 0;
case x.typ of
ints: emit1(24,adr);
reals: emit1(25,adr);
bools: emit1(64,adr);
chars: emit1(65,adr);
end;
end ;
variable: begin x.typ := typ; x.ref := ref;
if sy in [lbrack,lparent,period] then
begin if normal then f := 0 else f := 1;
emit2(f, lev, adr);
selector(fsys,x);
if x.typ in stantyps then emit(34)
end else
begin
if x.typ in stantyps then
if normal then f := 1 else f := 2
else
if normal then f := 0 else f := 1;
emit2(f, lev, adr)
end
end ;
type1, prozedure: error(44);
funktion :begin x.typ := typ;
if lev <> 0 then call(fsys, i)
else standfct(adr)
end
end (*case,with*)
end else
if sy in [charcon,intcon,realcon] then
begin
if sy = realcon then
begin x.typ := reals; enterreal(rnum);
emit1(25, c1)
end else
begin
if sy = charcon then begin
x.typ := chars;
emit1(65, inum);
end else begin
x.typ := ints;
emit1(24, inum);
end;
end ;
x.ref := 0; insymbol
end else
if sy = lparent then
begin insymbol; expression(fsys+[rparent], x);
if sy = rparent then insymbol else error(4)
end else
if sy = notsy then
begin insymbol; factor(fsys,x);
if x.typ=bools then emit(35) else
if x.typ<>notyp then error(32)
end ;
test(fsys, facbegsys, 6)
end (*while*)
end (*factor*) ;
begin (*term*)
factor(fsys+[times,rdiv,idiv,imod,andsy], x);
while sy in [times,rdiv,idiv,imod,andsy] do
begin op := sy; insymbol;
factor(fsys+[times,rdiv,idiv,imod,andsy], y);
if op = times then
begin x.typ := resulttype(x.typ, y.typ);
case x.typ of
notyp: ;
ints : emit(57);
reals: emit(60);
end
end else
if op = rdiv then
begin
if x.typ = ints then
begin emit1(26,1); x.typ := reals
end ;
if y.typ = ints then
begin emit1(26,0); y.typ := reals
end ;
if (x.typ=reals) and (y.typ=reals) then emit(61) else
begin if (x.typ<>notyp) and (y.typ<>notyp) then
error(33);
x.typ := notyp
end
end else
if op = andsy then
begin if (x.typ=bools) and (y.typ=bools) then
emit(56) else
begin if (x.typ<>notyp) and (y.typ<>notyp) then
error(32);
x.typ := notyp
end
end else
begin (*op in [idiv,imod]*)
if (x.typ=ints) and (y.typ=ints) then
if op=idiv then emit(58)
else emit(59) else
begin if (x.typ<>notyp) and (y.typ<>notyp) then
error(34);
x.typ := notyp
end
end
end
end (*term*) ;
begin (*simpleexpression*)
if sy in [plus,minus] then
begin op := sy; insymbol;
term(fsys+[plus,minus], x);
if x.typ > reals then error(33) else
if op = minus then
if x.typ = reals then
emit(66)
else
emit(36)
end else
term(fsys+[plus,minus,orsy], x);
while sy in [plus,minus,orsy] do
begin op := sy; insymbol;
term(fsys+[plus,minus,orsy], y);
if op = orsy then
begin
if (x.typ=bools) and (y.typ=bools) then emit(51) else
begin if (x.typ<>notyp) and (y.typ<>notyp) then
error(32);
x.typ := notyp
end
end else
begin x.typ := resulttype(x.typ, y.typ);
case x.typ of
notyp: ;
ints : if op = plus then emit(52)
else emit(53);
reals: if op = plus then emit(54)
else emit(55)
end
end
end
end (*simpleexpression*) ;
begin (*expression*)
simpleexpression(fsys+[eql,neq,lss,leq,gtr,geq], x);
if sy in [eql,neq,lss,leq,gtr,geq] then
begin op := sy; insymbol;
simpleexpression(fsys, y);
if (x.typ in [ notyp,ints,bools,chars]) and (x.typ = y.typ) then
case op of
eql: emit(45);
neq: emit(46);
lss: emit(47);
leq: emit(48);
gtr: emit(49);
geq: emit(50);
end else
begin if x.typ = ints then
begin x.typ := reals; emit1(26,1)
end else
if y.typ = ints then
begin y.typ := reals; emit1(26,0)
end ;
if (x.typ=reals) and (y.typ=reals) then
case op of
eql: emit(39);
neq: emit(40);
lss: emit(41);
leq: emit(42);
gtr: emit(43);
geq: emit(44);
end
else error(35)
end ;
x.typ := bools
end
end (*expression*) ;
procedure assignment(lv,ad: integer);
var x,y: item; f: integer;
(*tab[i].obj in [variable,prozedure]*)
begin x.typ := tab[i].typ; x.ref := tab[i].ref;
if tab[i].normal then f := 0 else f := 1;
emit2(f, lv, ad);
if sy in [lbrack,lparent,period] then
selector([becomes,eql]+fsys, x);
if sy = becomes then insymbol else
begin error(51); if sy = eql then insymbol
end ;
expression(fsys, y);
if x.typ = y.typ then
if x.typ in stantyps then emit(38) else
if x.ref <> y.ref then error(46) else
if x.typ = arrays then emit1(23, atab[x.ref].size)
else emit1(23, btab[x.ref].vsize)
else
if (x.typ=reals) and (y.typ=ints) then
begin emit1(26,0); emit(38)
end else
if (x.typ<>notyp) and (y.typ<>notyp) then error(46)
end (*assignment*) ;
procedure compoundstatement;
begin insymbol;
statement([semicolon,endsy]+fsys);
while sy in [semicolon]+statbegsys do
begin if sy = semicolon then insymbol else error(14);
statement([semicolon,endsy]+fsys)
end ;
if sy = endsy then insymbol else error(57)
end (*compoundstatemenet*) ;
procedure ifstatement;
var x: item; lc1,lc2: integer;
begin insymbol;
expression(fsys+[thensy,dosy], x);
if not (x.typ in [bools,notyp]) then error(17);
lc1 := lc; emit(11); (*jmpc*)
if sy = thensy then insymbol else
begin error(52); if sy = dosy then insymbol
end ;
statement(fsys+[elsesy]);
if sy = elsesy then
begin insymbol; lc2 := lc; emit(10);
code[lc1].y := lc; statement(fsys); code[lc2].y := lc
end
else code[lc1].y := lc
end (*ifstatement*) ;
procedure casestatement;
var x: item;
i,j,k,lc1: integer;
casetab: array [1..csmax] of
packed record val, lc: index end ;
exittab: array [1..csmax] of integer;
procedure caselabel;
var lab: conrec; k: integer;
begin constant(fsys+[comma,colon], lab);
if lab.tp <> x.typ then error(47) else
if i = csmax then fatal(6) else
begin i := i+1; k := 0;
casetab[i].val := lab.i; casetab[i].lc := lc;
repeat k := k+1 until casetab[k].val = lab.i;
if k < i then error(1); (*multiple definition*)
end
end (*caselabel*) ;
procedure onecase;
begin if sy in constbegsys then
begin caselabel;
while sy = comma do
begin insymbol; caselabel
end ;
if sy = colon then insymbol else error(5);
statement([semicolon,endsy]+fsys);
j := j+1; exittab[j] := lc; emit(10)
end
end (*onecase*) ;
begin insymbol; i := 0; j := 0;
expression(fsys+[ofsy,comma,colon], x);
if not (x.typ in [ints,bools,chars,notyp]) then error(23);
lc1 := lc; emit(12); (*jmpx*)
if sy = ofsy then insymbol else error(8);
onecase;
while sy = semicolon do
begin insymbol; onecase
end ;
code[lc1].y := lc;
for k := 1 to i do
begin emit1(13,casetab[k].val); emit1(13,casetab[k].lc)
end ;
emit1(10,0);
for k := 1 to j do code[exittab[k]].y := lc;
if sy = endsy then insymbol else error(57)
end (*casestatement*) ;
procedure repeatstatement;
var x: item; lc1: integer;
begin lc1 := lc;
insymbol; statement([semicolon,untilsy]+fsys);
while sy in [semicolon]+statbegsys do
begin if sy = semicolon then insymbol else error(14);
statement([semicolon,untilsy]+fsys)
end ;
if sy = untilsy then
begin insymbol; expression(fsys, x);
if not (x.typ in [bools,notyp]) then error(17);
emit1(11,lc1)
end
else error(53)
end (*repeatstatement*) ;
procedure whilestatement;
var x: item; lc1,lc2: integer;
begin insymbol; lc1 := lc;
expression(fsys+[dosy], x);
if not (x.typ in [bools,notyp]) then error(17);
lc2 := lc; emit(11);
if sy = dosy then insymbol else error(54);
statement(fsys); emit1(10,lc1); code[lc2].y := lc
end (*whilestatement*) ;
procedure forstatement;
var cvt: types; x: item;
i,f,lc1,lc2: integer;
begin insymbol;
if sy = ident then
begin i := loc(id); insymbol;
if i = 0 then cvt := ints else
if tab[i].obj = variable then
begin cvt := tab[i].typ;
if not tab[i].normal then error(37) else
emit2(0, tab[i].lev, tab[i].adr);
if not (cvt in [notyp,ints,bools,chars]) then error(18)
end else
begin error(37); cvt := ints
end
end else skip([becomes,tosy,downtosy,dosy]+fsys, 2);
if sy = becomes then
begin insymbol; expression([tosy,downtosy,dosy]+fsys, x);
if x.typ <> cvt then error(19);
end else skip([tosy,downtosy,dosy]+fsys, 51);
f := 14;
if sy in [tosy, downtosy] then
begin if sy = downtosy then f := 16;
insymbol; expression([dosy]+fsys, x);
if x.typ <> cvt then error(19)
end else skip([dosy]+fsys, 55);
lc1 := lc; emit(f);
if sy = dosy then insymbol else error(54);
lc2 := lc; statement(fsys);
emit1(f+1,lc2); code[lc1].y := lc
end (*forstatement*) ;
procedure standproc(n: integer);
var i,f: integer;
x,y: item;
begin
case n of
1,2: begin (*read*)
if not iflag then
begin error(20); iflag := true
end ;
if sy = lparent then
begin
repeat insymbol;
if sy <> ident then error(2) else
begin i := loc(id); insymbol;
if i <> 0 then
if tab[i].obj <> variable then error(37) else
begin x.typ := tab[i].typ; x.ref := tab[i].ref;
if tab[i].normal then f := 0 else f := 1;
emit2(f, tab[i].lev, tab[i].adr);
if sy in [lbrack,lparent,period] then
selector(fsys+[comma,rparent], x);
if x.typ in [ints,reals,chars,notyp] then
emit1(27, ord(x.typ)) else error(40)
end
end ;
test([comma,rparent], fsys, 6);
until sy <> comma;
if sy = rparent then insymbol else error(4)
end ;
if n = 2 then emit(62)
end ;
3,4: begin (*write*)
if sy = lparent then
begin
repeat insymbol;
if sy = string then
begin emit1(24,sleng); emit1(28,inum); insymbol
end else
begin expression(fsys+[comma,colon,rparent], x);
if not (x.typ in stantyps) then error(41);
if sy = colon then
begin insymbol;
expression(fsys+[comma,colon,rparent], y);
if y.typ <> ints then error(43);
if sy = colon then
begin if x.typ <> reals then error(42);
insymbol; expression(fsys+[comma,rparent], y);
if y.typ <> ints then error(43);
emit(37)
end
else emit1(30, ord(x.typ))
end
else emit1(29, ord(x.typ))
end
until sy <> comma;
if sy = rparent then insymbol else error(4)
end ;
if n = 4 then emit(63)
end ;
end (*case*)
end (*standproc*) ;
begin (*statement*)
if sy in statbegsys+[ident] then
case sy of
ident: begin i := loc(id); insymbol;
if i <> 0 then
case tab[i].obj of
konstant, type1: error(45);
variable: assignment(tab[i].lev, tab[i].adr);
prozedure:
if tab[i].lev <> 0 then call(fsys, i)
else standproc(tab[i].adr);
funktion:
if tab[i].ref = display[level] then
assignment(tab[i].lev+1, 0) else error(45)
end
end ;
beginsy: compoundstatement;
ifsy: ifstatement;
casesy: casestatement;
whilesy: whilestatement;
repeatsy: repeatstatement;
forsy: forstatement;
end;
test(fsys, [], 14)
end (*statement*) ;
begin (*block*) dx := 5; prt := t;
if level > lmax then fatal(5);
test([lparent,colon,semicolon], fsys, 7);
enterblock; display[level] := b; prb := b;
tab[prt].typ := notyp; tab[prt].ref := prb;
if sy = lparent then parameterlist;
btab[prb].lastpar := t; btab[prb].psize := dx;
if isfun then
if sy = colon then
begin insymbol; (*function type*)
if sy = ident then
begin x := loc(id); insymbol;
if x <> 0 then
if tab[x].obj <> type1 then error(29) else
if tab[x].typ in stantyps then tab[prt].typ := tab[x].typ
else error(15)
end else skip([semicolon]+fsys, 2)
end else error(5);
if sy = semicolon then insymbol else error(14);
repeat
if sy = constsy then constantdeclaration;
if sy = typesy then typedeclaration;
if sy = varsy then variabledeclaration;
btab[prb].vsize := dx;
while sy in [proceduresy,functionsy] do procdeclaration;
test([beginsy], blockbegsys+statbegsys, 56)
until sy in statbegsys;
tab[prt].adr := lc;
insymbol; statement([semicolon,endsy]+fsys);
while sy in [semicolon]+statbegsys do
begin if sy = semicolon then insymbol else error(14);
statement([semicolon,endsy]+fsys)
end ;
if sy = endsy then insymbol else error(57);
test(fsys+[period], [], 6)
end (*block*) ;