// BCAE3.bcpl - BCPL Compiler -- Part 3 of CAE. // Copyright Xerox Corporation 1980 // Last modified on Sun 15 Oct 72 1929.16 by jec. // Swinehart, 5-10-77: docase exp // Rdef Read a definition, returning the node thus produced. // Rcom Read a command. // Rselect Read a switchon block. get "bcaex" let Rdef() = valof [ let A, B = 0, 0 and Thisline = LinePtr() let N = Rnamelist() let M = 0 switchon Symb into // What comes after the name list? [ case RBRA: // A name. It is a function or routine definition. unless (H1!N & TypeMask) eq LOCAL do [ CAEskip(15); goto DefErr ] H1!N = (H1!N & NameMask) + LABEL Nextsymb() if Symb eq NAME % Symb eq NIL do A = Rnamelist() // Formal params if Symb eq SEMICOLON do Nextsymb() if Symb ne RKET do [ unless Symb eq NUMARGS do [ CAEskip(15); goto DefErr ] Nextsymb() M = Rnamelist() unless (H1!M & TypeMask) eq LOCAL do [ CAEskip(15); goto DefErr ] ] unless Symb eq RKET do [ CAEskip(15); goto DefErr ] Nextsymb() if Symb eq BE do // It"s a routine definition. [ Nextsymb() B = Rcom(Rcom) A = List7(RTDEF, N, A, B, 0, 0, M) endcase ] if Symb eq ASS do // It"s a function definition. [ Nextsymb() B = Rexp(0) A = List7(FNDEF, N, A, B, 0, 0, M) endcase ] CAEskip(15) DefErr: B = Rcom(Rcom) A = List6(RTDEF, N, A, B, 0, 0) endcase case ASS: Nextsymb() A = Rexp(0) A = List4(VALDEF, N, A, 0) // Extra cell to hold count in Trans. endcase default: CAEskip(17) ] A = List3(LINE, Thisline, A) while Symb eq SEMICOLON do Nextsymb() if Symb eq AND do [ Nextsymb() if Symb eq LET do Nextsymb() B = Rdef() resultis List3(AND, A, B) ] resultis A ] and Rcom(Nextfn) = valof [ let A, B, C, Op = nil, nil, nil, nil let Thisline = LinePtr() switchon Symb into [ default: resultis 0 case NAME: case NUMBER: case STRINGCONST: case CHARCONST: case NOT: case SELECTON: case NIL: case TRUE: case FALSE: case LV: case RV: case RBRA: case VALOF: case PLUS: case MINUS: case OFFSET: case SIZE: // these are all the symbols which can start an expression A = Rexp(0) if Symb eq ASS do [ Nextsymb() B = Rexp(0) A = List3(ASS, A, B) endcase ] if Symb eq COLON do [ unless (A & NameBit) ne 0 do CAEreport(18) A = List2((A & NameMask) + LABEL, 0) Nextsymb() B = Nextfn(Nextfn) A = List5(COLON, A, B, 0, 0) // Last cells hold label numbers endcase ] if H1!A eq FNAP do [ H1!A = RTAP; endcase ] CAEskip(19) endcase case GOTO: case RESULTIS: case DOCASE: Op = Symb Nextsymb() A = Rexp(0) A = List2(Op, A) endcase case IF: case UNLESS: case WHILE: case UNTIL: Op = Symb Nextsymb() A = Rexp(0) while Symb eq SEMICOLON do Nextsymb() test Symb eq DO then Nextsymb() or CAEskip(20) B = Rcom(Rcom) A = List3(Op, A, B) endcase case TEST: Nextsymb() A = Rexp(0) while Symb eq SEMICOLON do Nextsymb() test Symb eq IFNOT then [ Nextsymb() C = Rcom(Rcom) while Symb eq SEMICOLON do Nextsymb() test Symb eq IFSO then Nextsymb() or CAEskip(20) B = Rcom(Rcom) ] or test Symb eq DO % Symb eq IFSO then [ Nextsymb() B = Rcom(Rcom) while Symb eq SEMICOLON do Nextsymb() test Symb eq OR % Symb eq IFNOT then Nextsymb() or CAEskip(20) C = Rcom(Rcom) ] or [ CAEskip(20) A, B = 0, 0 ] A = List4(TEST, A, B, C) endcase case FOR: [ Nextsymb() A, B = 0, 0 let L, U, S = 0, 0, 0 unless Symb eq NAME do [ CAEskip(21); goto ForErr ] A = List2(V!0 + LOCAL, 0) Nextsymb() unless Symb eq ASS do [ CAEskip(21); goto ForErr ] Nextsymb() L = Rexp(0) test Symb eq BY then [ Nextsymb() S = Rexp(0) unless Symb eq TO do [ CAEskip(22); goto ForErr ] Nextsymb() U = Rexp(0) ] or [ unless Symb eq TO do [ CAEskip(22); goto ForErr ] Nextsymb() U = Rexp(0) if Symb eq BY do [ Nextsymb(); S = Rexp(0) ] ] ForErr: while Symb eq SEMICOLON do Nextsymb() test Symb eq DO then Nextsymb() or CAEskip(20) B = Rcom(Rcom) A = List6(FOR, A, L, U, S, B) endcase ] case ENDCASE: case LOOP: case BREAK: case FINISH: case ABORT: case RETURN: A = List1(Symb) Nextsymb() endcase case SWITCHON: Op = Symb Nextsymb() A = Rexp(0) while Symb eq SEMICOLON do Nextsymb() test Symb eq INTO then Nextsymb() or CAEskip(11) while Symb eq SEMICOLON do Nextsymb() unless Symb eq SECTBRA do CAEskip(12) B = Rblock() A = List3(Op, A, B) endcase case CASE: Nextsymb() A = Rexp(0) test Symb eq TO // Case label with limits? then [ Nextsymb(); C = Rexp(0) ] or C = 0 test Symb eq COLON then Nextsymb() or CAEskip(23) B = Nextfn(Nextfn) A = C eq 0 ? List4(CASE, A, B, Thisline), List5(CASETO, A, C, B, Thisline) endcase case DEFAULT: Nextsymb() test Symb eq COLON then Nextsymb() or CAEskip(23) A = Nextfn(Nextfn) A = List2(DEFAULT, A) endcase case SECTBRA: A = Rblock() endcase case DO: case OR: case IFSO: case IFNOT: case INTO: CAEreport(25) Nextsymb() A = Nextfn(Nextfn) endcase ] L: switchon Symb into [ default: resultis List3(LINE, Thisline, A) case REPEAT: Nextsymb() A = List2(REPEAT, A) goto L case REPEATWHILE: case REPEATUNTIL: [ Op = Symb Nextsymb() B = Rexp(0) A = List3(Op, A, B) goto L ] ] ] and Rselect(ExpOK) = valof [ let a, b = nil, nil let ThisLine = LinePtr() if Symb eq DEFAULT do [ Nextsymb() test Symb eq COLON then Nextsymb() or CAEskip(23) a = Rselect(true) resultis List3(LINE, ThisLine, List2(DEFAULT, a)) ] if Symb eq CASE do [ let c = 0 Nextsymb() a = Rexp(0) if Symb eq TO do [ Nextsymb(); c = Rexp(0) ] // Case label with limits. test Symb eq COLON then Nextsymb() or CAEskip(23) b = Rselect(true) a = c eq 0 ? List4(CASE, a, b, ThisLine), List5(CASETO, a, c, b, ThisLine) resultis List3(LINE, ThisLine, a) ] unless ExpOK do CAEreport(24) a = Rexp(0) a = List2(RESULTIS, a) unless Symb eq SEMICOLON resultis List3(LINE, ThisLine, a) Nextsymb() b = Rselect(false) a = List3(SEQ, a, b) resultis List3(LINE, ThisLine, a) ]