PROCEDURE STATEMENT(FSYS: SETOFSYS);
        LABEL 1;
        VAR LCP: CTP; LLP: LBP; FLLEV: INTEGER; PKEY: 1..16;
            FILELOAD: BOOLEAN;

        PROCEDURE EXPRESSION (FSYS: SETOFSYS); FORWARD;

        PROCEDURE DERANGE (VAR A : ATTR);
         (* CHANGE A SUBRANGE TYPE TO ITS BASE TYPE *)
        BEGIN
          WITH A.TYPTR^ DO
            IF FORM = SUBRANGE
              THEN A.TYPTR := RANGETYPE
        END (* DERANGE *);

        FUNCTION FILEVAR(VAR LSP: STP): BOOLEAN;
        (* test variable type to see if it is a file.  FILEVAR returns *)
        (* true if variable is of type file.  LSP points to the file   *)
        (* variable or variable element of type file                   *)
        BEGIN
          IF (LSP^.FORM = FILES) AND (SY = ARROW) THEN FILEVAR := FALSE
          (* return false if variable is a file buffer *)
          ELSE BEGIN (* if varaible type is complex, check element types *)
            IF LSP^.FORM = ARRAYS THEN (* get element type *)
              WHILE LSP^.FORM = ARRAYS DO
                LSP := LSP^.AELTYPE;
            FILEVAR := LSP^.FORM = FILES
          END
        END;


        PROCEDURE SELECTOR(FSYS: SETOFSYS; FCP: CTP);
        VAR LATTR: ATTR; LCP: CTP; LSP: STP;
         LSIZE,LMIN,LMAX: INTEGER;

        (* this procedure assigns values to GATTR for the variable in   *)
        (* FCP.  If the variable is an array or record element, the     *)
        (* code to calculate the address for the element is printed.    *)
        (* If a procedure requires a file address to be loaded, then    *)
        (* that address must be loaded first.  FILELOAD is a flag which *)
        (* indicates whether or not a file address needs to be loaded.  *)

        BEGIN
          WITH FCP^, GATTR DO
            BEGIN TYPTR := IDTYPE; KIND := VARBL;
              CASE KLASS OF
                VARS:
                  IF VKIND = ACTUAL THEN
                    BEGIN ACCESS := DRCT; VLEVEL := VLEV;
                    FLLEV := VLEV; DPLMT := VADDR
                    END
                  ELSE
                    BEGIN GEN2T(54(*LOD*),LEVEL-VLEV,VADDR,NILPTR);
                    ACCESS := INDRCT; IDPLMT := 0
                    END;
                FIELD:
                  WITH DISPLAY[DISX] DO
                    IF OCCUR = CREC THEN
                      BEGIN ACCESS := DRCT; VLEVEL := CLEV;
                      DPLMT := CDSPL + FLDADDR
                      END
                    ELSE
                      BEGIN
                        IF LEVEL = 1 THEN GEN1T(39(*LDO*),VDSPL,NILPTR)
                        ELSE GEN2T(54(*LOD*),0,VDSPL,NILPTR);
                        ACCESS := INDRCT; IDPLMT := FLDADDR
                      END;
                FUNC:
                  IF PFDECKIND = STANDARD THEN
                    BEGIN ERROR(150); TYPTR := NIL END
                  ELSE
                    BEGIN
                      IF PFKIND = FORMAL THEN ERROR(151)
                      ELSE
                        IF (PFLEV+1<>LEVEL)OR(FPROCP<>FCP) THEN ERROR(177);
                        BEGIN ACCESS := DRCT; VLEVEL := PFLEV + 1;
                          DPLMT := 0   (*IMPL. RELAT. ADDR. OF FCT. RESULT*)
                        END
                    END
              END (*CASE*)
            END (*WITH*);
          IF NOT (SY IN SELECTSYS + FSYS) THEN
            BEGIN ERROR(59); SKIP(SELECTSYS + FSYS) END;
          IF NOT FILELOAD THEN (* address of file has not been loaded *)
            BEGIN LSP := GATTR.TYPTR; FILELOAD := TRUE;
            IF NOT FILEVAR(LSP) THEN (* load address of standard file *)
              IF PKEY IN [2,6,12] THEN BEGIN (* in procedure put or write *)
                IF NOT OUTFLG THEN ERROR(176);
                GEN2(50(*LDA*),LEVEL-1,7)
                END
              ELSE BEGIN
                IF NOT INPFLG THEN ERROR(175);
                GEN2(50(*LDA*),LEVEL-1,5)
                END
            ELSE (* first parameter is a file, load its address *)
              IF GATTR.TYPTR^.FORM <> ARRAYS THEN LOADADDRESS
              (* if array of files, file address loaded below *)
            END;
          WHILE SY IN SELECTSYS DO
            BEGIN
        (*[*)   IF SY = LBRACK THEN
                BEGIN
                  REPEAT LATTR := GATTR;
                    WITH LATTR DO
                      IF TYPTR <> NIL THEN
                        IF TYPTR^.FORM <> ARRAYS THEN
                          BEGIN ERROR(138); TYPTR := NIL END;
                    LOADADDRESS;
                    INSYMBOL; EXPRESSION(FSYS + [COMMA,RBRACK]);
                    LOAD;
                    IF GATTR.TYPTR <> NIL THEN
                      IF GATTR.TYPTR^.FORM > SUBRANGE THEN ERROR(113);
                    IF LATTR.TYPTR <> NIL THEN
                      WITH LATTR.TYPTR^ DO
                        BEGIN
                          IF COMPTYPES(INXTYPE,GATTR.TYPTR) THEN
                            BEGIN
                              IF INXTYPE <> NIL THEN
                                BEGIN GETBOUNDS(INXTYPE,LMIN,LMAX);
                                IF CHECKNEEDED (INXTYPE, GATTR.TYPTR)
                                  THEN GEN2T(45(*CHK*),LMIN,LMAX,INTPTR);
                                IF LMIN>0 THEN GEN1T(31(*DEC*),LMIN,INTPTR)
                                  ELSE IF LMIN<0 THEN
                                  GEN1T(34(*INC*),-LMIN,INTPTR);
                                  (*OR SIMPLY GEN1(31,LMIN)*)
                                END
                            END
                          ELSE ERROR(139);
                          WITH GATTR DO
                            BEGIN TYPTR := AELTYPE; KIND := VARBL;
                          IF (AELTYPE = CHARPTR) AND PACKEDSTRUCT THEN
                           ACCESS := INXD
                          ELSE
                           BEGIN
                              ACCESS := INDRCT; IDPLMT := 0
                           END
                            END;
                          IF (GATTR.TYPTR <> NIL) AND (GATTR.ACCESS = INDRCT) THEN
                            BEGIN
                              LSIZE := GATTR.TYPTR^.SIZE;
                              ALIGN(GATTR.TYPTR,LSIZE);
                              GEN1(36(*IXA*),LSIZE)
                            END
                        END
                  UNTIL SY <> COMMA;
                  IF SY = RBRACK THEN INSYMBOL ELSE ERROR(12)
                END (*IF SY = LBRACK*)
              ELSE
        (*.*)     IF SY = PERIOD THEN
                  BEGIN
                    WITH GATTR DO
                      BEGIN
                        IF TYPTR <> NIL THEN
                          IF TYPTR^.FORM <> RECORDS THEN
                            BEGIN ERROR(140); TYPTR := NIL END;
                        INSYMBOL;
                        IF SY = IDENT THEN
                          BEGIN
                            IF TYPTR <> NIL THEN
                              BEGIN SEARCHSECTION(TYPTR^.FSTFLD,LCP);
                                IF LCP = NIL THEN
                                  BEGIN ERROR(152); TYPTR := NIL END
                                ELSE
                                  WITH LCP^ DO
                                    BEGIN TYPTR := IDTYPE;
                                      CASE ACCESS OF
                                        DRCT:   DPLMT := DPLMT + FLDADDR;
                                        INDRCT: IDPLMT := IDPLMT + FLDADDR;
                                        INXD:   ERROR(350)
                                      END
                                    END
                              END;
                            INSYMBOL
                          END (*SY = IDENT*)
                        ELSE ERROR(2)
                      END (*WITH GATTR*)
                  END (*IF SY = PERIOD*)
                ELSE
        (*^*)       BEGIN
                    IF GATTR.TYPTR <> NIL THEN
                      WITH GATTR,TYPTR^ DO
                        IF FORM = POINTER THEN
                          BEGIN LOAD; TYPTR := ELTYPE;
                            IF PTRCHECKS THEN
                               GEN2T(45(*CHK*),1,MAXADDR,NILPTR);
                            WITH GATTR DO
                              BEGIN KIND := VARBL; ACCESS := INDRCT;
                                IDPLMT := 0
                              END
                          END
                        ELSE
                          IF FORM = FILES THEN BEGIN
                            TYPTR := FILTYPE;
                            DPLMT := DPLMT + 1
                            END
                          ELSE ERROR(141);
                    INSYMBOL
                  END;
              IF NOT (SY IN FSYS + SELECTSYS) THEN
                BEGIN ERROR(6); SKIP(FSYS + SELECTSYS) END
            END; (*WHILE*)
        END; (*SELECTOR*)

        PROCEDURE CALL(FSYS: SETOFSYS; FCP: CTP);
          VAR LKEY: 1..16;
          PROCEDURE VARIABLE(FSYS: SETOFSYS; VAR LCP: CTP);
          BEGIN
            IF SY = IDENT THEN
              BEGIN SEARCHID([VARS,FIELD],LCP); INSYMBOL END
            ELSE BEGIN ERROR(2); LCP := UVARPTR END;
            SELECTOR(FSYS + [COMMA],LCP)
          END (*VARIABLE*);

          PROCEDURE RESETREWRITE;
            VAR
              I,J,SIZE,FLEV: INTEGER;
              LSP: STP; LCP: CTP;
              EXTNAME: BOOLEAN;

          BEGIN
            EXTNAME := FALSE; FILELOAD := FALSE;
            FOR I := 2 TO 100 DO PATHNAME[I] := ' ';
            VARIABLE(FSYS + [RPARENT], LCP); LSP := LCP^.IDTYPE;
            IF GATTR.TYPTR = NIL THEN ERROR(2)
            ELSE IF NOT(LSP^.FORM IN [ARRAYS,FILES,RECORDS]) THEN ERROR(116)
            ELSE BEGIN
              IF SY = COMMA THEN (* read in a pathanme *)
                IF NOT FINDFILE(LCP) THEN
                  BEGIN ERROR(183);
                  (* file is temporary; pathname is not allowed *)
                  SKIP(FSYS + [COMMA,RPARENT])
                  END
                ELSE BEGIN (* get pathname *)
                  INSYMBOL; EXTNAME := TRUE;
                  IF SY <> IDENT THEN ERROR(2);
                  INSYMBOL
                  END;
              IF NOT EXTNAME THEN (* no pathname was givin *)
                FOR J := 1 TO 8 DO PATHNAME[J] := ID[J];
              CASE LSP^.FORM OF
                ARRAYS: IF FILEVAR(LSP)
                          THEN FLEV := LCP^.VLEV
                          ELSE ERROR(116);
                 FILES: FLEV := 0;
               RECORDS: ERROR(400)
                END; (* case *)
              IF (LSP^.FILTYPE = CHARPTR) AND (LKEY = 3)
                THEN SIZE := 0              (* indicates ascii file *)
                ELSE SIZE := LSP^.SIZE - 1; (* size of buffer for binary file ((
              (* open file for either input or output *)
              WRITE(PRR, ' ':6, 'CALL', SNA[LKEY+21], '(', FLEV:1, ',');
              IF LKEY = 3 THEN WRITE(PRR, SIZE:1, ',''') ELSE WRITE(PRR, '''');
              J := 1;
              REPEAT (* print pathname *)
                WRITE(PRR, PATHNAME[J]);
                J := J + 1
                UNTIL (PATHNAME[J] = ' ') OR (J > 100);
              WRITELN(PRR, ';'')');
                IC := IC + 1;
                TOPNEW := TOPNEW + PDX [LKEY+21] * MAXSTACK;
                IF TOPNEW > TOPMAX THEN TOPMAX := TOPNEW
                END
          END; (* resetrewrite *)

          PROCEDURE GETPUT;
            VAR LCP: CTP;
          BEGIN FILELOAD := FALSE; VARIABLE(FSYS + [RPARENT], LCP);
            IF FILEVAR(LCP^.IDTYPE) THEN
              GEN1(30(*CSP*),LKEY(*GET,PUT*))
            ELSE ERROR(116)
          END (*GETPUT*);

          PROCEDURE TEXTPAGE;
            VAR LSP: STP; LCP: CTP;
          BEGIN FILELOAD := FALSE;
            VARIABLE(FSYS + [RPARENT], LCP);
            IF LCP = NIL THEN ERROR(2)
            ELSE BEGIN
              IF FILEVAR(LCP^.IDTYPE) THEN
                IF LCP^.IDTYPE^.FILTYPE <> CHARPTR
                  THEN BEGIN ERROR(182); ERROR(59) END
          (* error 182 -- file must be of type text *)
                  ELSE GEN1(30(*CSP*),26(*PAG*))
              ELSE ERROR(59)
            END
          END;

          PROCEDURE READ;
            VAR LCP: CTP; LSP,VTYPE,FTYPE: STP; SIZE: ADDRRANGE;
          BEGIN
            FTYPE := CHARPTR; FILELOAD := FALSE;
            IF SY = LPARENT THEN
              BEGIN INSYMBOL; TEST := FALSE;
              (* note since each parameter must be a variable, the *)
              (* file address will be loaded onto the stack by the *)
              (* procedure SELECTOR called by VARIABLE.  LCP will  *)
              (* always be assigned a value if the first parameter *)
              (* is defined.                                       *)
              VARIABLE(FSYS + [COMMA,RPARENT], LCP);
              IF LCP <> NIL THEN BEGIN  (* first parameter is defined *)
                VTYPE := LCP^.IDTYPE;
                IF FILEVAR(VTYPE) THEN   (* first parameter is a file *)
                  BEGIN FTYPE := VTYPE^.FILTYPE;
                  IF SY = RPARENT THEN (* should be readln *)
                    BEGIN
                    IF LKEY = 5 THEN ERROR(116);     (*PUG*)
                    TEST := TRUE
                    END
                  ELSE IF SY <> COMMA THEN
                    BEGIN
                    SKIP(FSYS + [COMMA,RPARENT]);
                    ERROR(116)
                    END;
                  IF SY = COMMA THEN (* input next symbol *)
                    BEGIN
                    INSYMBOL;
                    VARIABLE(FSYS + [COMMA,RPARENT], LCP)
                    END
                  ELSE TEST := TRUE
                  END
                END;
              IF NOT TEST THEN
                REPEAT LOADADDRESS;
                  IF GATTR.TYPTR <> NIL THEN
                    BEGIN VTYPE := GATTR.TYPTR;
                    IF FTYPE^.FORM IN [SCALAR, SUBRANGE, ARRAYS, RECORDS] THEN
                      IF COMPTYPES(FTYPE,CHARPTR) THEN (* file is ascii *)
                        IF COMPTYPES(VTYPE,INTPTR)
                          THEN GEN1(30(*csp*),3(*rdi*))
                        ELSE IF COMPTYPES(VTYPE,REALPTR)
                          THEN GEN1(30(*csp*),4(*rdi*))
                        ELSE IF COMPTYPES(VTYPE,CHARPTR)
                          THEN GEN1(30(*csp*),5(*rdc*))
                        ELSE ERROR(145)
                      ELSE IF COMPTYPES(VTYPE,FTYPE) THEN
                        (* variable and file are of the same type *)
                        BEGIN SIZE := FTYPE^.SIZE;
                        GEN2(30(*csp*),27(*brd*),SIZE)
                        END
                      ELSE ERROR(116)
                    END;
                  TEST := SY <> COMMA;
                  IF NOT TEST THEN
                    BEGIN INSYMBOL; VARIABLE(FSYS + [COMMA,RPARENT], LCP) END
                UNTIL TEST;
              IF SY = RPARENT THEN INSYMBOL ELSE ERROR(4)
              END (* if sy = lparent *)
            ELSE IF LKEY = 5 THEN ERROR(116)
              ELSE BEGIN (* load standard input address for readln *)
                FILELOAD := TRUE;
                IF NOT INPFLG THEN ERROR(176);
                GEN2(50(*LDA*),LEVEL-1,5)
                END;
            IF LKEY = 11
              THEN GEN1(30(*CSP*),21(*RLN*))
            ELSE WRITELN(PRR, ' ':6, 'SP=SP-1')  (* decrement stack *)
          END; (*READ*)

          PROCEDURE WRITE;
            VAR LSP,VTYPE,FTYPE: STP; IDEFLT,RDEFLT: BOOLEAN;
                LCP:CTP; LADDR,SIZE,LEN: ADDRRANGE; LLKEY: 1..16;
                HIGH,LOW: INTEGER;
          BEGIN LLKEY := LKEY;
            FTYPE := CHARPTR; FILELOAD := FALSE;
            IF SY = LPARENT THEN
              BEGIN INSYMBOL; TEST := FALSE;
              EXPRESSION(FSYS + [COMMA,COLON,RPARENT]);
              IF GATTR.TYPTR <> NIL THEN BEGIN (* first parameter is a variable *)
                VTYPE := GATTR.TYPTR;
                IF FILEVAR(VTYPE) THEN  (* first parameter is file *)
                  BEGIN FTYPE := VTYPE^.FILTYPE;
                  IF SY = RPARENT THEN (* should be writeln *)
                    BEGIN
                    IF LLKEY = 6 THEN ERROR(116);    (*PUG*)
                    TEST := TRUE
                    END
                  ELSE IF SY <> COMMA THEN
                    BEGIN
                    SKIP(FSYS+[COMMA,RPARENT]);
                    ERROR(116)
                    END;
                  IF SY = COMMA THEN
                    BEGIN INSYMBOL;
                    EXPRESSION(FSYS+[COMMA,COLON,RPARENT])
                    END
                  ELSE TEST := TRUE
                  END
                END;
              IF NOT FILELOAD THEN (* the call to expression did not load file address *)
                BEGIN
                FILELOAD := TRUE;
                IF NOT OUTFLG THEN ERROR(176);
                GEN2(50(*LDA*),LEVEL-1,7)
                END;
              IF NOT TEST THEN
                REPEAT
                DERANGE (GATTR);
                VTYPE := GATTR.TYPTR;
                IF VTYPE <> NIL THEN
                  IF VTYPE^.FORM <= SUBRANGE THEN LOAD ELSE LOADADDRESS;
                IF FTYPE^.FORM IN [SCALAR,SUBRANGE,ARRAYS,RECORDS] THEN
                  IF COMPTYPES(FTYPE,CHARPTR) THEN (* file is ascii *)
                    BEGIN
                    IF SY = COLON THEN
                      BEGIN INSYMBOL;
                      EXPRESSION(FSYS + [COMMA,COLON,RPARENT]);
                      DERANGE (GATTR);
                      IF GATTR.TYPTR <> NIL THEN
                        IF GATTR.TYPTR <> INTPTR THEN ERROR(116);
                      LOAD; IDEFLT := FALSE
                      END
                    ELSE IDEFLT := TRUE;
                    IF SY = COLON THEN
                      BEGIN INSYMBOL;
                      EXPRESSION(FSYS + [COMMA,RPARENT]);
                      DERANGE (GATTR);
                      IF GATTR.TYPTR <> NIL THEN
                        IF VTYPE <> REALPTR THEN ERROR(124);
                      LOAD; RDEFLT := FALSE
                      END
                    ELSE RDEFLT := TRUE;
                    IF VTYPE = INTPTR THEN
                      BEGIN
                      IF IDEFLT THEN GEN1T (51 (*LDC*), 10, INTPTR);
                      GEN1(30(*CSP*),6(*WRI*))
                      END
                    ELSE IF VTYPE = REALPTR THEN
                      BEGIN
                      IF IDEFLT THEN GEN1T (51 (*LDC*), 20, INTPTR);
                      IF RDEFLT THEN GEN1T (51 (*LDC*), 20, INTPTR);
                      GEN1(30(*CSP*),8(*WRR*))
                      END
                    ELSE IF VTYPE = CHARPTR THEN
                      BEGIN
                      IF IDEFLT THEN GEN1T(51(*LDC*),1,INTPTR);
                      GEN1(30(*CSP*),9(*WRC*))
                      END
                    ELSE IF VTYPE^.FORM = SCALAR THEN ERROR(399)
                      ELSE IF STRING(VTYPE) THEN
                        BEGIN GETBOUNDS(VTYPE^.INXTYPE,LOW,HIGH);
                        LEN := HIGH - LOW + 1;
                        IF IDEFLT THEN
                          GEN1T(51(*LDC*),LEN,INTPTR);
                        GEN1T(51(*LDC*),LEN,INTPTR);
                        GEN1(30(*CSP*),10(*WRS*))
                        END
                      ELSE ERROR(145)
                    END
                  ELSE IF COMPTYPES(VTYPE,FTYPE) THEN
                    BEGIN SIZE := FTYPE^.SIZE;
                    GEN2(30(*csp*),28(*bwr*),SIZE)
                    END
                  ELSE ERROR(116);
                TEST := SY <> COMMA;
                IF NOT TEST THEN
                  BEGIN INSYMBOL;
                  EXPRESSION(FSYS + [COMMA,COLON,RPARENT])
                  END
                UNTIL TEST;
              IF SY = RPARENT THEN INSYMBOL ELSE ERROR(4)
              END (* if sy = lparent *)
            ELSE IF LKEY = 6 THEN ERROR(116)
              ELSE BEGIN (* load standard output address for writeln *)
                FILELOAD := TRUE;
                IF NOT OUTFLG THEN ERROR(176);
                GEN2(50(*LDA*),LEVEL-1,7)
                END;
            IF LLKEY = 12 THEN (*WRITELN*)
              GEN1(30(*CSP*),22(*WLN*))
            ELSE
              WRITELN(PRR, ' ':6, 'SP=SP-1')
          END (*WRITE*) ;

          PROCEDURE PACK;
            VAR LSP,LSP1: STP; LCP: CTP;
          BEGIN ERROR(399); VARIABLE(FSYS + [COMMA,RPARENT], LCP);
            LSP := NIL; LSP1 := NIL;
            IF GATTR.TYPTR <> NIL THEN
              WITH GATTR.TYPTR^ DO
                IF FORM = ARRAYS THEN
                  BEGIN LSP := INXTYPE; LSP1 := AELTYPE END
                ELSE ERROR(116);
            IF SY = COMMA THEN INSYMBOL ELSE ERROR(20);
            EXPRESSION(FSYS + [COMMA,RPARENT]);
            IF GATTR.TYPTR <> NIL THEN
              IF GATTR.TYPTR^.FORM > SUBRANGE THEN ERROR(116)
              ELSE
                IF NOT COMPTYPES(LSP,GATTR.TYPTR) THEN ERROR(116);
            IF SY = COMMA THEN INSYMBOL ELSE ERROR(20);
            VARIABLE(FSYS + [RPARENT], LCP);
            IF GATTR.TYPTR <> NIL THEN
              WITH GATTR.TYPTR^ DO
                IF FORM = ARRAYS THEN
                  BEGIN
                    IF NOT COMPTYPES(AELTYPE,LSP1)
                      OR NOT COMPTYPES(INXTYPE,LSP) THEN
                      ERROR(116)
                  END
                ELSE ERROR(116)
          END (*PACK*) ;

          PROCEDURE UNPACK;
            VAR LSP,LSP1: STP; LCP: CTP;
          BEGIN ERROR(399); VARIABLE(FSYS + [COMMA,RPARENT], LCP);
            LSP := NIL; LSP1 := NIL;
            IF GATTR.TYPTR <> NIL THEN
              WITH GATTR.TYPTR^ DO
                IF FORM = ARRAYS THEN
                  BEGIN LSP := INXTYPE; LSP1 := AELTYPE END
                ELSE ERROR(116);
            IF SY = COMMA THEN INSYMBOL ELSE ERROR(20);
            VARIABLE(FSYS + [COMMA,RPARENT], LCP);
            IF GATTR.TYPTR <> NIL THEN
              WITH GATTR.TYPTR^ DO
                IF FORM = ARRAYS THEN
                  BEGIN
                    IF NOT COMPTYPES(AELTYPE,LSP1)
                      OR NOT COMPTYPES(INXTYPE,LSP) THEN
                      ERROR(116)
                  END
                ELSE ERROR(116);
            IF SY = COMMA THEN INSYMBOL ELSE ERROR(20);
            EXPRESSION(FSYS + [RPARENT]);
            IF GATTR.TYPTR <> NIL THEN
              IF GATTR.TYPTR^.FORM > SUBRANGE THEN ERROR(116)
              ELSE
                IF NOT COMPTYPES(LSP,GATTR.TYPTR) THEN ERROR(116);
          END (*UNPACK*) ;

          PROCEDURE NEW;
            LABEL 1;
            VAR LSP,LSP1: STP; VARTS,LMIN,LMAX: INTEGER;
                LSIZE,LSZ: ADDRRANGE; LVAL: VALU; LCP: CTP;
          BEGIN VARIABLE(FSYS + [COMMA,RPARENT], LCP); LOADADDRESS;
            LSP := NIL; VARTS := 0; LSIZE := 0;
            IF GATTR.TYPTR <> NIL THEN
              WITH GATTR.TYPTR^ DO
                IF FORM = POINTER THEN
                  BEGIN
                    IF ELTYPE <> NIL THEN
                      BEGIN LSIZE := ELTYPE^.SIZE;
                        IF ELTYPE^.FORM = RECORDS THEN LSP := ELTYPE^.RECVAR
                      END
                  END
                ELSE ERROR(116);
            WHILE SY = COMMA DO
              BEGIN INSYMBOL;CONSTANT(FSYS + [COMMA,RPARENT],LSP1,LVAL);
                VARTS := VARTS + 1;
                (*CHECK TO INSERT HERE: IS CONSTANT IN TAGFIELDTYPE RANGE*)
                IF LSP = NIL THEN ERROR(158)
                ELSE
                  IF LSP^.FORM <> TAGFLD THEN ERROR(162)
                  ELSE
                    IF LSP^.TAGFIELDP <> NIL THEN
                      IF STRING(LSP1) OR (LSP1 = REALPTR) THEN ERROR(159)
                      ELSE
                        IF COMPTYPES(LSP^.TAGFIELDP^.IDTYPE,LSP1) THEN
                          BEGIN
                            LSP1 := LSP^.FSTVAR;
                            WHILE LSP1 <> NIL DO
                              WITH LSP1^ DO
                                IF VARVAL.IVAL = LVAL.IVAL THEN
                                  BEGIN LSIZE := SIZE; LSP := SUBVAR;
                                    GOTO 1
                                  END
                                ELSE LSP1 := NXTVAR;
                            LSIZE := LSP^.SIZE; LSP := NIL;
                          END
                        ELSE ERROR(116);
          1:  END (*WHILE*) ;
            GEN1T(51(*LDC*),LSIZE,INTPTR);
            GEN1(30(*CSP*),12(*NEW*));
          END (*NEW*) ;

          PROCEDURE MARK;
            VAR LCP: CTP;
          BEGIN VARIABLE(FSYS+[RPARENT], LCP);
             IF GATTR.TYPTR <> NIL THEN
               IF GATTR.TYPTR^.FORM = POINTER THEN
                 BEGIN LOADADDRESS; GEN1(30(*CSP*),23(*SAV*)) END
               ELSE ERROR(116)           (*PUG*)
          END(*MARK*);

          PROCEDURE RELEASE;
            VAR LCP: CTP;
          BEGIN VARIABLE(FSYS+[RPARENT], LCP);
                IF GATTR.TYPTR <> NIL THEN
                   IF GATTR.TYPTR^.FORM = POINTER THEN
                      BEGIN LOAD; GEN1(30(*CSP*),13(*RST*)) END
                   ELSE ERROR(116)          (*PUG*)
          END (*RELEASE*);

          PROCEDURE TIMEDATE;
            VAR LCP: CTP;
          BEGIN VARIABLE(FSYS + [RPARENT], LCP);
            IF GATTR.TYPTR <> NIL THEN
              IF GATTR.TYPTR^.FORM <> ARRAYS THEN ERROR(103)
              ELSE BEGIN
                LOADADDRESS;
                IF LKEY = 15
                  THEN GEN2(30(*CSP*),29(*DAT*),2(*TIME*))
                  ELSE GEN2(30(*CSP*),29(*DAT*),1(*DATE*))
                END
            ELSE ERROR(2)
          END; (*TIMEDATE*)

          PROCEDURE ABS;
          BEGIN
            IF GATTR.TYPTR <> NIL THEN
              IF GATTR.TYPTR = INTPTR THEN GEN0(0(*ABI*))
              ELSE
                IF GATTR.TYPTR = REALPTR THEN GEN0(1(*ABR*))
                ELSE BEGIN ERROR(125); GATTR.TYPTR := INTPTR END
          END (*ABS*) ;

          PROCEDURE SQR;
          BEGIN
            IF GATTR.TYPTR <> NIL THEN
              IF GATTR.TYPTR = INTPTR THEN GEN0(24(*SQI*))
              ELSE
                IF GATTR.TYPTR = REALPTR THEN GEN0(25(*SQR*))
                ELSE BEGIN ERROR(125); GATTR.TYPTR := INTPTR END
          END (*SQR*) ;

          PROCEDURE TRUNC;
          BEGIN
            IF GATTR.TYPTR <> NIL THEN
              IF GATTR.TYPTR <> REALPTR THEN ERROR(125);
            GEN0(27(*TRC*));
            GATTR.TYPTR := INTPTR
          END (*TRUNC*) ;

          PROCEDURE ODD;
          BEGIN
            IF GATTR.TYPTR <> NIL THEN
              IF GATTR.TYPTR <> INTPTR THEN ERROR(125);
            GEN0(20(*ODD*));
            GATTR.TYPTR := BOOLPTR
          END (*ODD*) ;

          PROCEDURE ORD;
          BEGIN
            IF GATTR.TYPTR <> NIL THEN
              IF GATTR.TYPTR^.FORM >= POWER THEN ERROR(125);
           (* GEN0T(58[ORD],GATTR.TYPTR); *)
            GATTR.TYPTR := INTPTR
          END (*ORD*);

          PROCEDURE CHR;
          BEGIN
            IF GATTR.TYPTR <> NIL THEN
              IF GATTR.TYPTR <> INTPTR THEN ERROR(125)
               ELSE IF RANGECHECKS THEN
                 GEN2T (45(*CHK*), ORDMINCHAR, ORDMAXCHAR, INTPTR);
            GATTR.TYPTR := CHARPTR
          END (*CHR*) ;

          PROCEDURE PREDSUCC;
          BEGIN
            IF GATTR.TYPTR <> NIL THEN
              IF GATTR.TYPTR^.FORM <> SCALAR THEN ERROR(125);
            IF LKEY = 7 THEN GEN1T(31(*DEC*),1,GATTR.TYPTR)
            ELSE GEN1T(34(*INC*),1,GATTR.TYPTR)
          END (*PREDSUCC*) ;

(*        PROCEDURE SHORT;                                           *)
(*        (* Only integer, character or array types may be used *)
(*          (* with this function *)
(*        BEGIN                                                      *)
(*        IF GATTR.TYPTR <> NIL THEN                                 *)
(*          IF ((GATTR.TYPTR = INTPTR) OR (GATTR.TYPTR = CHARPTR)) THEN*)
(*            generate left shift                                    *)
(*          ELSE IF GATTR.TYPTR^.FORM = ARRAYS THEN                  *)
(*            GEN1(66(*CPF  , GATTR.TYPTR^.SIZE)                     *)
(*          ELSE ERROR(125)                                          *)
(*        END;                                                       *)

          PROCEDURE EOF;
            VAR LCP: CTP;
          BEGIN
            IF SY = LPARENT THEN
              BEGIN INSYMBOL; VARIABLE(FSYS + [RPARENT], LCP);
                IF SY = RPARENT THEN INSYMBOL ELSE ERROR(4)
              END
            ELSE
              WITH GATTR DO
                BEGIN TYPTR := TEXTPTR; KIND := VARBL; ACCESS := DRCT;
                  VLEVEL := 1; DPLMT := LCAFTERMARKSTACK
                END;
            LOADADDRESS;
            IF GATTR.TYPTR <> NIL THEN
              IF GATTR.TYPTR^.FORM <> FILES THEN ERROR(125);
            IF LKEY = 9 THEN GEN0(8(*EOF*)) ELSE GEN1(30(*CSP*),14(*ELN*));
              GATTR.TYPTR := BOOLPTR
          END (*EOF*) ;

          PROCEDURE CALLNONSTANDARD;
            VAR NXT,LCP: CTP; LSP: STP; LKIND: IDKIND; LB: BOOLEAN;
              LOCPAR,          (* # locations needed for parameters *)
                               (* on run time stack, init to zero *)
              LLC: ADDRRANGE;
          BEGIN LOCPAR := 0;
            WITH FCP^ DO
              BEGIN NXT := NEXT; LKIND := PFKIND;
                IF NOT EXTDECL THEN GEN1(41(*MST*),LEVEL-PFLEV)
                (* LEVEL-PFLEV is static level difference between *)
                (* caller and callee *)
              END;
            IF SY = LPARENT THEN
              BEGIN LLC := LC;
                REPEAT LB := FALSE; (*DECIDE WHETHER PROC/FUNC MUST BE PASSED*)
                  IF LKIND = ACTUAL THEN
                    BEGIN
                      IF NXT = NIL THEN ERROR(126)
                      ELSE LB := NXT^.KLASS IN [PROC,FUNC]
                    END ELSE ERROR(399);
                  (*FOR FORMAL PROC/FUNC LB IS FALSE AND EXPRESSION
                   WILL BE CALLED, WHICH WILL ALLWAYS INTERPRET A PROC/FUNC ID
                  AT ITS BEGINNING AS A CALL RATHER THAN A PARAMETER PASSING.
                  IN THIS IMPLEMENTATION, PARAMETER PROCEDURES/FUNCTIONS
                  ARE THEREFORE NOT ALLOWED TO HAVE PROCEDURE/FUNCTION
                  PARAMETERS*)
                  INSYMBOL;
                  IF LB THEN   (*PASS FUNCTION OR PROCEDURE*)
                    BEGIN ERROR(399);
                      IF SY <> IDENT THEN
                        BEGIN ERROR(2); SKIP(FSYS + [COMMA,RPARENT]) END
                      ELSE
                        BEGIN
                          IF NXT^.KLASS = PROC THEN SEARCHID([PROC],LCP)
                          ELSE
                            BEGIN SEARCHID([FUNC],LCP);
                              IF NOT COMPTYPES(LCP^.IDTYPE,NXT^.IDTYPE) THEN
                                ERROR(128)
                            END;
                          INSYMBOL;
                          IF NOT (SY IN FSYS + [COMMA,RPARENT]) THEN
                            BEGIN ERROR(6); SKIP(FSYS + [COMMA,RPARENT]) END
                        END
                    END (*IF LB*)
                  ELSE (* parameters passed are not func or proc *)
                    (* normal case *)
                    BEGIN EXPRESSION(FSYS + [COMMA,RPARENT]);
                      IF GATTR.TYPTR <> NIL THEN
                        IF LKIND = ACTUAL THEN
                          BEGIN
                            IF NXT <> NIL THEN (* parameters exist *)
                              BEGIN LSP := NXT^.IDTYPE;
                                IF LSP <> NIL THEN
                                  BEGIN
                                    IF (NXT^.VKIND = ACTUAL) THEN
                                      IF LSP^.FORM <= POWER THEN
                                      BEGIN LOAD;
                                        IF COMPTYPES(REALPTR,LSP)
                                           AND COMPTYPES(GATTR.TYPTR,INTPTR)
                                          THEN BEGIN GEN0(10(*FLT*));
                                            GATTR.TYPTR := REALPTR
                                          END;
                                        IF LSP^.FORM <= SUBRANGE THEN
                                         IF CHECKNEEDED (LSP, GATTR.TYPTR)
                                          THEN CHECKBNDS(LSP);
                                        IF LSP^.FORM = POWER THEN
                                           LOCPAR := LOCPAR + SETHIGH DIV 32 + 1
                                        ELSE LOCPAR := LOCPAR + LSP^.SIZE;
                                        ALIGN(PARMPTR,LOCPAR);
                                      END
                                      ELSE
                                      BEGIN
                                        LOADADDRESS;
                                        LOCPAR := LOCPAR+PTRSIZE;
                                        ALIGN(PARMPTR,LOCPAR)
                                      END
                                    ELSE
                                      IF GATTR.KIND = VARBL THEN
                                       BEGIN LOADADDRESS;
                                         LOCPAR := LOCPAR+PARMSIZE
                                        END
                                      ELSE ERROR(154);
                                    IF NOT COMPTYPES(LSP,GATTR.TYPTR) THEN
                                      ERROR(142)
                                  END
                              END
                          END
                      ELSE (*LKIND = FORMAL*)
                        BEGIN (*PASS FORMAL PARAM*)
                        END
                    END;
                  IF (LKIND = ACTUAL) AND (NXT <> NIL) THEN NXT := NXT^.NEXT
                UNTIL SY <> COMMA;
                LC := LLC;
              IF SY = RPARENT THEN INSYMBOL ELSE ERROR(4)
            END (*IF LPARENT*);
            IF LKIND = ACTUAL THEN
              BEGIN IF NXT <> NIL THEN ERROR(126);
                WITH FCP^ DO
                  BEGIN
                    IF EXTDECL THEN GEN1(30(*CSP*),PFNAME)
                    ELSE IF FORTDECL THEN (* Fortran proc/func *)
                      GENFENT(46(*CUP*),LOCPAR,NAME,FCP)
                      (* Assume no parameters need > 1 location *)
                      (* since sets not supported by Fortran, *)
                      (* thus LOCPAR = # entries pushed on stack *)
                    ELSE GENCUPENT(46(*CUP*),LOCPAR,PFNAME)
                  END
              END;
            GATTR.TYPTR := FCP^.IDTYPE
          END (*CALLNONSTANDARD*) ;

        BEGIN (*CALL*)
          IF FCP^.PFDECKIND = STANDARD THEN
            BEGIN
              LKEY := FCP^.KEY;
              IF FCP^.KLASS = PROC THEN
                BEGIN
                PKEY := FCP^.KEY;
                IF NOT(LKEY IN [5,6,11,12]) THEN
                  IF SY = LPARENT THEN INSYMBOL ELSE ERROR(9);
                CASE LKEY OF
                   1,2: GETPUT;
                   3,4: RESETREWRITE;
                  5,11: READ;
                  6,12: WRITE;
                     7: PACK;
                     8: UNPACK;
                     9: NEW;
                    10: RELEASE;
                    13: TEXTPAGE;
                    14: MARK;
                 15,16: TIMEDATE
                END;
                IF NOT(LKEY IN [5,6,11,12]) THEN
                  IF SY = RPARENT THEN INSYMBOL ELSE ERROR(4)
               END
              ELSE
                BEGIN
                  IF LKEY <= 8 THEN
                    BEGIN
                      IF SY = LPARENT THEN INSYMBOL ELSE ERROR(9);
                      EXPRESSION(FSYS+[RPARENT]); LOAD; DERANGE (GATTR)
                    END;
                  CASE LKEY OF
                    1:    ABS;
                    2:    SQR;
                    3:    TRUNC;
                    4:    ODD;
                    5:    ORD;
                    6:    CHR;
                    7,8:  PREDSUCC;
                    9,10:    EOF
                  END;
                  IF LKEY <= 8 THEN
                    IF SY = RPARENT THEN INSYMBOL ELSE ERROR(4)
                END;
            END (*STANDARD PROCEDURES AND FUNCTIONS*)
          ELSE CALLNONSTANDARD
        END (*CALL*) ;

        PROCEDURE EXPRESSION;
          VAR LATTR: ATTR; LOP: OPERATOR; TYPIND: INTEGER; LSIZE: ADDRRANGE;
              LMAX, LMIN : INTEGER;

          PROCEDURE SIMPLEEXPRESSION(FSYS: SETOFSYS);
            VAR LATTR: ATTR; LOP: OPERATOR; SIGNED: BOOLEAN;

            PROCEDURE TERM(FSYS: SETOFSYS);
              VAR LATTR: ATTR; LOP: OPERATOR;

              PROCEDURE FACTOR(FSYS: SETOFSYS);
                VAR LCP: CTP; LVP: CSP; VARPART: BOOLEAN;
                    CSTPART: MAXSET; LSP,INX: STP;
                    OFFSET, LMAX, LMIN, FIRSTWORD, LASTWORD : INTEGER;
                    SETVAL : VALU;

                PROCEDURE ENTERSET (S : MAXSET; VAR FIRST, LAST : INTEGER);
                   VAR OFFSET, I, J : INTEGER;
                       W : WORDSET;

                   PROCEDURE INSERT (W : WORDSET);
                   BEGIN
                   IF SETINDEX <= MAXSETINDEX THEN BEGIN
                      SETTABLE [SETINDEX] := W;
                      SETINDEX := SETINDEX + 1;
                      END
                   ELSE ERROR (254)
                   END (* INSERT *);

                BEGIN (* ENTERSET *)
                IF S = [] THEN BEGIN
                   FIRST := 1;   LAST := 0;
                   END
                ELSE BEGIN
                   FIRST := 7;   LAST := -1;
                   FOR I := 0 TO (SETHIGH DIV 32) DO BEGIN
                      W := [];   OFFSET := I * (MAXBIT + 1);
                      FOR J := 0 TO MAXBIT DO
                         IF J+OFFSET IN S THEN W := W + [J];
                      IF W <> [] THEN BEGIN
                         IF (FIRST <= LAST) AND (LAST < I-1) THEN
                            FOR J := LAST+1 TO I-1 DO INSERT([]);
                         INSERT(W);
                         LAST := I;
                         IF I < FIRST THEN FIRST := I
                         END (* W <> [] *)
                      END (* FOR I *)
                   END (* S <> [] *)
                END (* ENTERSET *);

                FUNCTION CONSTERROR : BOOLEAN;

                BEGIN
                CONSTERROR := FALSE;
                IF GATTR.KIND = CST
                 THEN IF (GATTR.CVAL.IVAL < SETLOW) OR
                         (GATTR.CVAL.IVAL > SETHIGH) THEN
                   BEGIN   ERROR(304);
                   CONSTERROR := TRUE
                   END
                END (* CONSTERROR *);


                FUNCTION VALIDELTYPE : BOOLEAN;

                BEGIN
                VALIDELTYPE := FALSE;
                IF GATTR.TYPTR <> NIL THEN
                  IF GATTR.TYPTR^.FORM > SUBRANGE THEN ERROR(136)
                  ELSE IF COMPTYPES (LSP^.ELSET, GATTR.TYPTR)
                     THEN VALIDELTYPE := TRUE
                     ELSE ERROR (137)
                END (* VALIDELTYPE *);


              BEGIN (* FACTOR *)
                IF NOT (SY IN FACBEGSYS) THEN
                  BEGIN ERROR(58); SKIP(FSYS + FACBEGSYS);
                    GATTR.TYPTR := NIL
                  END;
                WHILE SY IN FACBEGSYS DO
                  BEGIN
                    CASE SY OF
              (*ID*)    IDENT:
                        BEGIN SEARCHID([KONST,VARS,FIELD,FUNC],LCP);
                          INSYMBOL;
                          IF LCP^.KLASS = FUNC THEN
                            BEGIN CALL(FSYS,LCP);
                              GATTR.KIND := EXPR;
                            END
                          ELSE
                            IF LCP^.KLASS = KONST THEN
                              WITH GATTR, LCP^ DO
                                BEGIN TYPTR := IDTYPE; KIND := CST;
                                  CVAL := VALUES
                                END
                            ELSE
                              SELECTOR(FSYS,LCP)
                        END;
              (*CST*)   INTCONST:
                        BEGIN
                          WITH GATTR DO
                            BEGIN TYPTR := INTPTR; KIND := CST;
                              CVAL := VAL
                            END;
                          INSYMBOL
                        END;
                      REALCONST:
                        BEGIN
                          WITH GATTR DO
                            BEGIN TYPTR := REALPTR; KIND := CST;
                              CVAL := VAL
                            END;
                          INSYMBOL
                        END;
                      STRINGCONST:
                        BEGIN
                          WITH GATTR DO
                            BEGIN
                              IF LGTH = 0 THEN TYPTR := NIL
                              ELSE IF LGTH = 1 THEN TYPTR := CHARPTR
                                ELSE
                                  BEGIN NEW(LSP,ARRAYS);
                                  WITH LSP^ DO
                                    BEGIN AELTYPE := CHARPTR; FORM:=ARRAYS;
                                    PACKEDSTRUCT := TRUE;
                                    NEW(INX,SUBRANGE);
                                    INXTYPE := INX;
                                    WITH INXTYPE^ DO
                                      BEGIN FORM := SUBRANGE;
                                      RANGETYPE := INTPTR;
                                      MIN.IVAL := 1;
                                      MAX.IVAL := LGTH
                                      END;
                                    SIZE := (LGTH + 3) DIV 4
                                    END;
                                  TYPTR := LSP
                                  END;
                              KIND := CST; CVAL := VAL
                            END;
                          INSYMBOL
                        END;
              (*(*)     LPARENT:
                        BEGIN INSYMBOL; EXPRESSION(FSYS + [RPARENT]);
                          IF SY = RPARENT THEN INSYMBOL ELSE ERROR(4)
                        END;
              (*NOT*)   NOTSY:
                        BEGIN INSYMBOL; FACTOR(FSYS);
                          LOAD; GEN0(19(*NOT*));
                          IF GATTR.TYPTR <> NIL THEN
                            IF GATTR.TYPTR <> BOOLPTR THEN
                              BEGIN ERROR(135); GATTR.TYPTR := NIL END;
                        END;
              (*[*)     LBRACK:
                        BEGIN INSYMBOL; CSTPART := [ ]; VARPART := FALSE;
                          NEW(LSP,POWER);
                          WITH LSP^ DO
                            BEGIN ELSET:=NIL;SIZE:=SETSIZE;FORM:=POWER END;
                          IF SY = RBRACK THEN
                            BEGIN
                              WITH GATTR DO
                                BEGIN TYPTR := LSP; KIND := CST END;
                              INSYMBOL
                            END
                          ELSE
                            BEGIN
                              REPEAT EXPRESSION(FSYS + [COMMA,COLON,RBRACK]);
                                IF VALIDELTYPE THEN BEGIN
                                  IF SY <> COLON THEN
                                    BEGIN (* SINGLE ELEMENT TO ADD *)
                                    IF GATTR.KIND = CST THEN BEGIN
                                      IF NOT CONSTERROR THEN
                                         CSTPART := CSTPART+[GATTR.CVAL.IVAL]
                                      END
                                    ELSE
                                      BEGIN LOAD;
                                        GEN0(23(*SGS*));
                                        IF VARPART THEN GEN0(28(*UNI*))
                                        ELSE VARPART := TRUE
                                      END;
                                    LSP^.ELSET := GATTR.TYPTR;
                                    END (* SINGLE ELEMENT *)
                                  ELSE BEGIN (* ADD MULTIPLE ELEMENTS *)
                                    IF CONSTERROR THEN GATTR.CVAL.IVAL := SETHIGH;
                                    LOAD;
                                    LSP^.ELSET := GATTR.TYPTR;
                                    INSYMBOL;
                                    EXPRESSION (FSYS + [COMMA,RBRACK]);
                                    IF VALIDELTYPE THEN BEGIN
                                      IF CONSTERROR THEN GATTR.CVAL.IVAL := SETLOW;
                                      LOAD;
                                      GEN0(59(*MTS*));
                                      END
                                    ELSE (* INVALID SECOND ITEM *)
                                      GEN0(23(*SGS*));
                                    IF VARPART THEN GEN0(28(*UNI*))
                                     ELSE VARPART := TRUE
                                    END (* MULTIPLE ELEMENTS *);
                                  GATTR.TYPTR := LSP
                                  END (* VALIDELTYPE *)
                                 ELSE GATTR.TYPTR := NIL;
                                TEST := SY <> COMMA;
                                IF NOT TEST THEN INSYMBOL
                              UNTIL TEST;
                              IF SY = RBRACK THEN INSYMBOL ELSE ERROR(12)
                            END;
                          IF GATTR.TYPTR <> NIL THEN BEGIN
                            GETBOUNDS (GATTR.TYPTR^.ELSET, LMIN, LMAX);
                            OFFSET := LMAX DIV 32 - LMIN DIV 32 + 1;
                            IF OFFSET > 8 THEN GATTR.TYPTR^.SIZE := 8
                             ELSE GATTR.TYPTR^.SIZE := OFFSET;
                            OFFSET := SETINDEX;
                            ENTERSET (CSTPART, FIRSTWORD, LASTWORD);
                            NEW (LVP, PSET);
                            WITH LVP^ DO BEGIN
                               CCLASS := PSET;   START := OFFSET;
                               FIRST := FIRSTWORD; LAST := LASTWORD;
                               END;
                            IF VARPART THEN BEGIN
                               IF CSTPART <> [ ] THEN
                                  BEGIN
                                  SETVAL.VALP := LVP;
                                  GENLDC(LSP,SETVAL);
                                  GEN0(28(*UNI*)); GATTR.KIND := EXPR
                                  END
                               END
                            ELSE
                                GATTR.CVAL.VALP := LVP
                            END (* GATTR.TYPTR <> NIL *)
                        END
                    END (*CASE*) ;
                    IF NOT (SY IN FSYS) THEN
                      BEGIN ERROR(6); SKIP(FSYS + FACBEGSYS) END
                  END (*WHILE*)
              END (*FACTOR*) ;

            BEGIN (*TERM*)
              FACTOR(FSYS + [MULOP]);
              IF SY = MULOP THEN DERANGE(GATTR);
              WHILE SY = MULOP DO
                      BEGIN LOAD; LATTR := GATTR; LOP := OP;
                  INSYMBOL; FACTOR(FSYS + [MULOP]); LOAD; DERANGE(GATTR);
                  IF (LATTR.TYPTR <> NIL) AND (GATTR.TYPTR <> NIL) THEN
                    CASE LOP OF
            (***)       MUL:  IF (LATTR.TYPTR=INTPTR)AND(GATTR.TYPTR=INTPTR)
                              THEN GEN0(15(*MPI*))
                            ELSE
                              BEGIN
                                IF LATTR.TYPTR = INTPTR THEN
                                  BEGIN GEN0(9(*FLO*));
                                    LATTR.TYPTR := REALPTR
                                  END
                                ELSE
                                  IF GATTR.TYPTR = INTPTR THEN
                                    BEGIN GEN0(10(*FLT*));
                                      GATTR.TYPTR := REALPTR
                                    END;
                                IF (LATTR.TYPTR = REALPTR)
                                  AND(GATTR.TYPTR=REALPTR)THEN GEN0(16(*MPR*))
                                ELSE
                                  IF(LATTR.TYPTR^.FORM=POWER)
                                    AND COMPTYPES(LATTR.TYPTR,GATTR.TYPTR)THEN
                                    GEN0(12(*INT*))
                                  ELSE BEGIN ERROR(134);GATTR.TYPTR:=NIL END
                              END;
            (*/*)       RDIV: BEGIN
                              IF GATTR.TYPTR = INTPTR THEN
                                  BEGIN GEN0(10(*FLT*));
                                  GATTR.TYPTR := REALPTR
                                END;
                              IF LATTR.TYPTR = INTPTR THEN
                                BEGIN GEN0(9(*FLO*));
                                  LATTR.TYPTR := REALPTR
                                END;
                              IF (LATTR.TYPTR = REALPTR)
                                AND (GATTR.TYPTR=REALPTR)THEN GEN0(7(*DVR*))
                              ELSE BEGIN ERROR(134); GATTR.TYPTR := NIL END
                            END;
            (*DIV*)     IDIV: IF (LATTR.TYPTR = INTPTR)
                              AND (GATTR.TYPTR = INTPTR) THEN GEN0(6(*DVI*))
                            ELSE BEGIN ERROR(134); GATTR.TYPTR := NIL END;
            (*MOD*)     IMOD: IF (LATTR.TYPTR = INTPTR)
                              AND (GATTR.TYPTR = INTPTR) THEN GEN0(14(*MOD*))
                            ELSE BEGIN ERROR(134); GATTR.TYPTR := NIL END;
            (*AND*)     ANDOP:IF (LATTR.TYPTR = BOOLPTR)
                              AND (GATTR.TYPTR = BOOLPTR) THEN GEN0(4(*AND*))
                            ELSE BEGIN ERROR(134); GATTR.TYPTR := NIL END
                    END (*CASE*)
                  ELSE GATTR.TYPTR := NIL
                END (*WHILE*)
            END (*TERM*) ;

          BEGIN (*SIMPLEEXPRESSION*)
            SIGNED := FALSE;
            IF (SY = ADDOP) AND (OP IN [PLUS,MINUS]) THEN
              BEGIN SIGNED := OP = MINUS; INSYMBOL END;
            TERM(FSYS + [ADDOP]);
            IF SIGNED THEN
              BEGIN LOAD; DERANGE(GATTR);
                IF GATTR.TYPTR = INTPTR THEN GEN0(17(*NGI*))
                ELSE
                  IF GATTR.TYPTR = REALPTR THEN GEN0(18(*NGR*))
                  ELSE BEGIN ERROR(134); GATTR.TYPTR := NIL END
              END;
            IF SY = ADDOP THEN DERANGE(GATTR);
            WHILE SY = ADDOP DO
              BEGIN LOAD; LATTR := GATTR; LOP := OP;
                INSYMBOL; TERM(FSYS + [ADDOP]); LOAD; DERANGE(GATTR);
                IF (LATTR.TYPTR <> NIL) AND (GATTR.TYPTR <> NIL) THEN
                  CASE LOP OF
          (*+*)       PLUS:
                      IF (LATTR.TYPTR = INTPTR)AND(GATTR.TYPTR = INTPTR) THEN
                        GEN0(2(*ADI*))
                      ELSE
                        BEGIN
                          IF LATTR.TYPTR = INTPTR THEN
                            BEGIN GEN0(9(*FLO*));
                              LATTR.TYPTR := REALPTR
                            END
                          ELSE
                            IF GATTR.TYPTR = INTPTR THEN
                              BEGIN GEN0(10(*FLT*));
                                GATTR.TYPTR := REALPTR
                              END;
                          IF (LATTR.TYPTR = REALPTR)AND(GATTR.TYPTR = REALPTR)
                            THEN GEN0(3(*ADR*))
                          ELSE IF(LATTR.TYPTR^.FORM=POWER)
                                 AND COMPTYPES(LATTR.TYPTR,GATTR.TYPTR) THEN
                                 GEN0(28(*UNI*))
                               ELSE BEGIN ERROR(134);GATTR.TYPTR:=NIL END
                        END;
          (*-*)       MINUS:
                      IF (LATTR.TYPTR = INTPTR)AND(GATTR.TYPTR = INTPTR) THEN
                        GEN0(21(*SBI*))
                      ELSE
                        BEGIN
                          IF LATTR.TYPTR = INTPTR THEN
                            BEGIN GEN0(9(*FLO*));
                              LATTR.TYPTR := REALPTR
                            END
                          ELSE
                            IF GATTR.TYPTR = INTPTR THEN
                            BEGIN GEN0(10(*FLT*));
                                GATTR.TYPTR := REALPTR
                              END;
                          IF (LATTR.TYPTR = REALPTR)AND(GATTR.TYPTR = REALPTR)
                            THEN GEN0(22(*SBR*))
                          ELSE
                            IF (LATTR.TYPTR^.FORM = POWER)
                              AND COMPTYPES(LATTR.TYPTR,GATTR.TYPTR) THEN
                              GEN0(5(*DIF*))
                            ELSE BEGIN ERROR(134); GATTR.TYPTR := NIL END
                        END;
          (*OR*)      OROP:
                      IF(LATTR.TYPTR=BOOLPTR)AND(GATTR.TYPTR=BOOLPTR)THEN
                        GEN0(13(*IOR*))
                      ELSE BEGIN ERROR(134); GATTR.TYPTR := NIL END
                  END (*CASE*)
                ELSE GATTR.TYPTR := NIL
              END (*WHILE*)
          END (*SIMPLEEXPRESSION*) ;

        BEGIN (*EXPRESSION*)
          SIMPLEEXPRESSION(FSYS + [RELOP]);
          IF SY = RELOP THEN
            BEGIN
              DERANGE (GATTR);
              IF GATTR.TYPTR <> NIL THEN
                IF GATTR.TYPTR^.FORM <= POWER THEN LOAD
                ELSE LOADADDRESS;
                LATTR := GATTR; LOP := OP;
             (* IF LOP = INOP THEN
                 IF NOT COMPTYPES(GATTR.TYPTR,INTPTR) THEN
                   GEN0T(58[ORD],GATTR.TYPTR);*)
              INSYMBOL; SIMPLEEXPRESSION(FSYS);
              DERANGE (GATTR);
              IF GATTR.TYPTR <> NIL THEN
                IF GATTR.TYPTR^.FORM <= POWER THEN LOAD
                ELSE LOADADDRESS;
              IF (LATTR.TYPTR <> NIL) AND (GATTR.TYPTR <> NIL) THEN
                IF LOP = INOP THEN
                  IF GATTR.TYPTR^.FORM = POWER THEN
                    IF COMPTYPES(LATTR.TYPTR,GATTR.TYPTR^.ELSET) THEN
                      GEN0(11(*INN*))
                    ELSE BEGIN ERROR(129); GATTR.TYPTR := NIL END
                  ELSE BEGIN ERROR(130); GATTR.TYPTR := NIL END
                ELSE
                  BEGIN
                    IF LATTR.TYPTR <> GATTR.TYPTR THEN
                      IF LATTR.TYPTR = INTPTR THEN
                        BEGIN GEN0(9(*FLO*));
                          LATTR.TYPTR := REALPTR
                        END
                      ELSE
                        IF GATTR.TYPTR = INTPTR THEN
                          BEGIN GEN0(10(*FLT*));
                            GATTR.TYPTR := REALPTR
                          END;
                    IF COMPTYPES(LATTR.TYPTR,GATTR.TYPTR) THEN
                      BEGIN LSIZE := LATTR.TYPTR^.SIZE;
                        CASE LATTR.TYPTR^.FORM OF
                          SCALAR:
                            IF LATTR.TYPTR = REALPTR THEN TYPIND := 2
                            ELSE
                              IF LATTR.TYPTR = BOOLPTR THEN TYPIND := 3
                              ELSE
                                IF LATTR.TYPTR = CHARPTR THEN TYPIND := 6
                                ELSE TYPIND := 1;
                          POINTER:
                            BEGIN
                              IF LOP IN [LTOP,LEOP,GTOP,GEOP] THEN ERROR(131);
                              TYPIND := 0
                            END;
                          POWER:
                            BEGIN IF LOP IN [LTOP,GTOP] THEN ERROR(132);
                              TYPIND := 4;   MEP(-15)
                          END;
                          ARRAYS:
                            BEGIN
                              IF NOT STRING(LATTR.TYPTR) THEN ERROR(134);
                              GETBOUNDS (LATTR.TYPTR^.INXTYPE,LMIN,LMAX);
                              LSIZE := LMAX - LMIN + 1;
                              TYPIND := 5
                            END;
                          RECORDS:
                            BEGIN
                               ERROR(134);                 (*PUG*)
                              TYPIND := 5
                            END;
                          FILES:
                            BEGIN ERROR(133); TYPIND := 1 END
                        END;
                        CASE LOP OF
                          LTOP: GEN2(53(*LES*),TYPIND,LSIZE);
                          LEOP: GEN2(52(*LEQ*),TYPIND,LSIZE);
                          GTOP: GEN2(49(*GRT*),TYPIND,LSIZE);
                          GEOP: GEN2(48(*GEQ*),TYPIND,LSIZE);
                          NEOP: GEN2(55(*NEQ*),TYPIND,LSIZE);
                          EQOP: GEN2(47(*EQU*),TYPIND,LSIZE)
                        END
                      END
                    ELSE ERROR(129)
                  END;
              GATTR.TYPTR := BOOLPTR; GATTR.KIND := EXPR
            END (*SY = RELOP*)
        END (*EXPRESSION*) ;