GGParseInImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Last edited by Bier on January 6, 1986 11:33:00 pm PST
Contents: Routines for reading gargoyle data structures from a stream. Stolen from Solidviews Solidmodeler TFI3d.mesa.
DIRECTORY
Convert, GGBasicTypes, GGParseIn, Imager, ImagerColor, ImagerTransformation, IO, RefText, Rope;
GGParseInImpl: CEDAR PROGRAM
IMPORTS Convert, Imager, ImagerColor, ImagerTransformation, IO, RefText, Rope
EXPORTS GGParseIn =
BEGIN
RopeNotOnTop: PUBLIC SIGNAL [position: NAT, wasThere: Rope.ROPE, notThere: Rope.ROPE] = CODE;
Color: TYPE = Imager.Color;
Point: TYPE = GGBasicTypes.Point;
ReadBlank: PUBLIC PROC [f: IO.STREAM] = {
Reads, <SPACE>'s, <CR>'s, and <TAB>'s until something else is encountered. Doesn't mind if no white space characters are found. Treats comments as white space.
[] ← IO.SkipWhitespace[f, TRUE];
};
ReadWhiteSpace: PUBLIC PROC [f: IO.STREAM] = {
Reads, <SPACE>'s, <CR>'s, and <TAB>'s until something else is encountered. Signals RopeNotOnTop if no white space characters are found.
WhiteSpaceProc: SAFE PROC [char: CHAR] RETURNS [IO.CharClass] = TRUSTED {
SELECT char FROM
IO.TAB => RETURN [other];
IO.CR =>RETURN [other];
IO.SP => RETURN [other];
ENDCASE => RETURN [break];
};
whiteSpace: Rope.ROPE;
end: BOOLFALSE;
[whiteSpace, ----] ← IO.GetTokenRope[f, WhiteSpaceProc
!IO.EndOfStream => {end ← TRUE; CONTINUE}];
IF end OR Rope.Size[whiteSpace] = 0 THEN SIGNAL RopeNotOnTop[IO.GetIndex[f], "null", "<whitespace>"];
};
ReadHorizontalBlank: PUBLIC PROC [f: IO.STREAM] RETURNS [good: BOOL] = {
Reads <SPACE>'s, and <TABS>'s until something else is encountered. Returns good = FALSE if a CR is encountered before anything else
HorizontalBlankProc: SAFE PROC [char: CHAR] RETURNS [IO.CharClass] = TRUSTED {
SELECT char FROM
IO.TAB, IO.SP => RETURN [other];
ENDCASE => RETURN [break];
};
whiteSpace: Rope.ROPE;
c: CHAR;
end: BOOLFALSE;
good ← TRUE;
[whiteSpace, ----] ← IO.GetTokenRope[f, HorizontalBlankProc
!IO.EndOfStream => {end ← TRUE; CONTINUE}];
IF end THEN {good ← FALSE; RETURN};
c ← Rope.Fetch[whiteSpace, 0];
SELECT c FROM
IO.CR => {good ← FALSE; RETURN};
IO.TAB, IO.SP => {good ← TRUE; RETURN};
ENDCASE => {good ← TRUE; IO.Backup[f, c]; RETURN};
};
ReadWord: PUBLIC PROC [f: IO.STREAM] RETURNS [word: Rope.ROPE] = {
Used to read in a rope which is data.
WordBreakProc: SAFE PROC [char: CHAR] RETURNS [IO.CharClass] = CHECKED {
SELECT char FROM
IO.TAB => RETURN [break];
IO.CR =>RETURN [break];
IO.SP => RETURN [break];
', => RETURN [break];
'] => RETURN [break];
') => RETURN [break];
ENDCASE => RETURN [other];
};
[word, ----] ← IO.GetTokenRope[f, WordBreakProc
!IO.EndOfStream => {word ← NIL; CONTINUE}];
};
ReadColorToken: PUBLIC PROC [f: IO.STREAM] RETURNS [word: Rope.ROPE] = {
Reads a rope until <SPACE>, <CR> or <TAB> are encountered.
ColorBreakProc: SAFE PROC [char: CHAR] RETURNS [IO.CharClass] = CHECKED {
SELECT char FROM
IO.TAB => RETURN [break];
IO.CR =>RETURN [break];
IO.SP => RETURN [break];
ENDCASE => RETURN [other];
};
[word, ----] ← IO.GetTokenRope[f, ColorBreakProc
!IO.EndOfStream => {word ← NIL; CONTINUE}];
};
ReadBlankAndWord: PUBLIC PROC [f: IO.STREAM] RETURNS [word: Rope.ROPE] = {
A convenience function. Equivalent to ReadBlank[f]; word ← ReadWord[f];
ReadBlank[f];
word ← ReadWord[f];
};
ReadBlankAndColor: PUBLIC PROC [f: IO.STREAM] RETURNS [word: Rope.ROPE] = {
ReadBlank[f];
word ← ReadColorToken[f];
};
ReadRope: PUBLIC PROC [f: IO.STREAM, rope: Rope.ROPE] = {
Removes the given rope from the top of the stream. Used to remove formatting words and phrases from 3d files. We are not interested in these strings but only in the data in between them.
Signals RopeNotOnTop if some other rope is on top.
c: CHAR;
endofstream: BOOLFALSE;
FOR i: INT IN[1..Rope.Length[rope]] DO
c ← IO.GetChar[f
! IO.EndOfStream => {endofstream ← TRUE; CONTINUE}];
IF endofstream THEN
SIGNAL RopeNotOnTop [IO.GetIndex[f], NIL, rope];
IF NOT c = Rope.Fetch[rope,i-1] THEN
SIGNAL RopeNotOnTop [IO.GetIndex[f], Rope.FromChar[c], rope];
ENDLOOP;
};
ReadBlankAndRope: PUBLIC PROC [f: IO.STREAM, rope: Rope.ROPE] = {
ReadBlank[f];
ReadRope[f, rope];
};
ReadNAT: PUBLIC PROC [f: IO.STREAM] RETURNS [n: NAT] = {
Reads digits up to the next ], <CR>, <SPACE>. Leaves these terminators on the stream.
NATBreakProc: SAFE PROC [char: CHAR] RETURNS [IO.CharClass] = TRUSTED {
SELECT char FROM
'], IO.CR, IO.SP, '., ',, ': => RETURN [break];
ENDCASE => RETURN [other];
};
end: BOOLFALSE;
intRope: Rope.ROPE;
[intRope, ----] ← IO.GetTokenRope[f, NATBreakProc
!IO.EndOfStream => {end ← TRUE; CONTINUE}];
IF end THEN {n ← 1; RETURN};
n ← Convert.IntFromRope[intRope];
};
ReadBlankAndNAT: PUBLIC PROC [f: IO.STREAM] RETURNS [n: NAT] = {
A convenience function. Equivalent to ReadBlank[f]; n ← ReadNAT[f];
ReadBlank[f];
n ← ReadNAT[f];
};
ReadColor: PUBLIC PROC [f: IO.STREAM] RETURNS [color: Color] = {
s: IO.STREAM;
r, g, b: REAL;
word: Rope.ROPE ← ReadBlankAndColor[f];
IF Rope.Equal[word, "none"] THEN RETURN[NIL];
s ← IO.RIS[word, colorStream];
ReadChar[s, '[];
r ← ReadBlankAndReal[s];
ReadChar[s, ',];
g ← ReadBlankAndReal[s];
ReadChar[s, ',];
b ← ReadBlankAndReal[s];
ReadChar[s, ']];
color ← ImagerColor.ColorFromRGB[[r, g, b]];
IF ImagerColor.GrayFromColor[NARROW[color]]=1.0 THEN color ← Imager.black; -- "process black"
}; -- end of ReadColor
ReadStrokeEnd: PUBLIC PROC [f: IO.STREAM] RETURNS [strokeEnd: Imager.StrokeEnd] = {
endName: Rope.ROPE ← ReadBlankAndWord[f];
SELECT TRUE FROM
Rope.Equal[endName, "square", TRUE] => strokeEnd ← square;
Rope.Equal[endName, "butt", TRUE] => strokeEnd ← butt;
Rope.Equal[endName, "round", TRUE] => strokeEnd ← round;
ENDCASE => ERROR;
};
ReadPoint: PUBLIC PROC [f: IO.STREAM] RETURNS [point: Point] = {
Assumes the next rope on the stream will be of the form "[<real1>,<real2>]".
ReadRope[f, "["];
point.x ← ReadBlankAndReal[f];
ReadRope[f, ","];
point.y ← ReadBlankAndReal[f];
ReadRope[f, "]"];
};
ReadChar: PUBLIC PROC [f: IO.STREAM, c: CHAR] = {
streamC: CHARIO.GetChar[f];
IF NOT c = streamC THEN SIGNAL RopeNotOnTop[IO.GetIndex[f], Rope.FromChar[streamC], Rope.FromChar[c]];
};
ReadKeyWord: PUBLIC PROC [f: IO.STREAM] RETURNS [keyWord: Rope.ROPE, good: BOOL] = {
Reads a rope until a ':' or <CR> are encountered. If CR is encountered first, then good is FALSE since ":" is expected after a keyword.
KeyWordBreakProc: SAFE PROC [char: CHAR] RETURNS [IO.CharClass] = CHECKED {
SELECT char FROM
IO.CR =>RETURN [break];
': => RETURN [break];
ENDCASE => RETURN [other];
};
end: BOOLFALSE;
nextChar: Rope.ROPE;
[keyWord, ----] ← IO.GetTokenRope[f, KeyWordBreakProc
!IO.EndOfStream => {end ← TRUE; CONTINUE}];
IF end THEN {good ← FALSE; keyWord ← NIL; RETURN};
[nextChar, ----] ← IO.GetTokenRope[f, KeyWordBreakProc
!IO.EndOfStream => {end ← TRUE; CONTINUE}];
IF end THEN {good ← FALSE; RETURN};
good ← Rope.Equal[nextChar, ":", TRUE];
};
ReadLine: PUBLIC PROC [f: IO.STREAM] RETURNS [line: Rope.ROPE] = {
Reads a rope UNTIL <CR> is encountered.
LineBreakProc: SAFE PROC [char: CHAR] RETURNS [IO.CharClass] = CHECKED {
SELECT char FROM
IO.CR =>RETURN [break];
ENDCASE => RETURN [other];
};
end: BOOLFALSE;
[line, ----] ← IO.GetTokenRope[f, LineBreakProc
!IO.EndOfStream => {end ← TRUE; CONTINUE}];
IF end THEN {line ← NIL; RETURN};
[----, ----] ← IO.GetTokenRope[f, LineBreakProc]; -- remove <CR>
};
ReadReal: PUBLIC PROC [f: IO.STREAM] RETURNS [r: REAL] = {
Reads digits up to the next ), ], <CR>, <SPACE> or <COMMA>. Leaves these terminators on the stream.
RealBreakProc: SAFE PROC [char: CHAR] RETURNS [IO.CharClass] = TRUSTED {
SELECT char FROM
'), '], ', => RETURN [break];
IO.CR =>RETURN [break];
IO.SP => RETURN [break];
ENDCASE => RETURN [other];
};
realText, buffer: REF TEXT;
end: BOOLFALSE;
buffer ← RefText.ObtainScratch[50];
[realText, ----] ← IO.GetToken[f, RealBreakProc, buffer
!IO.EndOfStream => {end ← TRUE; CONTINUE}];
IF end THEN {r ← 0.0; RETURN};
IF RefText.Find[realText, ".", 0, FALSE] = -1 THEN realText ← RefText.Append[realText, ".0"];
r ← Convert.RealFromRope[RefText.TrustTextAsRope[realText]];
RefText.ReleaseScratch[buffer];
};
ReadBlankAndReal: PUBLIC PROC [f: IO.STREAM] RETURNS [r: REAL] = {
A convenience function. Equivalent to ReadBlank[f]; r ← ReadReal[f];
ReadBlank[f];
r ← ReadReal[f];
};
ReadBOOL: PUBLIC PROC [f: IO.STREAM] RETURNS [truth: BOOL, good: BOOL] = {
Tries to read TRUE or FALSE from the stream. If it encounters another word, good = FALSE;
BoolBreakProc: SAFE PROC [char: CHAR] RETURNS [IO.CharClass] = TRUSTED {
SELECT char FROM
'], IO.CR, IO.SP, '., ', => RETURN [break];
ENDCASE => RETURN [other];
};
end: BOOLFALSE;
boolRope: Rope.ROPE;
[boolRope, ----] ← IO.GetTokenRope[f, BoolBreakProc
!IO.EndOfStream => {end ← TRUE; CONTINUE}];
IF end THEN {good ← FALSE; truth ← FALSE; RETURN};
good ← TRUE;
IF Rope.Equal[boolRope, "TRUE", TRUE] THEN truth ← TRUE
ELSE IF Rope.Equal[boolRope, "FALSE", TRUE] THEN truth ← FALSE
ELSE {truth ← FALSE; good ← FALSE};
};
ReadListOfRope: PUBLIC PROC [f: IO.STREAM] RETURNS [ropeList: LIST OF Rope.ROPE] = {
RopesOnOneLineOrParenProc: SAFE PROC [char: CHAR] RETURNS [IO.CharClass] = CHECKED {
SELECT char FROM
IO.CR, ') =>RETURN [break];
IO.SP, IO.TAB, ', , '; => RETURN [sepr];
ENDCASE => RETURN [other];
};
rope: Rope.ROPE;
end: BOOLFALSE;
ropeList ← NIL;
WHILE TRUE DO
[rope, ----] ← IO.GetTokenRope[f, RopesOnOneLineOrParenProc
!IO.EndOfStream => {end ← TRUE; CONTINUE}];
IF end OR rope = NIL THEN RETURN;
IF Rope.Equal[rope, Rope.FromChar[IO.CR]] THEN RETURN;
IF Rope.Equal[rope, Rope.FromChar[')]] THEN {
f.Backup[')];
RETURN;
};
ropeList ← AppendRopeToRopeList[rope, ropeList];
ENDLOOP;
};
ReadTransformation: PUBLIC PROC [f: IO.STREAM] RETURNS [transform: ImagerTransformation.Transformation] = {
a, b, c, d, e, g: REAL;
ReadBlankAndRope[f, "["];
a ← ReadBlankAndReal[f];
b ← ReadBlankAndReal[f];
c ← ReadBlankAndReal[f];
d ← ReadBlankAndReal[f];
e ← ReadBlankAndReal[f];
g ← ReadBlankAndReal[f];
ReadBlankAndRope[f, "]"];
transform ← ImagerTransformation.Create[a, b, c, d, e, g];
};
AppendRopeToRopeList: PROC [rope: Rope.ROPE, list: LIST OF Rope.ROPE] RETURNS [LIST OF Rope.ROPE] = {
A copy of List.Nconc1 for LIST OF Rope.ROPE instead of LIST OF REF ANY
z: LIST OF Rope.ROPE ← list;
IF z = NIL THEN RETURN[CONS[rope,NIL]];
UNTIL z.rest = NIL DO z ← z.rest; ENDLOOP;
z.rest ← CONS[rope,NIL];
RETURN[list];
};
colorStream: IO.STREAM;
realNumberStream: IO.STREAM;
Init: PROC [] = {
realNumberStream ← IO.TIS["This string is longer than any real number is likely to be."];
colorStream ← IO.RIS["This string is longer than any color is likely to be."];
};
Init[];
END.