// BCAE2.bcpl - BCPL Compiler -- Part 2 of CAE.
// Copyright Xerox Corporation 1980
//  Last modified on Sat 28 Oct 72 0028.04 by  jec.
//  Paxton, 9-14-78: unsigned compares

//	Rexp	The main expression reader.

get "bcaex"

let Rexp(n) = valof
 [  let A, B, C, Op = nil, nil, nil, nil

    if Symb eq NAME do   // This is the usual case, so give it fast service.
     [  A = V!0 + NameBit; Nextsymb()
	goto L
      ]

    //  Read the next operand, and store it into A.
    switchon Symb into   //  Branch on the leading operand of the expression.
     [  default:
	    CAEskip(2)
	    resultis List2(NUMBER, 0)

	case STRINGCONST:
	    A = Newvec(1 + Length(V)/Bytesperword)
	    A!0 = STRINGCONST
	    for k = 0 to Length(V)/Bytesperword do A!(k+1) = V!k
	    Nextsymb()
	    endcase

	case CHARCONST:
	    A = List2(CHARCONST, V!0)
	    Nextsymb()
	    endcase

	case NUMBER:
	    A = List2(NUMBER, V!0)
	    Nextsymb()
	    endcase

	case NIL:
	    A = NILNODE; Nextsymb(); endcase
	case TRUE:
	    A = TRUENODE; Nextsymb(); endcase
	case FALSE:
	    A = FALSENODE; Nextsymb(); endcase

	case RBRA:
	    Nextsymb()
	    A = Rexp(0)
	    test Symb eq RKET then Nextsymb()
	    or [ CAEskip(2)
		 resultis A
		]
	    endcase

	case VALOF:
	    Nextsymb()
	    A = Rcom(Rcom)
	    A = List2(VALOF, A)
	    endcase  

	case TABLE:
	 [  Nextsymb()
	    A = Rtable()
	    endcase
	  ]

	case SELECTON:
	 [  Nextsymb()
	    A = Rexp(0)
	    while Symb eq SEMICOLON do Nextsymb()
	    test Symb eq INTO 
	    then Nextsymb()
	    or   CAEskip(11)
	    let V1 = 0
	    while Symb eq SEMICOLON do Nextsymb()
	    test Symb eq SECTBRA
	    ifnot CAEskip(12)
	    ifso  [  if V!0 ne 0 do
			[ V1 = Newvec(Length(V)/Bytesperword)
		          for k = 0 to Length(V)/Bytesperword do V1!k = V!k
			]
		      Nextsymb()
		    ]
	    B = Rselect(false)
	    test  Symb eq SECTKET
	    ifso  if EqVec(V1) do Nextsymb()
	    ifnot CAEskip(7)
	    A = List3(SWITCHON, A, B)
	    A = List2(VALOF, A)
	    endcase
	  ]

	case SIZE:   //  Size of a structure item.
	case OFFSET:   //  Offset of a structure item
	    Op = Symb
	    A = Rqualname(2)
	    H1!A = Op
	    H2!A = 0
	    endcase

	case LV: case RV:
	    Op = Symb
	    Nextsymb()
	    A = Rexp(35)
	    A = List2(Op, A)
	    endcase

	case PLUS:
	    Nextsymb()
	    A = Rexp(35)
	    endcase

	case MINUS:
	    Nextsymb()
	    A = Rexp(35)
	    A = List2(NEG, A)
	    endcase

	case VEC:
	    Nextsymb()
	    A = Rexp(12)
	    A = List2(VEC, A)
	    endcase

	case NOT:
	    Nextsymb()
	    A = Rexp(25)
	    A = List2(NOT, A)
	    endcase

     ]

  L:  //  An operand has been read.  Now look at the next operator.

    switchon Symb into
     [  default:
	    resultis A

	case RBRA:
	    Nextsymb()
	    test  Symb eq RKET   //  Have empty parentheses been scanned?
	    ifso  [ B = 0; Nextsymb() ]   //  Yes.
	    ifnot [ B = Rexp(0)
		    test Symb eq RKET
		    then Nextsymb()
		    or   [ CAEskip(13)
			   resultis List3(FNAP, A, B)
			 ]
		  ]
	    A = List3(FNAP, A, B)
	    goto L

	case VECAP:
	    if n ge 40 resultis A
	    Nextsymb()
	    B = Rexp(40)
	    A = List3(VECAP, A, B)
	    goto L

	case HEFALUMP:
	    A = List2(RV, A)
	    Symb = RIGHTLUMP
	case LEFTLUMP:
	case RIGHTLUMP:
	    if n ge 38 resultis A
	    Op = Symb
	    B = Rqualname(3)
	    H1!B = Op
	    H2!B = A
	    H3!B = 0
	    A = B
	    goto L

	case DIV:  case REM:
	case MULT:
	case LSHIFT: case RSHIFT:
	    if n ge 35 resultis A
	    Op = Symb
	    Nextsymb()
	    B = Rexp(34)
	    A = List3(Op, A, B)
	    goto L

	case PLUS:
	case MINUS:
	    if n ge 34 resultis A
	    Op = Symb
	    Nextsymb()
	    B = Rexp(34)
	    A = List3(Op, A, B)
	    goto L

	case EQ: case NE:
	case LS: case LE:
	case GR: case GE:
	case ULS: case ULE:
	case UGR: case UGE:
	    if n ge 30 resultis A
	    Op = Symb
	    Nextsymb()
	    B = Rexp(30)
	    A = List3(Op, A, B)
	    goto L

	case LOGAND:
	    if n ge 24 resultis A
	    Nextsymb()
	    B = Rexp(23)
	    A = List3(LOGAND, A, B)
	    goto L

	case LOGOR:
	    if n ge 23 resultis A
	    Nextsymb()
	    B = Rexp(22)
	    A = List3(LOGOR, A, B)
	    goto L

	case EQV:
	case NEQV:
	    if n ge 22 resultis A
	    Op = Symb
	    Nextsymb()
	    B = Rexp(22)
	    A = List3(Op, A, B)
	    goto L

	case COND:
	    if n ge 13 resultis A
	    Nextsymb()
	    B = Rexp(12)
	    test Symb eq COMMA then Nextsymb()
	    or   [ CAEskip(14)
		   resultis A
		 ]
	    C = Rexp(12)
	    A = List4(COND, A, B, C)
	    goto L

	case COMMA:
	    if n ge 12 resultis A
	    Nextsymb()
	    B = Rexp(11)
	    A = List3(COMMA, A, B)
	    goto L
      ]
  ]