home *** CD-ROM | disk | FTP | other *** search
- (*
- TITLE Pascal Pascal Compiler (pascal self compiler)
- FILENAME PPC.PAS
- AUTHOR Robert A. Van Valzah 9/01/79
- LAST REVISOR R. A. V. 01/05/80
- REASON repaired bug in var parameters
- *)
-
- (*
- This is a single pass pascal subset compiler. Source code
- is read from the input device and a listing is produced.
- A label addressed p-code is used so that forward references
- are no problem. The use of theses labels removes the need for
- "backplugging", and with it, the need to keep the generated
- p-codes around in core. This cuts down on memory requirements
- and allows the compiler to write the p-code to disk as it is
- generated. The overall design uses recursive descent where
- ever possible.
-
- internal structure
- ==================
- The compiler can be broken down into the major functional units
- shown in the table below. In this compiler, code generation is
- rolled right in with the parsing routines. As soon as a valid
- construct is recognized, code for it is emitted.
-
- Block nesting and function is shown below.
-
- FUNCTION ROUTINE NAME
- ======== ============
- error processing error, test
- symbol table routines enter, position
- token scanner getsym
- char scanner getch, getline, etc.
- semantic routines block
- declaritive const, typ, var dcl
- statement scanner statement
- expression scanner epxression, sexp, term, factor
- main line
- *)
-
- const
- vhu = 0; (* version number hundreds *)
- vtn = 0; (* tens *)
- vun = 8; (* units *)
- devrel = 'r'; (* development or release version *)
- norw = 29; (* number of reserved words *)
- al = 8; (* length of identifiers *)
- alm1 = 7; (* length of id minus 1 *)
- llen = 80; (* max input line length *)
- symax = 300; (* max number of symbol table entrys *)
- ordminchar = 0; (* minimum legal char ord value *)
- ordmaxchar = 127; (* maximum legal char ord value *)
- intsize = 2; (* size of integer in stack units *)
- charsize = 1; (* size of character *)
- boolsize = 2; (* size of boolean *)
- alfasize = 8; (* size of alfa *)
- true = 1; (* kludge until implemented in compiler *)
- false = 0;
-
- type symbol = ( (* symbol tokens *)
- nul, ident, number, charcon,
- plus, minus, times,
- slash, eql, lss, gtr, lparen, rparen,
- comma, semicolon, period, lbrack, rbrack,
- colon, pound,
- andsym, arraysym,
- beginsym, casesym, constsym,
- divsym, dosym, downtosym, elsesym,
- endsym, forsym, funcsym, getsy,
- ifsym, modsym, notsym, ofsym,
- orsym, procsym, progsym, putsym, recordsym,
- repeatsym, thensym, tosym, typesym,
- untilsym, varsym, whilesym
- );
- object = ( (* types of symbol table entrys *)
- notype, constant, prozedure, funktion,
- simpvar, arrayvar, tipe, simptype, varparm
- );
- pops = ( (* p-op codes *)
- cal, jpc, jmp, lit, opr, lod, sto, int,
- csp, lodx, stox, alit, alod, asto,
- alodx, astox, pshf, clod, csto,
- clodx, cstox, halt, lab,
- peof, (* end of p-code file *)
- laa, lodi, stoi, clodi, cstoi, alodi, astoi,
- indx, aindx, cindx
- );
- exptyp = ( (* possible expression types *)
- wurd, alpha, chars, dontcare
- );
-
- (* define all array types needed
- this is a temporary kludge until the compiler
- will accept arrays in var declarations
- *)
-
- rwwtyp = array[0..norw] of word;
- rwatyp = array[0..norw] of alfa;
- alatyp = array[0..alm1] of word;
- chatyp = array[ordminchar..ordmaxchar] of word;
- linetyp = array[0..llen] of word;
- statyp = array[0..symax] of alfa;
- stwtyp = array[0..symax] of word;
-
- var
- (* indexed by reserved word number *)
- wsym : rwwtyp; (* gives token of type symbol *)
- rword : rwatyp; (* holds reserved word in order *)
-
- (* indexed by ascii character value *)
- ssym : chatyp; (* gives token of type sybol *)
-
- (* indexed by character number 0 .. *)
- ccon : linetyp; (* last character constant read *)
-
- (* symbol table *)
- (* indexed by tx *)
- stname : statyp; (* symbol table entry name *)
- stkind : stwtyp; (* symbol table entry kind *)
- stlev : stwtyp; (* symbol table entry level *)
- stadr : stwtyp; (* symbol table address *)
- stlen : stwtyp; (* symbol table length *)
- (* stname allways contains name, contents of stkind
- determines meaning of other arrays:
- stkind stlev stadr stlen
- ====== ===== ===== =====
- constant 0=declared const value --
- 1=scalar element
- prozedure lexical level label number parm len
- funktion " " "
- simpvar lexical level stack disp length
- arrayvar lexical level base stack disp type ptr
- simptype -- cardinality length
- tipe 0=array element length total length
-
- notes: type ptr is index of symbol table entry for
- declared type of array. this is a kludge to save
- symbol table space.
- *)
-
- (* global scanner result variables *)
- cclen : word; (* length of last character
- constant *)
- ch : word; (* last character read *)
- sym : symbol; (* last symbol read *)
- num : word; (* last number read *)
- id : alfa; (* last identifier read *)
-
- (* temp used in getsym *)
- aw : alatyp;
-
- (* global pointers *)
- tx : word; (* index of last st entry *)
- nl : word; (* last assigned label number *)
-
- errflag : word; (* error occured in last line *)
- listing : word; (* 13 if no listing wanted *)
-
- erestyp : exptyp; (* result type of expression *)
-
- (* global variables for procedure getsym for speed *)
- gsi, gsk, gsj : word;
-
- (* global variables for function position for speed *)
- posi : word;
-
- procedure error(n: word); (* parameter is error number *)
-
- begin
- errflag:=true;
- put#1('>','>',n#,7,'<','<')
- end;
-
- (* scan next token from input stream. set global variables
- based on result of scan.
- token scaned
- ============
- identifier sym=ident, id=<value of identifier>
- number sym=number, num=<value of number>
- character const sym=charcon, cclen=<length of constant>,
- ccon=<characters of constant>
- special symbol sym=<token for special symbol>
- resreved word sym=<token for reserved word>
- *)
-
- procedure getsym;
-
- (* see global variables for local var declaration *)
-
- procedure getch;
-
- begin
- get#0(ch);
- if listing<>13 then put#1(ch);
- if ch>=97 then ch:=ch-32;
- if ch<32 then begin (* this is for speed *)
- if ch=13 then begin
- (* get & ignore the line feed *)
- get#0(ch); if listing<>13 then
- put#1(ch);
- if errflag=true then begin
- errflag:=false;
- put#1('********',13,10);
- get#1(ch)
- end
- end;
- ch:=32
- end
- end; (* getch *)
-
- begin (* getsym *)
- while ch=' ' do getch;
- if (ch>='A') and (ch<='Z') then
- begin (* id or reserved word *)
- gsk:=0;
- repeat if gsk<al then
- begin
- aw[gsk]:=ch; gsk:=gsk+1
- end;
- getch
- until ((ch<'A')or(ch>'Z'))and((ch<'0')or(ch>'9'));
- (* blank remainder of aw *)
- while gsk<al do begin aw[gsk]:=' '; gsk:=gsk+1 end;
- (* pack aw word array into a alfa simple variable *)
- gsj:=0;
- for gsi:=0 to 3 do begin
- id[gsi]:=aw[gsj]+aw[gsj+1]*256;
- gsj:=gsj+2
- end;
- (* perform binary search for symbol in rword *)
- gsi:=1; gsj:=norw;
- repeat gsk:=(gsi+gsj)/2;
- if id<=rword[gsk] then gsj:=gsk-1;
- if id>=rword[gsk] then gsi:=gsk+1
- until gsi>gsj;
- if gsi-1>gsj then sym:=wsym[gsk] else sym:=ident
- end
- else if (ch>='0') and (ch<='9') then begin (* number *)
- num:=0; sym:=number;
- repeat num:=num*10+(ch-'0'); getch
- until (ch<'0') or (ch>'9')
- end
- else if ch='(' then begin
- getch;
- if ch='*' then begin (* inside of comment *)
- repeat
- repeat
- getch
- until ch='*';
- getch
- until ch=')';
- getch;
- getsym
- end
- else
- sym:=lparen
- end
- else if ch='''' then begin (* character constant *)
- sym:=charcon; gsk:=0;
- repeat
- repeat
- getch;
- ccon[gsk]:=ch; gsk:=gsk+1
- until ch='''';
- getch
- until ch<>'''';
- cclen:=gsk-1
- end
- else begin (* special symbol *)
- sym:=ssym[ch]; getch
- end
- end; (* getsym *)
-
- (* test for present symbol equal to first argument, error
- number of second argument is issued if not. also gets next
- symbol if desired symbol was present
- *)
- procedure test(s1, errn: word);
-
- begin
- if sym<>s1 then
- error(errn)
- else
- getsym
- end;
-
- (* emit the p-instruction passed in the arguments.
- *)
- procedure gen(op: pops; lev,adr: word);
-
- begin
- put#0(op, lev, adr, adr/256)
- end; (* gen *)
-
- (* enter an identifier into the symbol table with the
- attributes passed as arguments
- *)
- procedure enter(nam: alfa; kind,lev,adr,len: word);
-
- begin
- tx:=tx+1;
- if tx>symax then put#1('*SY OVER')
- else begin
- stname[tx]:=nam; stkind[tx]:=kind;
- stlev[tx]:=lev; stadr[tx]:=adr;
- stlen[tx]:=len
- end
- end; (* enter *)
-
- (* returns the symbol table index of the identifier in id.
- gives error 104 if not found and returns 0.
- *)
- function position;
-
- (* see global variables for local var declaration *)
-
- begin
- stname[0]:=id;
- posi:=tx;
- while stname[posi]<>id do posi:=posi-1;
- if posi=0 then error(104);
- position:=posi
- end; (* position *)
-
- (* returns the next available label number *)
- function nlab;
-
- begin
- nl:=nl+1; nlab:=nl
- end;
-
- (* semantic routine to compile a block *)
- procedure block(lev, plab: word);
-
- var (* values returned by typ *)
- ttype : object; (* type type (simple or not) *)
- tadr : word;
- tlen : word;
-
- dx : word; (* data allocation index *)
- px : word; (* parameter allocation index *)
- btype : object; (* block type (func or proc) *)
- tx0 : word; (* table index at start of block *)
- tx1 : word; (* table index at start of
- nested proc/func *)
- i : word; (* temp used in fwd ref *)
-
- (* emit the p-instruction passed in the first argument,
- taking the level and address from the symbol table
- entry passed in the second argument.
- *)
- procedure genlev(op: pops; i: word);
-
- var stl : word;
-
- begin
- stl:=stlev[i];
- if stl=1 (* only if global variable ref *)
- then gen(op,255,stadr[i])
- else gen(op,lev-stl,stadr[i])
- end; (* genlev *)
-
- function compcon; (* returned value is a compile time constant *)
-
- var i : word;
-
- begin
- case sym of
- number: begin compcon:=num; getsym end;
- charcon: begin compcon:=ccon[0]; getsym end;
- ident: begin
- i:=position;
- if stkind[i]<>constant then error(103);
- compcon:=stadr[i];
- getsym;
- while sym=plus do begin
- getsym;
- compcon:=stadr[i]+compcon
- end
- end (* case ident *)
- else error(50)
- end (* case sym of *)
- end; (* function compcon *)
-
- procedure constdcl;
-
- var ctx : word;
-
- begin
- test(ident,2);
- enter(id,constant,0,0,0);
- ctx:=tx;
- test(eql,16);
- stadr[ctx]:=compcon
- end; (* constdcl *)
-
- procedure typ;
-
- var scard : word; (* array subscript cardinality *)
-
- procedure styp;
-
- var i : word;
-
- begin
- ttype:=simptype;
- if sym=ident then begin
- i:=position;
- if (stkind[i]=simptype) or
- (stkind[i]=tipe) then begin
- ttype:=stkind[i];
- tadr:=stadr[i];
- tlen:=stlen[i];
- getsym
- end
- else if stkind[i]=constant then begin
- i:=compcon;
- test(period,20); test(period,20);
- tadr:=compcon-i+1; tlen:=intsize
- end
- else error(103)
- end
- else if sym=lparen then begin
- i:=0;
- repeat
- getsym;
- test(ident,2);
- enter(id,constant,intsize,i,0);
- i:=i+1
- until sym<>comma;
- tadr:=i; tlen:=intsize;
- test(rparen,4)
- end
- else begin
- i:=compcon;
- test(period,20);
- test(period,20);
- tadr:=compcon-i+1; tlen:=intsize
- end
- end; (* styp *)
-
- begin (* typ *)
- if sym<>arraysym then styp
- else begin
- getsym; test(lbrack,11);
- styp; scard:=tadr; (* save subscript cardinality *)
- test(rbrack,12);
- test(ofsym,8); styp;
- ttype:=tipe;
- tadr:=tlen; tlen:=tlen*scard
- end
- end; (* typ *)
-
- procedure typedcl;
-
- var tid : alfa; (* type identifer *)
-
- begin
- test(ident,2);
- tid:=id;
- test(eql,16);
- typ;
- enter(tid,ttype,lev,tadr,tlen)
- end; (* typdcl *)
-
- procedure vardcl;
-
- var i : word;
- tx0 : word;
- tlen : word; (* total length *)
- vkind : word; (* variable type *)
- len : word;
-
- begin
- test(ident,2);
- enter(id,notype,lev,0,0);
- tx0:=tx;
- while sym=comma do begin
- getsym;
- test(ident,2);
- enter(id,notype,lev,0,0)
- end;
- test(colon,5);
- test(ident,2);
- i:=position;
- tlen:=stlen[i]; (* total length of variable *)
- vkind:=stkind[i];
- if vkind=simptype then begin
- vkind:=simpvar;
- len:=tlen
- end
- else if vkind=tipe then begin
- vkind:=arrayvar;
- len:=i (* pointer to array type info *)
- end
- else error(103);
- for i:=tx0 to tx do begin
- stkind[i]:=vkind; stlen[i]:=len;
- if lev=1 then stadr[i]:=dx
- else stadr[i]:=dx+tlen;
- dx:=dx+tlen
- end
- end; (* vardcl *)
-
- procedure statement;
-
- var i, elab, flab, tlab, op, updn : word;
-
- procedure expression; forward;
-
- procedure call(i: word);
-
- var j : word;
-
- begin
- getsym;
- if sym=lparen then begin
- getsym;
- if sym<>varsym then begin
- expression(dontcare);
- while sym=comma do begin
- getsym;
- expression(dontcare)
- end
- end
- else (* procedure has var parameters *)
- repeat
- getsym; test(ident,2);
- j:=position;
- if stkind[j]=varparm
- then genlev(lod,j)
- else genlev(laa,j)
- until sym<>comma;
- test(rparen,4)
- end;
- gen(cal,lev-stlev[i],stadr[i]);
- gen(int,0,0-stlen[i])
- end; (* procedure call *)
-
- procedure expression(etyp: exptyp); backward;
-
- procedure chetyp(destyp: exptyp);
-
- begin
- if etyp=dontcare then
- etyp:=destyp
- else if etyp<>destyp then
- error(129)
- end; (* chetyp *)
-
- procedure sexp;
-
- var addop : symbol;
-
- procedure term;
-
- var mulop : symbol;
-
- procedure factor;
-
- var i : word;
- op : pops;
-
- begin (* factor *)
- case sym of
- number: begin (* load constant *)
- gen(lit,0,num);
- chetyp(wurd);
- getsym
- end; (* case number *)
- charcon: begin (* load string literal *)
- if cclen=1 then begin
- gen(lit,0,ccon[0]);
- chetyp(wurd) end
- else begin
- chetyp(alpha);
- gen(alit,0,0);
- gen(ccon[7],ccon[6],
- ccon[5]+ccon[4]*256);
- gen(ccon[3],ccon[2],
- ccon[1]+ccon[0]*256)
- end;
- getsym
- end; (* case charcon *)
- lparen: begin (* get sub expression *)
- getsym; expression(etyp);
- chetyp(erestyp);
- test(rparen,4)
- end; (* case lparen *)
- ident: begin
- i:=position;
- case stkind[i] of
- arrayvar: begin (* index into array var *)
- getsym;
- test(lbrack,11);
- expression(wurd);
- test(rbrack,12);
- case stadr[stlen[i]] of
- intsize: begin
- op:=lodx; chetyp(wurd) end;
- alfasize: begin
- op:=alodx; chetyp(alpha) end;
- charsize: begin
- op:=clodx; chetyp(wurd) end
- end; (* case *)
- genlev(op,i);
- end; (* case arrayvar *)
- constant: begin (* load constant *)
- gen(lit,0,stadr[i]);
- chetyp(wurd);
- getsym
- end; (* case constant *)
- varparm: begin (* load from var parameter *)
- getsym; genlev(lod,i);
- gen(lodi,0,0);
- chetyp(wurd)
- end; (* case varparm *)
- simpvar: begin (* load from simple var *)
- getsym;
- case stlen[i] of
- intsize: begin
- op:=lod; chetyp(wurd) end;
- alfasize:
- if sym=lbrack then begin
- getsym; expression(wurd);
- test(rbrack,12); op:=lodx;
- chetyp(wurd) end
- else begin
- op:=alod; chetyp(alpha)
- end;
- charsize: begin
- op:=clod; chetyp(wurd) end
- end; (* case stlen[i] *)
- genlev(op,i)
- end; (* case simpvar *)
- funktion: begin (* function reference *)
- gen(int,0,intsize);
- call(i);
- chetyp(wurd)
- end (* case funktion *)
- end (* case stkind[i] of *)
- end (* case ident *)
- else error(58)
- end (* case sym of *)
- end; (* factor *)
-
- begin (* term *)
- factor;
- while (sym=times) or (sym=slash) or
- (sym=andsym) do begin
- if sym=andsym then
- gen(pshf,0,0);
- mulop:=sym;
- getsym; factor;
- if mulop=times then gen(opr,0,4)
- else if mulop=slash then gen(opr,0,5)
- else gen(opr,0,15)
- end
- end; (* term *)
-
- begin (* sexp *)
- if (sym=plus) or (sym=minus) then begin
- addop:=sym; getsym; term;
- if addop=minus then gen(opr,0,1)
- end
- else term;
- while (sym=plus) or (sym=minus) or
- (sym=orsym) do begin
- if sym=orsym then
- gen(pshf,0,0);
- addop:=sym; getsym; term;
- if addop=plus then gen(opr,0,2)
- else if addop=minus then gen(opr,0,3)
- else gen(opr,0,14)
- end
- end; (* sexp *)
-
- begin (* expression *)
- sexp;
- if sym=lss then begin
- getsym;
- if sym=eql then begin
- getsym; sexp;
- gen(opr,etyp,13) end
- else if sym=gtr then begin
- getsym; sexp;
- gen(opr,etyp,9) end
- else begin
- sexp; gen(opr,etyp,10) end
- end
- else if sym=gtr then begin
- getsym;
- if sym=eql then begin
- getsym; sexp;
- gen(opr,etyp,11) end
- else begin
- sexp; gen(opr,etyp,12) end
- end
- else if sym=eql then begin
- getsym; sexp; gen(opr,etyp,8) end;
- erestyp:=etyp
- end; (* expression *)
-
- begin (* statement *)
- case sym of
- ident: begin (* could be anything *)
- i:=position;
- case stkind[i] of
- arrayvar: begin (* array assignment *)
- getsym; test(lbrack,11);
- expression(wurd);
- test(rbrack,12);
- test(colon,51); test(eql,51);
- expression(dontcare);
- case stadr[stlen[i]] of
- charsize: op:=cstox;
- intsize: op:=stox;
- alfasize: op:=astox
- end; (* case stadr[stlen[i]] of *)
- genlev(op,i)
- end; (* case arrayvar *)
- varparm: begin (* var parameter assignment *)
- getsym; genlev(lod,i);
- test(colon,51); test(eql,51);
- expression(dontcare);
- gen(stoi,0,0)
- end; (* case varparm *)
- simpvar: begin (* simple variable assignment *)
- getsym;
- if sym=lbrack then begin
- getsym; expression(dontcare);
- test(rbrack,12) end;
- test(colon,51); test(eql,51);
- expression(dontcare);
- if erestyp=wurd then
- case stlen[i] of
- alfasize: op:=stox;
- intsize: op:=sto;
- charsize: op:=csto
- end (* case stlen[i] of *)
- else op:=asto;
- genlev(op,i)
- end; (* case simpvar *)
- prozedure: begin (* procedure call *)
- call(i)
- end; (* case prozedure *)
- funktion: begin (* function return value *)
- getsym;
- test(colon,51); test(eql,51);
- expression(dontcare);
- gen(sto,0,0-stlen[i]-6)
- end (* case funktion *)
- else error(103)
- end (* case stkind[i] *)
- end; (* case ident *)
- ifsym: begin getsym; expression(dontcare);
- test(thensym,52);
- flab:=nlab; gen(jpc,0,flab);
- statement;
- if sym=elsesym then begin
- elab:=nlab; gen(jmp,0,elab);
- gen(lab,0,flab);
- getsym;
- statement;
- gen(lab,0,elab)
- end
- else gen(lab,0,flab)
- end; (* case ifsym *)
- forsym: begin getsym;
- test(ident,2); i:=position;
- test(colon,51); test(eql,51);
- expression(dontcare);
- genlev(sto,i);
- if sym=tosym then begin
- getsym; updn:=19; op:=11 end
- else if sym=downtosym then begin
- getsym; updn:=20; op:=13 end
- else error(55);
- expression(dontcare);
- test(dosym,54);
- tlab:=nlab; gen(lab,0,tlab);
- gen(opr,0,21);
- genlev(lod,i);
- gen(opr,0,op);
- elab:=nlab; gen(jpc,0,elab);
- statement;
- genlev(lod,i);
- gen(opr,0,updn);
- genlev(sto,i);
- gen(jmp,0,tlab);
- gen(lab,0,elab); gen(int,0,0-intsize)
- end; (* case forsym *)
- repeatsym: begin
- tlab:=nlab; gen(lab,0,tlab);
- repeat
- getsym; statement
- until sym<>semicolon;
- test(untilsym,53); expression(dontcare);
- gen(jpc,0,tlab)
- end; (* case repeatsym *)
- casesym: begin
- getsym; expression(dontcare);
- if sym<>ofsym then error(8);
- elab:=nlab; (* end label *)
- repeat
- getsym;
- gen(opr,0,21); (* dup *)
- gen(lit,0,compcon);
- test(colon,5);
- gen(opr,0,8); (* equal relop *)
- flab:=nlab; gen(jpc,0,flab);
- statement;
- gen(jmp,0,elab);
- gen(lab,0,flab)
- until (sym=elsesym) or (sym=endsym);
- if sym=elsesym then begin
- getsym;
- statement
- end;
- test(endsym,13);
- gen(lab,0,elab);
- gen(int,0,0-intsize)
- end; (* case casesym *)
- getsy: begin
- getsym; test(pound,99);
- i:=compcon;
- test(lparen,9); test(ident,2);
- gen(csp,i,0);
- i:=position;
- genlev(sto,i);
- test(rparen,4)
- end; (* case getsy *)
- putsym: begin
- getsym;
- test(pound,99);
- i:=compcon;
- if sym<>lparen then error(9);
- repeat
- getsym; expression(dontcare);
- if erestyp=wurd then op:=1
- else op:=8;
- if sym=pound then begin
- getsym; op:=3 end;
- gen(csp,i,op)
- until sym<>comma;
- test(rparen,4)
- end; (* case putsym *)
- beginsym: begin
- repeat
- getsym; statement
- until sym<>semicolon;
- test(endsym,13)
- end; (* case beginsym *)
- whilesym: begin
- getsym;
- tlab:=nlab; gen(lab,0,tlab);
- expression(dontcare);
- elab:=nlab;
- gen(jpc,0,elab);
- test(dosym,54);
- statement;
- gen(jmp,0,tlab); gen(lab,0,elab);
- end (* case whilesym *)
- end (* case *)
- end; (* statement *)
-
- (* scan a parameter list for a func or proc call and
- allocate variables for parameters
- *)
- procedure plist;
-
- var tx0, tx1, i, j : word;
- ptyp : object;
-
- begin
- tx0:=tx;
- repeat
- tx1:=tx;
- ptyp:=notype;
- repeat
- getsym;
- if sym=varsym then begin
- getsym; ptyp:=varparm
- end;
- test(ident,2);
- enter(id,notype,lev+1,0,0)
- until sym<>comma;
- test(colon,5);
- test(ident,2);
- i:=position;
- if ptyp=notype then
- if stkind[i]=simptype
- then ptyp:=simpvar
- else ptyp:=arrayvar;
- for j:=tx1+1 to tx do begin
- stkind[j]:=ptyp;
- stlen[j]:=stlen[i];
- stadr[j]:=px+stlen[i]-6;
- px:=px+stlen[i]
- end;
- until sym<>semicolon;
- for j:=tx0+1 to tx do
- stadr[j]:=stadr[j]-px;
- test(rparen,4)
- end; (* plist *)
-
- begin (* block *)
- dx:=0; tx0:=tx;
- if sym=constsym then begin
- getsym;
- repeat
- constdcl;
- test(semicolon,14)
- until sym<>ident
- end;
- if sym=typesym then begin
- getsym;
- repeat
- typedcl;
- test(semicolon,14)
- until sym<>ident
- end;
- if sym=varsym then begin
- getsym;
- repeat
- vardcl;
- test(semicolon,14)
- until sym<>ident
- end;
- while (sym=procsym) or (sym=funcsym) do begin
- if sym=procsym
- then btype:=prozedure
- else btype:=funktion;
- getsym;
- enter(id,btype,lev,nlab,0);
- test(ident,2);
- tx1:=tx; px:=0;
- if sym=lparen then plist;
- stlen[tx1]:=px; (* arg len into proc *)
- test(semicolon,14);
- if id='FORWARD '
- then getsym
- else
- if id='BACKWARD' then begin
- getsym;
- test(semicolon,14);
- i:=1; id:=stname[tx1];
- while id<>stname[i] do
- i:=i+1;
- stname[i]:='********';
- stadr[tx1]:=stadr[i];
- block(lev+1,stadr[i])
- end
- else
- block(lev+1,nl);
- tx:=tx1; (* leave only proc name in table *)
- test(semicolon,14)
- end;
- test(beginsym,17);
- gen(lab,0,plab);
- if lev<>1 then gen(int,0,dx);
- statement;
- while sym=semicolon do begin
- getsym;
- statement
- end;
- if lev<>1 then gen(opr,0,0);
- test(endsym,13);
- if sym=comma then begin
- getsym;
- for tx1:=1 to tx do
- put#1(13,10,tx1#, ' ',stname[tx1],
- ' ',stkind[tx1]#, ' ',stlev[tx1]#,
- ' ', stadr[tx1]#, ' ',stlen[tx1]#)
- end;
- tx:=tx0
- end; (* block *)
-
- begin (* main line *)
- (* init special symbol token array *)
- for ch:=ordminchar to ordmaxchar do ssym[ch]:=nul;
- ssym['+']:=plus; ssym['-']:=minus;
- ssym['*']:=times; ssym['/']:=slash;
- ssym[':']:=colon; ssym[';']:=semicolon;
- ssym['=']:=eql; ssym['#']:=pound;
- ssym['<']:=lss; ssym['>']:=gtr;
- ssym['(']:=lparen; ssym[')']:=rparen;
- ssym['[']:=lbrack; ssym[']']:=rbrack;
- ssym['.']:=period; ssym[',']:=comma;
-
- (* init reserved word arrays *)
- (* must be in alpahbetical order for binary search *)
- rword[ 1]:='AND '; wsym[ 1]:=andsym;
- rword[ 2]:='ARRAY '; wsym[ 2]:=arraysym;
- rword[ 3]:='BEGIN '; wsym[ 3]:=beginsym;
- rword[ 4]:='CASE '; wsym[ 4]:=casesym;
- rword[ 5]:='CONST '; wsym[ 5]:=constsym;
- rword[ 6]:='DIV '; wsym[ 6]:=divsym;
- rword[ 7]:='DO '; wsym[ 7]:=dosym;
- rword[ 8]:='DOWNTO '; wsym[ 8]:=downtosym;
- rword[ 9]:='ELSE '; wsym[ 9]:=elsesym;
- rword[10]:='END '; wsym[10]:=endsym;
- rword[11]:='FOR '; wsym[11]:=forsym;
- rword[12]:='FUNCTION'; wsym[12]:=funcsym;
- rword[13]:='GET '; wsym[13]:=getsy;
- rword[14]:='IF '; wsym[14]:=ifsym;
- rword[15]:='MOD '; wsym[15]:=modsym;
- rword[16]:='NOT '; wsym[16]:=notsym;
- rword[17]:='OF '; wsym[17]:=ofsym;
- rword[18]:='OR '; wsym[18]:=orsym;
- rword[19]:='PROCEDUR'; wsym[19]:=procsym;
- rword[20]:='PROGRAM '; wsym[20]:=progsym;
- rword[21]:='PUT '; wsym[21]:=putsym;
- rword[22]:='RECORD '; wsym[22]:=recordsym;
- rword[23]:='REPEAT '; wsym[23]:=repeatsym;
- rword[24]:='THEN '; wsym[24]:=thensym;
- rword[25]:='TO '; wsym[25]:=tosym;
- rword[26]:='TYPE '; wsym[26]:=typesym;
- rword[27]:='UNTIL '; wsym[27]:=untilsym;
- rword[28]:='VAR '; wsym[28]:=varsym;
- rword[29]:='WHILE '; wsym[29]:=whilesym;
-
- errflag:=false; (* clear line error flag *)
- tx:=0; (* init table pointers *)
- put#1('ppc rev ',vhu#,'.',vtn#,vun#,devrel,13,10);
- put#1('Listing?'); get#1(listing);
-
- (* define standard type identifiers *)
- enter('INTEGER ',simptype,0,0,intsize);
- enter('CHAR ',simptype,0,0,charsize);
- enter('BOOLEAN ',simptype,0,0,boolsize);
- enter('BYTE ',simptype,0,0,charsize);
- enter('WORD ',simptype,0,0,intsize);
- enter('ALFA ',simptype,0,0,alfasize);
- ch:=' '; (* init the character scanner *)
- getsym;
- nl:=1; gen(jmp,0,1);
- block(1,1);
- gen(csp,0,9);
- gen(peof,0,0);
- if sym<> period then error(20)
- end.
- eof
-
-