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: ROPENIL];
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: ROPENIL];
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: BOOLTRUE] ←,
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: BOOLTRUE]
~ 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.