home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / beehive / program / pascal.arc / PASCAL1.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1990-07-16  |  25.8 KB  |  1,051 lines

  1. (*
  2.  
  3.   TITLE         Pascal Compiler (pascal self compiler)
  4.  
  5.   FILENAME      PASCAL1.PAS
  6.  
  7.   AUTHOR    Robert A. Van Valzah   9/01/79
  8.  
  9.   LAST REVISOR  Robert A. Van Valzah   1/05/80
  10.  
  11.   REASON        Repaired bug in Var parameters
  12.  
  13. *)
  14.  
  15. (*
  16. This is a single pass pascal subset compiler.  Source code
  17. is read from the input device and a listing is produced.
  18. A label addressed p-code is used so that forward references
  19. are no problem.  The use of theses labels removes the need for
  20. "backplugging", and with it, the need to keep the generated
  21. p-codes around in core.  This cuts down on memory requirements
  22. and allows the compiler to write the p-code to disk as it is
  23. generated.  The overall design uses recursive descent where
  24. ever possible.
  25.  
  26. internal structure
  27. ==================
  28. The compiler can be broken down into the major functional units
  29. shown in the table below.  In this compiler, code generation is
  30. rolled right in with the parsing routines.  As soon as a valid
  31. construct is recognized, code for it is emitted.
  32.  
  33. Block nesting and function is shown below.
  34.  
  35.     FUNCTION        ROUTINE NAME
  36.     ========        ============
  37.     error processing    error, test
  38.     symbol table routines    enter, position
  39.     token scanner        getsym
  40.       char scanner        getch, getline, etc.
  41.     semantic routines    block
  42.       declaritive        const, typ, var dcl
  43.       statement scanner    statement
  44.         expression scanner    epxression, sexp, term, factor
  45. main line
  46. *)
  47.  
  48. const
  49.     vhu    = 0;    (* version number hundreds *)
  50.     vtn    = 0;    (* tens *)
  51.     vun    = 8;    (* units *)
  52.     devrel    = 'r';    (* development or release version *)
  53.     norw    = 29;    (* number of reserved words *)
  54.     al    = 8;    (* length of identifiers *)
  55.     alm1    = 7;    (* length of id minus 1 *)
  56.     llen    = 80;    (* max input line length *)
  57.     symax    = 300;    (* max number of symbol table entrys *)
  58.     ordminchar = 0;    (* minimum legal char ord value *)
  59.     ordmaxchar = 127; (* maximum legal char ord value *)
  60.     intsize    = 2;    (* size of integer in stack units *)
  61.     charsize = 1;    (* size of character *)
  62.     boolsize = 2;    (* size of boolean *)
  63.     alfasize = 8;    (* size of alfa *)
  64.     true    = 1;    (* kludge until implemented in compiler *)
  65.     false    = 0;
  66.  
  67. type    symbol    = (    (* symbol tokens *)
  68.         nul, ident, number, charcon,
  69.         plus, minus, times,
  70.         slash, eql, lss, gtr, lparen, rparen,
  71.         comma, semicolon, period, lbrack, rbrack,
  72.         colon, pound,
  73.         andsym, arraysym,
  74.         beginsym, casesym, constsym,
  75.         divsym, dosym, downtosym, elsesym,
  76.         endsym, forsym, funcsym, getsy,
  77.         ifsym, modsym, notsym, ofsym,
  78.         orsym, procsym, progsym, putsym, recordsym,
  79.         repeatsym, thensym, tosym, typesym,
  80.         untilsym, varsym, whilesym
  81.         );
  82.     object    = ( (* types of symbol table entrys *)
  83.         notype, constant, prozedure, funktion,
  84.         simpvar, arrayvar, tipe, simptype, varparm
  85.         );
  86.     pops    = ( (* p-op codes *)
  87.         cal, jpc, jmp, lit, opr, lod, sto, int,
  88.         csp, lodx, stox, alit, alod, asto,
  89.         alodx, astox, pshf, clod, csto,
  90.         clodx, cstox, halt, lab,
  91.         peof, (* end of p-code file *)
  92.         laa, lodi, stoi, clodi, cstoi, alodi, astoi,
  93.         indx, aindx, cindx
  94.         );
  95.     exptyp    = ( (* possible expression types *)
  96.         wurd, alpha, chars, dontcare
  97.         );
  98.  
  99.     (* define all array types needed
  100.     this is a temporary kludge until the compiler
  101.     will accept arrays in var declarations
  102.     *)
  103.  
  104.     rwwtyp    = array[0..norw]   of word;
  105.     rwatyp    = array[0..norw]   of alfa;
  106.     alatyp    = array[0..alm1]    of word;
  107.     chatyp    = array[ordminchar..ordmaxchar] of word;
  108.     linetyp    = array[0..llen]   of word;
  109.     statyp    = array[0..symax]  of alfa;
  110.     stwtyp    = array[0..symax]  of word;
  111.     
  112. var
  113.     (* indexed by reserved word number *)
  114.     wsym    : rwwtyp;    (* gives token of type symbol *)
  115.     rword    : rwatyp;    (* holds reserved word in order *)
  116.  
  117.     (* indexed by ascii character value *)
  118.     ssym    : chatyp;    (* gives token of type sybol *)
  119.  
  120.     (* indexed by character number 0 .. *)
  121.     ccon    : linetyp;    (* last character constant read *)
  122.  
  123.     (* symbol table *)
  124.     (* indexed by tx *)
  125.     stname    : statyp;    (* symbol table entry name *)
  126.     stkind    : stwtyp;    (* symbol table entry kind *)
  127.     stlev    : stwtyp;    (* symbol table entry level *)
  128.     stadr    : stwtyp;    (* symbol table address *)
  129.     stlen    : stwtyp;    (* symbol table length *)
  130.     (* stname allways contains name, contents of stkind
  131.       determines meaning of other arrays:
  132.       stkind    stlev        stadr        stlen
  133.       ======    =====        =====        =====
  134.       constant    0=declared    const value    --
  135.             1=scalar element
  136.       prozedure    lexical level    label number    parm len
  137.       funktion    "        "        "
  138.       simpvar    lexical level    stack disp    length
  139.       arrayvar    lexical level    base stack disp    type ptr
  140.       simptype    --        cardinality    length
  141.       tipe        0=array        element length    total length
  142.  
  143.       notes:  type ptr is index of symbol table entry for
  144.       declared type of array.  this is a kludge to save
  145.       symbol table space.
  146.     *)
  147.  
  148.     (* global scanner result variables *)
  149.     cclen    : word;        (* length of last character
  150.                    constant *)
  151.     ch    : word;        (* last character read *)
  152.     sym    : symbol;    (* last symbol read *)
  153.     num    : word;        (* last number read *)
  154.     id    : alfa;        (* last identifier read *)
  155.  
  156.     (* temp used in getsym *)
  157.     aw    : alatyp;
  158.  
  159.     (* global pointers *)
  160.     tx    : word;        (* index of last st entry *)
  161.     nl    : word;        (* last assigned label number *)
  162.  
  163.     errflag    : word;        (* error occured in last line *)
  164.     listing    : word;        (* 13 if no listing wanted *)
  165.  
  166.     erestyp    : exptyp;    (* result type of expression *)
  167.  
  168.     (* global variables for procedure getsym for speed *)
  169.     gsi, gsk, gsj    : word;
  170.  
  171.     (* global variables for function position for speed *)
  172.     posi    : word;
  173.  
  174. procedure error(n: word); (* parameter is error number *)
  175.  
  176.     begin
  177.     errflag:=true;
  178.     put#1('>','>',n#,7,'<','<')
  179.     end;
  180.  
  181. (* scan next token from input stream.  set global variables
  182. based on result of scan.
  183. token scaned
  184. ============
  185. identifier    sym=ident, id=<value of identifier>
  186. number        sym=number, num=<value of number>
  187. character const    sym=charcon, cclen=<length of constant>,
  188.         ccon=<characters of constant>
  189. special symbol    sym=<token for special symbol>
  190. resreved word    sym=<token for reserved word>
  191. *)
  192.  
  193. procedure getsym;
  194.     
  195.     (* see global variables for local var declaration *)
  196.  
  197.     procedure getch;
  198.     
  199.         begin
  200.         get#0(ch);
  201.         if listing<>13 then put#1(ch);
  202.         if ch>=97 then ch:=ch-32;
  203.         if ch<32 then begin (* this is for speed *)
  204.             if ch=13 then begin
  205.                 (* get & ignore the line feed *)
  206.                 get#0(ch); if listing<>13 then
  207.                   put#1(ch);
  208.                 if errflag=true then begin
  209.                   errflag:=false;
  210.                   put#1('********',13,10);
  211.                   get#1(ch)
  212.                   end
  213.                 end;
  214.             ch:=32
  215.             end
  216.         end; (* getch *)
  217.     
  218.     begin (* getsym *)
  219.     while ch=' ' do getch;
  220.     if (ch>='A') and (ch<='Z') then
  221.         begin (* id or reserved word *)
  222.         gsk:=0;
  223.         repeat    if gsk<al then
  224.                 begin
  225.                 aw[gsk]:=ch; gsk:=gsk+1
  226.                 end;
  227.             getch
  228.         until ((ch<'A')or(ch>'Z'))and((ch<'0')or(ch>'9'));
  229.         (* blank remainder of aw *)
  230.         while gsk<al do begin aw[gsk]:=' '; gsk:=gsk+1 end;
  231.         (* pack aw word array into a alfa simple variable *)
  232.         gsj:=0;
  233.         for gsi:=0 to 3 do begin
  234.             id[gsi]:=aw[gsj]+aw[gsj+1]*256;
  235.             gsj:=gsj+2
  236.             end;
  237.         (* perform binary search for symbol in rword *)
  238.         gsi:=1; gsj:=norw;
  239.         repeat    gsk:=(gsi+gsj)/2;
  240.             if id<=rword[gsk] then gsj:=gsk-1;
  241.             if id>=rword[gsk] then gsi:=gsk+1
  242.         until gsi>gsj;
  243.         if gsi-1>gsj then sym:=wsym[gsk] else sym:=ident
  244.         end
  245.     else if (ch>='0') and (ch<='9') then begin (* number *)
  246.         num:=0; sym:=number;
  247.         repeat num:=num*10+(ch-'0'); getch
  248.         until (ch<'0') or (ch>'9')
  249.         end
  250.     else if ch='(' then begin
  251.         getch;
  252.         if ch='*' then begin (* inside of comment *)
  253.             repeat
  254.                 repeat
  255.                     getch
  256.                 until ch='*';
  257.                 getch
  258.             until ch=')';
  259.             getch;
  260.             getsym
  261.             end
  262.         else
  263.             sym:=lparen
  264.         end
  265.     else if ch='''' then begin (* character constant *)
  266.         sym:=charcon; gsk:=0;
  267.         repeat
  268.             repeat
  269.                 getch;
  270.                 ccon[gsk]:=ch; gsk:=gsk+1
  271.             until ch='''';
  272.             getch
  273.         until ch<>'''';
  274.         cclen:=gsk-1
  275.         end
  276.     else begin (* special symbol *)
  277.         sym:=ssym[ch]; getch
  278.         end
  279. end; (* getsym *)
  280.  
  281. (* test for present symbol equal to first argument, error
  282. number of second argument is issued if not.  also gets next
  283. symbol if desired symbol was present
  284. *)
  285. procedure test(s1, errn: word);
  286.  
  287.     begin
  288.     if sym<>s1 then
  289.         error(errn)
  290.     else
  291.         getsym
  292.     end;
  293.  
  294. (* emit the p-instruction passed in the arguments.
  295. *)
  296. procedure gen(op: pops; lev,adr: word);
  297.  
  298.     begin
  299.     put#0(op, lev, adr, adr/256)
  300.     end; (* gen *)
  301.  
  302. (* enter an identifier into the symbol table with the
  303. attributes passed as arguments
  304. *)
  305. procedure enter(nam: alfa; kind,lev,adr,len: word);
  306.  
  307.     begin
  308.     tx:=tx+1;
  309.     if tx>symax then put#1('*SY OVER')
  310.     else begin
  311.         stname[tx]:=nam; stkind[tx]:=kind;
  312.         stlev[tx]:=lev; stadr[tx]:=adr;
  313.         stlen[tx]:=len
  314.         end
  315.     end; (* enter *)
  316.  
  317. (* returns the symbol table index of the identifier in id.
  318. gives error 104 if not found and returns 0.
  319. *)
  320. function position;
  321.     
  322.     (* see global variables for local var declaration *)
  323.  
  324.     begin
  325.     stname[0]:=id;
  326.     posi:=tx;
  327.     while stname[posi]<>id do posi:=posi-1;
  328.     if posi=0 then error(104);
  329.     position:=posi
  330.     end; (* position *)
  331.  
  332. (* returns the next available label number *)
  333. function nlab;
  334.  
  335.     begin
  336.     nl:=nl+1; nlab:=nl
  337.     end;
  338.  
  339. (* semantic routine to compile a block *)
  340. procedure block(lev, plab: word);
  341.  
  342.     var    (* values returned by typ *)
  343.         ttype    : object; (* type type (simple or not) *)
  344.         tadr    : word;
  345.         tlen    : word;
  346.  
  347.         dx    : word; (* data allocation index *)
  348.         px    : word; (* parameter allocation index *)
  349.         btype    : object; (* block type (func or proc) *)
  350.         tx0    : word;    (* table index at start of block *)
  351.         tx1    : word;    (* table index at start of
  352.                 nested proc/func *)
  353.         i    : word;    (* temp used in fwd ref *)
  354.  
  355.     (* emit the p-instruction passed in the first argument,
  356.     taking the level and address from the symbol table
  357.     entry passed in the second argument.
  358.     *)
  359.     procedure genlev(op: pops; i: word);
  360.  
  361.         var    stl    : word;
  362.  
  363.         begin
  364.         stl:=stlev[i];
  365.         if stl=1 (* only if global variable ref *)
  366.             then gen(op,255,stadr[i])
  367.             else gen(op,lev-stl,stadr[i])
  368.         end; (* genlev *)
  369.  
  370.     function compcon; (* returned value is a compile time constant *)
  371.  
  372.         var     i    : word;
  373.  
  374.         begin
  375.         case sym of
  376.         number:    begin compcon:=num; getsym end;
  377.         charcon: begin compcon:=ccon[0]; getsym end;
  378.         ident:    begin
  379.             i:=position;
  380.             if stkind[i]<>constant then error(103);
  381.             compcon:=stadr[i];
  382.             getsym;
  383.             while sym=plus do begin
  384.                 getsym;
  385.                 compcon:=stadr[i]+compcon
  386.                 end
  387.             end (* case ident *)
  388.         else    error(50)
  389.         end (* case sym of *)
  390.         end; (* function compcon *)
  391.  
  392.     procedure constdcl;
  393.  
  394.         var    ctx    : word;
  395.  
  396.         begin
  397.         test(ident,2);
  398.         enter(id,constant,0,0,0);
  399.         ctx:=tx;
  400.         test(eql,16);
  401.         stadr[ctx]:=compcon
  402.         end; (* constdcl *)
  403.  
  404.     procedure typ;
  405.  
  406.         var    scard    : word; (* array subscript cardinality *)
  407.  
  408.         procedure styp;
  409.  
  410.             var    i    : word;
  411.  
  412.             begin
  413.             ttype:=simptype;
  414.             if sym=ident then begin
  415.                 i:=position;
  416.                 if (stkind[i]=simptype) or
  417.                    (stkind[i]=tipe) then begin
  418.                   ttype:=stkind[i];
  419.                   tadr:=stadr[i];
  420.                   tlen:=stlen[i];
  421.                   getsym
  422.                   end
  423.                 else if stkind[i]=constant then begin
  424.                   i:=compcon;
  425.                   test(period,20); test(period,20);
  426.                   tadr:=compcon-i+1; tlen:=intsize
  427.                   end
  428.                 else error(103)
  429.                 end
  430.             else if sym=lparen then begin
  431.                 i:=0;
  432.                 repeat
  433.                   getsym;
  434.                   test(ident,2);
  435.                   enter(id,constant,intsize,i,0);
  436.                   i:=i+1
  437.                 until sym<>comma;
  438.                 tadr:=i; tlen:=intsize;
  439.                 test(rparen,4)
  440.                 end
  441.             else begin
  442.                 i:=compcon;
  443.                 test(period,20);
  444.                 test(period,20);
  445.                 tadr:=compcon-i+1; tlen:=intsize
  446.                 end
  447.             end; (* styp *)
  448.  
  449.         begin (* typ *)
  450.         if sym<>arraysym then styp
  451.         else begin
  452.             getsym; test(lbrack,11);
  453.             styp; scard:=tadr; (* save subscript cardinality *)
  454.             test(rbrack,12);
  455.             test(ofsym,8); styp;
  456.             ttype:=tipe;
  457.             tadr:=tlen; tlen:=tlen*scard
  458.             end
  459.         end; (* typ *)
  460.  
  461.     procedure typedcl;
  462.  
  463.         var    tid    : alfa; (* type identifer *)
  464.  
  465.         begin
  466.         test(ident,2);
  467.         tid:=id;
  468.         test(eql,16);
  469.         typ;
  470.         enter(tid,ttype,lev,tadr,tlen)
  471.         end; (* typdcl *)
  472.  
  473.     procedure vardcl;
  474.  
  475.         var    i    : word;
  476.             tx0    : word;
  477.             tlen    : word; (* total length *)
  478.             vkind    : word; (* variable type *)
  479.             len    : word;
  480.  
  481.         begin
  482.         test(ident,2);
  483.         enter(id,notype,lev,0,0);
  484.         tx0:=tx;
  485.         while sym=comma do begin
  486.             getsym;
  487.             test(ident,2);
  488.             enter(id,notype,lev,0,0)
  489.             end;
  490.         test(colon,5);
  491.         test(ident,2);
  492.         i:=position;
  493.         tlen:=stlen[i]; (* total length of variable *)
  494.         vkind:=stkind[i];
  495.         if vkind=simptype then begin
  496.             vkind:=simpvar;
  497.             len:=tlen
  498.             end
  499.         else if vkind=tipe then begin
  500.             vkind:=arrayvar;
  501.             len:=i (* pointer to array type info *)
  502.             end
  503.         else error(103);
  504.         for i:=tx0 to tx do begin
  505.             stkind[i]:=vkind; stlen[i]:=len;
  506.             if lev=1 then stadr[i]:=dx
  507.             else    stadr[i]:=dx+tlen;
  508.             dx:=dx+tlen
  509.             end
  510.         end; (* vardcl *)
  511.  
  512.     procedure statement;
  513.  
  514.         var    i, elab, flab, tlab, op, updn    : word;
  515.  
  516.         procedure expression; forward;
  517.  
  518.         procedure call(i: word);
  519.  
  520.         var    j    : word;
  521.  
  522.         begin
  523.         getsym;
  524.         if sym=lparen then begin
  525.             getsym;
  526.             if sym<>varsym then begin
  527.                 expression(dontcare);
  528.                 while sym=comma do begin
  529.                   getsym;
  530.                   expression(dontcare)
  531.                   end
  532.                 end
  533.             else (* procedure has var parameters *)
  534.                 repeat
  535.                   getsym; test(ident,2);
  536.                   j:=position;
  537.                   if stkind[j]=varparm
  538.                     then genlev(lod,j)
  539.                     else genlev(laa,j)
  540.                 until sym<>comma;
  541.             test(rparen,4)
  542.             end;
  543.         gen(cal,lev-stlev[i],stadr[i]);
  544.         gen(int,0,0-stlen[i])
  545.         end; (* procedure call *)
  546.  
  547.         procedure expression(etyp: exptyp); backward;
  548.  
  549.         procedure chetyp(destyp: exptyp);
  550.  
  551.             begin
  552.             if etyp=dontcare then
  553.                 etyp:=destyp
  554.             else if etyp<>destyp then
  555.                 error(129)
  556.             end; (* chetyp *)
  557.  
  558.         procedure sexp;
  559.  
  560.         var    addop    : symbol;
  561.  
  562.         procedure term;
  563.  
  564.         var    mulop    : symbol;
  565.  
  566.         procedure factor;
  567.  
  568.             var    i    : word;
  569.                 op    : pops;
  570.  
  571.             begin (* factor *)
  572.             case sym of
  573.             number:    begin (* load constant *)
  574.                 gen(lit,0,num);
  575.                 chetyp(wurd);
  576.                 getsym
  577.                 end; (* case number *)
  578.             charcon: begin (* load string literal *)
  579.                 if cclen=1 then begin
  580.                     gen(lit,0,ccon[0]);
  581.                     chetyp(wurd) end
  582.                 else begin
  583.                     chetyp(alpha);
  584.                     gen(alit,0,0);
  585.                     gen(ccon[7],ccon[6],
  586.                      ccon[5]+ccon[4]*256);
  587.                     gen(ccon[3],ccon[2],
  588.                      ccon[1]+ccon[0]*256)
  589.                     end;
  590.                 getsym
  591.                 end; (* case charcon *)
  592.             lparen:    begin (* get sub expression *)
  593.                 getsym; expression(etyp);
  594.                 chetyp(erestyp);
  595.                 test(rparen,4)
  596.                 end; (* case lparen *)
  597.             ident:    begin
  598.                 i:=position;
  599.                 case stkind[i] of
  600.                 arrayvar: begin (* index into array var *)
  601.                   getsym;
  602.                   test(lbrack,11);
  603.                   expression(wurd);
  604.                   test(rbrack,12);
  605.                   case stadr[stlen[i]] of
  606.                   intsize: begin
  607.                     op:=lodx; chetyp(wurd) end;
  608.                   alfasize: begin
  609.                     op:=alodx; chetyp(alpha) end;
  610.                   charsize: begin
  611.                     op:=clodx; chetyp(wurd) end
  612.                   end; (* case *)
  613.                   genlev(op,i);
  614.                   end; (* case arrayvar *)
  615.                 constant: begin (* load constant *)
  616.                   gen(lit,0,stadr[i]);
  617.                   chetyp(wurd);
  618.                   getsym
  619.                   end; (* case constant *)
  620.                 varparm: begin (* load from var parameter *)
  621.                   getsym; genlev(lod,i);
  622.                   gen(lodi,0,0);
  623.                   chetyp(wurd)
  624.                   end; (* case varparm *)
  625.                 simpvar: begin (* load from simple var *)
  626.                   getsym;
  627.                   case stlen[i] of
  628.                   intsize:  begin
  629.                     op:=lod; chetyp(wurd) end;
  630.                   alfasize: 
  631.                     if sym=lbrack then begin
  632.                       getsym; expression(wurd);
  633.                       test(rbrack,12); op:=lodx;
  634.                       chetyp(wurd) end
  635.                     else begin
  636.                       op:=alod; chetyp(alpha)
  637.                       end;
  638.                   charsize: begin
  639.                     op:=clod; chetyp(wurd) end
  640.                   end; (* case stlen[i] *)
  641.                   genlev(op,i)
  642.                   end; (* case simpvar *)
  643.                 funktion: begin (* function reference *)
  644.                     gen(int,0,intsize);
  645.                     call(i);
  646.                     chetyp(wurd)
  647.                   end (* case funktion *)
  648.                 end (* case stkind[i] of *)
  649.                 end (* case ident *)
  650.             else    error(58)
  651.             end (* case sym of *)
  652.             end; (* factor *)
  653.  
  654.             begin (* term *)
  655.             factor;
  656.             while (sym=times) or (sym=slash) or
  657.                 (sym=andsym) do begin
  658.                 if sym=andsym then
  659.                     gen(pshf,0,0);
  660.                 mulop:=sym;
  661.                 getsym; factor;
  662.                 if mulop=times then gen(opr,0,4)
  663.                 else if mulop=slash then gen(opr,0,5)
  664.                 else gen(opr,0,15)
  665.                 end
  666.             end; (* term *)
  667.  
  668.             begin (* sexp *)
  669.             if (sym=plus) or (sym=minus) then begin
  670.                 addop:=sym; getsym; term;
  671.                 if addop=minus then gen(opr,0,1)
  672.                 end
  673.             else term;
  674.             while (sym=plus) or (sym=minus) or
  675.                 (sym=orsym) do begin
  676.                 if sym=orsym then
  677.                     gen(pshf,0,0);
  678.                 addop:=sym; getsym; term;
  679.                 if addop=plus then gen(opr,0,2)
  680.                 else if addop=minus then gen(opr,0,3)
  681.                 else gen(opr,0,14)
  682.                 end
  683.             end; (* sexp *)
  684.  
  685.             begin (* expression *)
  686.             sexp;
  687.             if sym=lss then begin
  688.                 getsym;
  689.                 if sym=eql then begin
  690.                     getsym; sexp;
  691.                     gen(opr,etyp,13) end
  692.                 else if sym=gtr then begin
  693.                     getsym; sexp;
  694.                     gen(opr,etyp,9) end
  695.                 else begin
  696.                     sexp; gen(opr,etyp,10) end
  697.                 end
  698.             else if sym=gtr then begin
  699.                 getsym;
  700.                 if sym=eql then begin
  701.                     getsym; sexp;
  702.                     gen(opr,etyp,11) end
  703.                 else begin
  704.                     sexp; gen(opr,etyp,12) end
  705.                 end
  706.             else if sym=eql then begin
  707.                 getsym; sexp; gen(opr,etyp,8) end;
  708.             erestyp:=etyp
  709.             end; (* expression *)
  710.  
  711.         begin (* statement *)
  712.         case sym of
  713.         ident:    begin (* could be anything *)
  714.             i:=position;
  715.             case stkind[i] of
  716.             arrayvar: begin (* array assignment *)
  717.                 getsym; test(lbrack,11);
  718.                 expression(wurd);
  719.                 test(rbrack,12);
  720.                 test(colon,51); test(eql,51);
  721.                 expression(dontcare);
  722.                 case stadr[stlen[i]] of
  723.                 charsize: op:=cstox;
  724.                 intsize:  op:=stox;
  725.                 alfasize: op:=astox
  726.                 end; (* case stadr[stlen[i]] of *)
  727.                 genlev(op,i)
  728.                 end; (* case arrayvar *)
  729.             varparm: begin (* var parameter assignment *)
  730.                 getsym; genlev(lod,i);
  731.                 test(colon,51); test(eql,51);
  732.                 expression(dontcare);
  733.                 gen(stoi,0,0)
  734.                 end; (* case varparm *)
  735.             simpvar: begin (* simple variable assignment *)
  736.                 getsym;
  737.                 if sym=lbrack then begin
  738.                   getsym; expression(dontcare);
  739.                   test(rbrack,12) end;
  740.                 test(colon,51); test(eql,51);
  741.                 expression(dontcare);
  742.                 if erestyp=wurd then
  743.                   case stlen[i] of
  744.                   alfasize: op:=stox;
  745.                   intsize:  op:=sto;
  746.                   charsize: op:=csto
  747.                   end (* case stlen[i] of *)
  748.                 else op:=asto;
  749.                 genlev(op,i)
  750.                 end; (* case simpvar *)
  751.             prozedure: begin (* procedure call *)
  752.                 call(i)
  753.                 end; (* case prozedure *)
  754.             funktion: begin (* function return value *)
  755.                 getsym;
  756.                 test(colon,51); test(eql,51);
  757.                 expression(dontcare);
  758.                 gen(sto,0,0-stlen[i]-6)
  759.                 end (* case funktion *)
  760.             else error(103)
  761.             end (* case stkind[i] *)
  762.             end; (* case ident *)
  763.         ifsym:    begin getsym; expression(dontcare);
  764.             test(thensym,52);
  765.             flab:=nlab; gen(jpc,0,flab);
  766.             statement;
  767.             if sym=elsesym then begin
  768.                 elab:=nlab; gen(jmp,0,elab);
  769.                 gen(lab,0,flab);
  770.                 getsym;
  771.                 statement;
  772.                 gen(lab,0,elab)
  773.                 end
  774.             else gen(lab,0,flab)
  775.             end; (* case ifsym *)
  776.         forsym:    begin getsym;
  777.             test(ident,2); i:=position;
  778.             test(colon,51); test(eql,51);
  779.             expression(dontcare);
  780.             genlev(sto,i);
  781.             if sym=tosym then begin
  782.                 getsym; updn:=19; op:=11 end
  783.             else if sym=downtosym then begin
  784.                 getsym; updn:=20; op:=13 end
  785.             else error(55);
  786.             expression(dontcare);
  787.             test(dosym,54);
  788.             tlab:=nlab; gen(lab,0,tlab);
  789.             gen(opr,0,21);
  790.             genlev(lod,i);
  791.             gen(opr,0,op);
  792.             elab:=nlab; gen(jpc,0,elab);
  793.             statement;
  794.             genlev(lod,i);
  795.             gen(opr,0,updn);
  796.             genlev(sto,i);
  797.             gen(jmp,0,tlab);
  798.             gen(lab,0,elab); gen(int,0,0-intsize)
  799.             end; (* case forsym *)
  800.         repeatsym: begin
  801.             tlab:=nlab; gen(lab,0,tlab);
  802.             repeat
  803.                 getsym; statement
  804.             until sym<>semicolon;
  805.             test(untilsym,53); expression(dontcare);
  806.             gen(jpc,0,tlab)
  807.             end; (* case repeatsym *)
  808.         casesym: begin
  809.             getsym; expression(dontcare);
  810.             if sym<>ofsym then error(8);
  811.             elab:=nlab; (* end label *)
  812.             repeat
  813.                 getsym;
  814.                 gen(opr,0,21); (* dup *)
  815.                 gen(lit,0,compcon);
  816.                 test(colon,5);
  817.                 gen(opr,0,8); (* equal relop *)
  818.                 flab:=nlab; gen(jpc,0,flab);
  819.                 statement;
  820.                 gen(jmp,0,elab);
  821.                 gen(lab,0,flab)
  822.             until (sym=elsesym) or (sym=endsym);
  823.             if sym=elsesym then begin
  824.                 getsym;
  825.                 statement
  826.                 end;
  827.             test(endsym,13);
  828.             gen(lab,0,elab);
  829.             gen(int,0,0-intsize)
  830.             end; (* case casesym *)
  831.         getsy:    begin
  832.             getsym; test(pound,99);
  833.             i:=compcon;
  834.             test(lparen,9); test(ident,2);
  835.             gen(csp,i,0);
  836.             i:=position;
  837.             genlev(sto,i);
  838.             test(rparen,4)
  839.             end; (* case getsy *)
  840.         putsym:    begin
  841.             getsym;
  842.             test(pound,99);
  843.             i:=compcon;
  844.             if sym<>lparen then error(9);
  845.             repeat
  846.                 getsym; expression(dontcare);
  847.                 if erestyp=wurd then op:=1
  848.                 else op:=8;
  849.                 if sym=pound then begin
  850.                     getsym; op:=3 end;
  851.                 gen(csp,i,op)
  852.             until sym<>comma;
  853.             test(rparen,4)
  854.             end; (* case putsym *)
  855.         beginsym: begin
  856.             repeat
  857.                 getsym; statement
  858.             until sym<>semicolon;
  859.             test(endsym,13)
  860.             end; (* case beginsym *)
  861.         whilesym: begin
  862.             getsym;
  863.             tlab:=nlab; gen(lab,0,tlab);
  864.             expression(dontcare);
  865.             elab:=nlab;
  866.             gen(jpc,0,elab);
  867.             test(dosym,54);
  868.             statement;
  869.             gen(jmp,0,tlab); gen(lab,0,elab);
  870.             end (* case whilesym *)
  871.         end (* case *)
  872.         end; (* statement *)
  873.  
  874.     (* scan a parameter list for a func or proc call and
  875.     allocate variables for parameters
  876.     *)
  877.     procedure plist;
  878.  
  879.         var    tx0, tx1, i, j    : word;
  880.             ptyp        : object;
  881.  
  882.         begin
  883.         tx0:=tx;
  884.         repeat
  885.             tx1:=tx;
  886.             ptyp:=notype;
  887.             repeat
  888.                 getsym;
  889.                 if sym=varsym then begin
  890.                     getsym; ptyp:=varparm
  891.                     end;
  892.                 test(ident,2);
  893.                 enter(id,notype,lev+1,0,0)
  894.             until sym<>comma;
  895.             test(colon,5);
  896.             test(ident,2);
  897.             i:=position;
  898.             if ptyp=notype then
  899.                 if stkind[i]=simptype
  900.                     then ptyp:=simpvar
  901.                     else ptyp:=arrayvar;
  902.             for j:=tx1+1 to tx do begin
  903.                 stkind[j]:=ptyp;
  904.                 stlen[j]:=stlen[i];
  905.                 stadr[j]:=px+stlen[i]-6;
  906.                 px:=px+stlen[i]
  907.                 end;
  908.         until sym<>semicolon;
  909.         for j:=tx0+1 to tx do
  910.             stadr[j]:=stadr[j]-px;
  911.         test(rparen,4)
  912.         end; (* plist *)
  913.  
  914.     begin (* block *)
  915.     dx:=0; tx0:=tx;
  916.     if sym=constsym then begin
  917.         getsym;
  918.         repeat
  919.             constdcl;
  920.             test(semicolon,14)
  921.         until sym<>ident
  922.         end;
  923.     if sym=typesym then begin
  924.         getsym;
  925.         repeat
  926.             typedcl;
  927.             test(semicolon,14)
  928.         until sym<>ident
  929.         end;
  930.     if sym=varsym then begin
  931.         getsym;
  932.         repeat
  933.             vardcl;
  934.             test(semicolon,14)
  935.         until sym<>ident
  936.         end;
  937.     while (sym=procsym) or (sym=funcsym) do begin
  938.         if sym=procsym
  939.             then btype:=prozedure
  940.             else btype:=funktion;
  941.         getsym;
  942.         enter(id,btype,lev,nlab,0);
  943.         test(ident,2);
  944.         tx1:=tx; px:=0;
  945.         if sym=lparen then plist;
  946.         stlen[tx1]:=px; (* arg len into proc *)
  947.         test(semicolon,14);
  948.         if id='FORWARD '
  949.         then getsym
  950.         else
  951.             if id='BACKWARD' then begin
  952.                 getsym;
  953.                 test(semicolon,14);
  954.                 i:=1; id:=stname[tx1];
  955.                 while id<>stname[i] do
  956.                     i:=i+1;
  957.                 stname[i]:='********';
  958.                 stadr[tx1]:=stadr[i];
  959.                 block(lev+1,stadr[i])
  960.                 end
  961.             else
  962.                 block(lev+1,nl);
  963.         tx:=tx1; (* leave only proc name in table *)
  964.         test(semicolon,14)
  965.         end;
  966.     test(beginsym,17);
  967.     gen(lab,0,plab);
  968.     if lev<>1 then gen(int,0,dx);
  969.     statement;
  970.     while sym=semicolon do begin
  971.         getsym;
  972.         statement
  973.         end;
  974.     if lev<>1 then gen(opr,0,0);
  975.     test(endsym,13);
  976.     if sym=comma then begin
  977.         getsym;
  978.         for tx1:=1 to tx do
  979.             put#1(13,10,tx1#, ' ',stname[tx1],
  980.             ' ',stkind[tx1]#, ' ',stlev[tx1]#,
  981.             ' ', stadr[tx1]#, ' ',stlen[tx1]#)
  982.         end;
  983.     tx:=tx0
  984.     end; (* block *)
  985.  
  986.     begin (* main line *)
  987.     (* init special symbol token array *)
  988.     for ch:=ordminchar to ordmaxchar do ssym[ch]:=nul;
  989.     ssym['+']:=plus;    ssym['-']:=minus;
  990.     ssym['*']:=times;    ssym['/']:=slash;
  991.     ssym[':']:=colon;    ssym[';']:=semicolon;
  992.     ssym['=']:=eql;        ssym['#']:=pound;
  993.     ssym['<']:=lss;        ssym['>']:=gtr;
  994.     ssym['(']:=lparen;    ssym[')']:=rparen;
  995.     ssym['[']:=lbrack;    ssym[']']:=rbrack;
  996.     ssym['.']:=period;    ssym[',']:=comma;
  997.  
  998.     (* init reserved word arrays *)
  999.     (* must be in alpahbetical order for binary search *)
  1000.     rword[ 1]:='AND     ';    wsym[ 1]:=andsym;
  1001.     rword[ 2]:='ARRAY   ';    wsym[ 2]:=arraysym;
  1002.     rword[ 3]:='BEGIN   ';    wsym[ 3]:=beginsym;
  1003.     rword[ 4]:='CASE    ';    wsym[ 4]:=casesym;
  1004.     rword[ 5]:='CONST   ';    wsym[ 5]:=constsym;
  1005.     rword[ 6]:='DIV     ';    wsym[ 6]:=divsym;
  1006.     rword[ 7]:='DO      ';    wsym[ 7]:=dosym;
  1007.     rword[ 8]:='DOWNTO  ';    wsym[ 8]:=downtosym;
  1008.     rword[ 9]:='ELSE    ';    wsym[ 9]:=elsesym;
  1009.     rword[10]:='END     ';    wsym[10]:=endsym;
  1010.     rword[11]:='FOR     ';    wsym[11]:=forsym;
  1011.     rword[12]:='FUNCTION';    wsym[12]:=funcsym;
  1012.     rword[13]:='GET     ';    wsym[13]:=getsy;
  1013.     rword[14]:='IF      ';    wsym[14]:=ifsym;
  1014.     rword[15]:='MOD     ';    wsym[15]:=modsym;
  1015.     rword[16]:='NOT     ';    wsym[16]:=notsym;
  1016.     rword[17]:='OF      ';    wsym[17]:=ofsym;
  1017.     rword[18]:='OR      ';    wsym[18]:=orsym;
  1018.     rword[19]:='PROCEDUR';    wsym[19]:=procsym;
  1019.     rword[20]:='PROGRAM ';    wsym[20]:=progsym;
  1020.     rword[21]:='PUT     ';    wsym[21]:=putsym;
  1021.     rword[22]:='RECORD  ';    wsym[22]:=recordsym;
  1022.     rword[23]:='REPEAT  ';    wsym[23]:=repeatsym;
  1023.     rword[24]:='THEN    ';    wsym[24]:=thensym;
  1024.     rword[25]:='TO      ';    wsym[25]:=tosym;
  1025.     rword[26]:='TYPE    ';    wsym[26]:=typesym;
  1026.     rword[27]:='UNTIL   ';    wsym[27]:=untilsym;
  1027.     rword[28]:='VAR     ';    wsym[28]:=varsym;
  1028.     rword[29]:='WHILE   ';    wsym[29]:=whilesym;
  1029.  
  1030.     errflag:=false; (* clear line error flag *)
  1031.     tx:=0; (* init table pointers *)
  1032.     put#1('ppc rev ',vhu#,'.',vtn#,vun#,devrel,13,10);
  1033.     put#1('Listing?'); get#1(listing);
  1034.  
  1035.     (* define standard type identifiers *)
  1036.     enter('INTEGER ',simptype,0,0,intsize);
  1037.     enter('CHAR    ',simptype,0,0,charsize);
  1038.     enter('BOOLEAN ',simptype,0,0,boolsize);
  1039.     enter('BYTE    ',simptype,0,0,charsize);
  1040.     enter('WORD    ',simptype,0,0,intsize);
  1041.     enter('ALFA    ',simptype,0,0,alfasize);
  1042.     ch:=' '; (* init the character scanner *)
  1043.     getsym;
  1044.     nl:=1; gen(jmp,0,1);
  1045.     block(1,1);
  1046.     gen(csp,0,9);
  1047.     gen(peof,0,0);
  1048.     if sym<> period then error(20)
  1049. end.
  1050. eof
  1051.