// BCAE0.bcpl - BCPL Compiler -- CAE Main Program.
// Copyright Xerox Corporation 1980
// Swinehart, 5-10-77: docase exp
// last modified by Butterfield, January 25, 1979 2:09 PM
// - Nextsymb, add END - 1/25/79
// ConstructTree Construct the AE-tree.
// Nextsymb Read the LEX file for the next lexeme
// CAEskip Skip over command after an error
// LinePtr Get the last line pointer read by Nextsymb
// CAEreport Error report for CAE.
get "bcaex"
external InitToRead
static // Scalars used in CAE.
[ TRUENODE = nil // Tree node to hold (TRUE, true).
FALSENODE = nil // ditto false
NILNODE = nil // ditto nil
ERRORNAME = nil // Dummy name used to recover from errors.
ERRORNODE = nil // Dummy node for undefined names
ZERONODE = nil // A useful node consisting of (NUMBER,0)
NULLQUALNODE = nil // For qualname errors
TempV = nil // Temp vector for EXT, etc. in Readblockbody
]
let ConstructTree() be // Translate the source code
[ if SWDebug do WriteS("CAE*n")
let v = vec Vmax; V = v // Nextsymb reads names and numbers and strings here.
let v = vec TempT; TempV = v
Tree = Newvec(0) // The initial tree location
TRUENODE = List2(TRUE, true) // Various useful nodes
FALSENODE = List2(FALSE, false)
NILNODE = List2(NIL, 0)
ZERONODE = List2(NUMBER,0)
ERRORNAME = 0
ERRORNODE = List2(ERRORNAME + LABEL, 0)
NULLQUALNODE = List3(0, WordSizeOb, 0)
ResetStream(LexStream, $l) // Reopen the LEX file for reading
InitToRead(LexStream)
Curline = 0
Nextsymb()
rv Tree = Readblockbody() // DO THE WORK.
unless Symb eq END do CAEreport(0)
CloseTemp(LexStream, $l) // Close the LEX file
]
and CAEreport(n) be
[ Ostream = ErrorStream
WW($*n)
let w = WriteLines(Curline, -1, 2)
if not w do unless SWHelp % SWDebug return
let m = selecton n into
[ default: 0
case 0: "END OF SOURCE TEXT NOT REACHED*n*t(POSSIBLY DUE TO PREVIOUS ERROR)"
case 1: "ILLEGAL EXPRESSION IN DECLARATION"
case 2: "ILLEGAL EXPRESSION"
case 3: "TOO MANY NAMES IN DECLARATION"
case 4: "DECLARATION IMPROPERLY TERMINATED"
case 5: "TABLE NOT FOLLOWED BY [ "
case 6: "END OF SOURCE TEXT REACHED -- CLOSING ] EXPECTED"
case 7: "CLOSING ] EXPECTED"
case 8: "NAME EXPECTED"
case 9: "MISSING COMMA"
case 10: "ILLEGAL STATEMENT"
case 11: "ILLEGAL EXPRESSION IN SWITCH"
case 12: "SWITCH NOT FOLLOWED BY [ "
case 13: "ILLEGAL ARGUMENT LIST"
case 14: "ILLEGAL CONDITIONAL EXPRESSION"
case 15: "ILLEGAL PROCEDURE DECLARATION"
case 16: "PROCEDURE BODY EXPECTED"
case 17: "ILLEGAL DECLARATION"
case 18: "ILLEGAL LABEL"
case 19: "ILLEGAL STATEMENT"
case 20: "CONDITIONAL CLAUSE IMPROPERLY TERMINATED"
case 21: "ILLEGAL FOR CLAUSE"
case 22: "FOR CLAUSE IMPROPERLY TERMINATED"
case 23: "CASE LABEL IMPROPERLY TERMINATED"
case 24: "NEXT CASE EXPECTED IN SELECTON EXPRESSION"
case 25: "DO, THEN, IFSO, IFNOT, INTO OUT OF CONTEXT"
case 26: "AND OUT OF CONTEXT"
case 27: "TABLE TOO BIG"
case 28: "OPENING [ EXPECTED"
]
BCPLreport(n, m)
if SWHelp do Help("CAE REPORT")
if n le 0 goto Abort
Ostream = OutputStream
]
and Nextsymb() be // Read the next lexeme from the LEX file
[ let n = nil
L: if SWCaeTrace do [ WriteS("*t*******s") ]
Readch(LexStream, lv Symb) // The lexeme symbol
switchon Symb into
[ case NAME:
Readaddr(LexStream, lv V!0)
if SWCaeTrace do
[ WriteS("NAME "); WriteO(V!0) ]
endcase
case LINE:
Readaddr(LexStream, lv Curline)
if SWCaeTrace do
[ WriteS("LINE "); WriteO(Curline); if SWList do WW($*n) ]
if SWList do
[ if not SWCaeTrace do [ WriteO(Curline); WW($*s) ]
WriteLine(Curline) ]
goto L
case END:
Readaddr(LexStream, lv V!0)
if SWCaeTrace do
[ WriteS("END "); WriteO(V!0) ]
endcase
case NUMBER:
case CHARCONST:
Readword(LexStream, lv V!0)
if SWCaeTrace do
[ WriteN(Symb); WW($*s); WriteO(V!0) ]
endcase
case NAMEBRA:
case NAMEKET:
case STRINGCONST:
Readword(LexStream, lv V!0)
for i = 1 to Length(V)/Bytesperword do Readword(LexStream, lv V!i)
test Symb eq NAMEBRA
then Symb = SECTBRA
or if Symb eq NAMEKET
then Symb = SECTKET
if SWCaeTrace do
[ WriteN(Symb); WW($*s); WriteS(V) ]
endcase
case SECTBRA:
case SECTKET:
V!0 = 0
if SWCaeTrace do
[ WriteN(Symb) ]
endcase
default:
if SWCaeTrace do
[ WriteN(Symb) ]
endcase
]
if SWCaeTrace do WW($*n)
]
and CAEskip(n) = valof
[ CAEreport(n)
switchon Symb into
[ case SEMICOLON: case SECTKET: case END:
resultis true // We are at the end of a command
case SECTBRA:
case LET: case AND: case STATIC: case EXT: case MANIFEST:
case IF: case UNLESS: case WHILE: case UNTIL:
case TEST: case FOR:
case GOTO: case SWITCHON: case CASE: case DEFAULT:
case BREAK: case LOOP: case ENDCASE:
case RETURN: case RESULTIS: case FINISH: case ABORT:
case DOCASE:
resultis false // We are at the beginning of a command
default: Nextsymb()
] repeat
]
and LinePtr() = Curline // Retrieve the last line pointer seen by Nextsymb