IPReader.mesa
Token-level interface for reading and writing encoded Interpress masters
Last edited by:
Doug Wyatt, March 8, 1984 5:13:46 pm PST
DIRECTORY
IO USING [STREAM],
IPBasic USING [Op, Rational, Version],
Rope USING [ROPE];
IPReader: CEDAR DEFINITIONS
~ BEGIN OPEN IPBasic;
ROPE: TYPE ~ Rope.ROPE;
STREAM: TYPE ~ IO.STREAM;
ErrorCode:
TYPE ~ {
ok, -- initial value for an ErrorCode
bug, -- implementation bug
unimplemented, -- operation not currently implemented
unknownEncoding, -- the requested encoding is not implemented
illegalHeader, -- invalid header for an Interpress master
illegalStructure, -- the skeleton of the master is malformed
illegalToken, -- a token is malformed
wrongType, -- token to be parsed has the wrong type
overflow, -- numeric overflow while trying to parse a number
closed -- tried to operate on a closed reader
};
Error:
ERROR[code: ErrorCode, explanation:
ROPE ←
NIL];
TokenType:
TYPE ~ {
nil,
op, -- value is token.op
shortNumber, -- value is reader.shortNumber
integer, -- use ReadInt or ReadReal
rational, -- use ReadRational or ReadReal
real, -- use ReadReal
identifier, -- value is reader.text
string, -- value is reader.text (uses Xerox Character Code Standard encoding)
vector, -- use ReadVector
insertfile, -- value is reader.text
comment, -- value is reader.text
annotation, -- value is reader.text
eof -- end of file
};
Token: TYPE ~ RECORD[type: TokenType, op: Op];
nullToken: Token ~ [type: $nil, op: $nil];
Index: TYPE ~ INT; -- a byte position in the master
nullIndex: Index ~ -1;
EncodedVector: TYPE ~ RECORD[stream: STREAM, decompressorName: ROPE ← NIL];
Reader: TYPE ~ REF ReaderRep;
ReaderRep:
TYPE ~
RECORD[
class: Class, -- procedures for reading the encoding
stream: STREAM, -- input stream on the master
index: Index, -- stream index of most recently scanned token
token: Token, -- token type
shortNumber: INTEGER, -- short number value for token
text: REF TEXT, -- text for token
length: INT ← 0, -- sequence data length (used by Xerox encoding)
buffer: REF TEXT -- scratch text buffer
];
Class: TYPE ~ REF ClassRep;
ClassRep:
TYPE ~
RECORD[
encoding: ATOM ←,
getToken: PROC[reader: Reader, flushComments: BOOL ← TRUE] ←,
readInt: PROC[reader: Reader] RETURNS[INT] ←,
readRational: PROC[reader: Reader] RETURNS[Rational] ←,
readReal: PROC[reader: Reader] RETURNS[REAL] ←,
readVector: PROC[reader: Reader] RETURNS[EncodedVector] ←,
finishBody: PROC[reader: Reader] ← NIL
];
Open:
PROC[name:
ROPE]
RETURNS[Reader];
Open the named file, parse the header to determine the encoding, and return a Reader.
Create:
PROC[stream:
STREAM, encoding:
ATOM, version: Version]
RETURNS[Reader];
Create a Reader for the given stream. Starts reading at the current stream index.
Close:
PROC[reader: Reader];
Close the reader's stream and prevent further calls on the reader.
Node: TYPE ~ REF NodeRep;
BodyNode: TYPE ~ REF NodeRep[body];
BlockNode: TYPE ~ REF NodeRep[block];
NodeRep:
TYPE ~
RECORD[
instructions: Index ← nullIndex, -- nullIndex if no instructions
content:
SELECT tag: *
FROM
body => [body: Index],
block => [block: Block],
ENDCASE
];
Block: TYPE ~ REF BlockRep;
BlockRep:
TYPE ~
RECORD[
noPages: BOOL,
preamble: Node,
nodes: SEQUENCE size: NAT OF Node
];
GetSkeleton:
PROC[reader: Reader]
RETURNS[Block];
GetIndex:
PROC[reader: Reader]
RETURNS[Index];
SetIndex:
PROC[reader: Reader, index: Index];
GetToken:
PROC[reader: Reader, flushComments:
BOOL ←
TRUE]
~ INLINE { reader.class.getToken[reader, flushComments] };
ReadInt:
PROC[reader: Reader]
RETURNS[
INT]
~ INLINE { RETURN reader.class.readInt[reader] };
ReadRational:
PROC[reader: Reader]
RETURNS[Rational]
~ INLINE { RETURN reader.class.readRational[reader] };
ReadReal:
PROC[reader: Reader]
RETURNS[
REAL]
~ INLINE { RETURN reader.class.readReal[reader] };
ReadVector:
PROC[reader: Reader]
RETURNS[EncodedVector]
~ INLINE { RETURN reader.class.readVector[reader] };
The first byte from the stream indicates the number of bytes per element.
FinishBody:
PROC[reader: Reader];
Register: PROC[class: Class];
END.