<> <<>> <> <> <> <<>> 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]; <> Create: PROC[stream: STREAM, encoding: ATOM, version: Version] RETURNS[Reader]; <> Close: PROC[reader: 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] }; <> FinishBody: PROC[reader: Reader]; Register: PROC[class: Class]; END.