home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / MBUG / MBUG066.ARC / PPC.PAS < prev    next >
Pascal/Delphi Source File  |  1979-12-31  |  26KB  |  1,046 lines

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