<> <> <> <> <<>> DIRECTORY Atom, Convert, Vector2, IO, RefText, Rope, SessionLog, SlackProcess; SessionLogImpl: CEDAR PROGRAM IMPORTS Atom, Convert, RefText, IO, Rope EXPORTS SessionLog = BEGIN <> EnterAction: PUBLIC PROC [f: IO.STREAM, action: LIST OF REF ANY] = { FOR actionList: LIST OF REF ANY _ action, actionList.rest UNTIL actionList = NIL DO WITH actionList.first SELECT FROM atom: ATOM => f.PutF["%g", [rope[Atom.GetPName[atom]]]]; n: REF INT => f.PutF["%g", [integer[n^]]]; r: REF REAL => f.PutF["%g", [real[r^]]]; c: REF CHAR => f.PutF["'%g", [character[c^]]]; cd: REF CARD => f.PutF["%g", [cardinal[cd^]]]; rope: Rope.ROPE => f.PutF["\"%g\"", [rope[rope]]]; refText: REF TEXT => f.PutF["\"%g\"", [text[refText]]]; refPoint: REF Vector2.VEC => f.PutF["[%g, %g]", [real[refPoint.x]], [real[refPoint.y]]]; ENDCASE => ERROR; IF actionList.rest = NIL THEN f.PutChar[IO.CR] ELSE f.PutChar[IO.SP]; ENDLOOP; }; <> PlayScript: PUBLIC PROC [f: IO.STREAM, clientData: REF ANY, notifyProc: SlackProcess.EventProc] = { endOfStream: BOOL _ FALSE; WHILE NOT endOfStream DO endOfStream _ PlayAction[f, clientData, notifyProc]; ENDLOOP; }; PlayAction: PUBLIC PROC [f: IO.STREAM, clientData: REF ANY, notifyProc: SlackProcess.EventProc] RETURNS [endOfStream: BOOL _ FALSE] = { c: CHAR; mouseEvent: BOOL; point: Vector2.VEC; good: BOOL; token: REF ANY; action: LIST OF REF ANY; ReadBlank[f]; <> c _ IO.GetChar[f !IO.EndOfStream => {endOfStream _ TRUE; CONTINUE}]; IF endOfStream THEN RETURN; IF c = '* THEN { atom: ATOM; refPoint: REF Vector2.VEC; good _ ReadHorizontalBlank[f]; IF NOT good THEN ERROR; point _ ReadPoint[f]; refPoint _ NEW[Vector2.VEC _ point]; token _ ReadSpacesAndToken[f]; atom _ NARROW[token]; UNTIL token = $EndOfLine DO token _ ReadSpacesAndToken[f]; ENDLOOP; action _ LIST[atom, refPoint]; } <> ELSE { mouseEvent _ FALSE; IO.Backup[f, c]; token _ $Start; UNTIL token = $EndOfLine DO token _ ReadSpacesAndToken[f]; IF token = $EndOfLine THEN LOOP; action _ AppendToken[token, action] ENDLOOP; }; notifyProc[action, clientData]; }; ReadSpacesAndToken: PUBLIC PROC [f: IO.STREAM] RETURNS [token: REF ANY] = { word: Rope.ROPE; good: BOOL; int: INT; real: REAL; firstChar: CHAR; good _ ReadHorizontalBlank[f]; IF NOT good THEN { token _ $EndOfLine; RETURN; }; firstChar _ IO.PeekChar[f]; SELECT TRUE FROM firstChar = '" => { token _ f.GetRopeLiteral[]; }; firstChar = '' => { [] _ f.GetChar[]; token _ NEW[CHAR _ f.GetChar[]]; }; firstChar = '[ => { point: Vector2.VEC _ ReadPoint[f]; token _ NEW[Vector2.VEC _ point]; }; IsDigitOrOp[firstChar] => { word _ ReadBlankAndWord[f]; IF Rope.Find[word, "."] = -1 THEN { -- an integer int _ IO.GetInt[IO.RIS[word]]; token _ NEW[INT _ int]; } ELSE { real _ IO.GetReal[IO.RIS[word]]; token _ NEW[REAL _ real]; }; }; ENDCASE => { word _ ReadBlankAndWord[f]; token _ Atom.MakeAtom[word]; }; }; ReadLine: PROC [f: IO.STREAM] RETURNS [line: Rope.ROPE] = { < is encountered.>> LineBreakProc: SAFE PROC [char: CHAR] RETURNS [IO.CharClass] = CHECKED { SELECT char FROM IO.CR =>RETURN [break]; ENDCASE => RETURN [other]; }; end: BOOL _ FALSE; [line, ----] _ IO.GetTokenRope[f, LineBreakProc !IO.EndOfStream => {end _ TRUE; CONTINUE}]; IF end THEN {line _ NIL; RETURN}; }; ReadSpaceAndChar: PROC [f: IO.STREAM] RETURNS [token: REF ANY] = { c: CHAR; good: BOOL; c _ IO.GetChar[f !IO.EndOfStream => ERROR]; c _ IO.GetChar[f !IO.EndOfStream => ERROR]; good _ ReadHorizontalBlank[f]; IF good THEN ERROR; token _ NEW[CHAR _ c]; }; AppendToken: PROC [token: REF ANY, list: LIST OF REF ANY] RETURNS [newList: LIST OF REF ANY] = { l: LIST OF REF ANY _ list; IF l = NIL THEN RETURN[LIST[token]]; UNTIL l.rest = NIL DO l _ l.rest ENDLOOP; l.rest _ CONS[token, NIL]; newList _ list; }; IsDigitOrOp: PROC [c: CHAR] RETURNS [BOOL] = { RETURN[c IN ['0..'9] OR c = '- OR c = '+]; }; <> <<>> ReadBlank: PUBLIC PROC [f: IO.STREAM] = { <'s, 's, and '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]; }; ReadHorizontalBlank: PUBLIC PROC [f: IO.STREAM] RETURNS [good: BOOL] = { <'s, and '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: BOOL _ FALSE; 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}; }; <<>> ReadBlankAndReal: PUBLIC PROC [f: IO.STREAM] RETURNS [r: REAL] = { <> ReadBlank[f]; r _ ReadReal[f]; }; ReadReal: PUBLIC PROC [f: IO.STREAM] RETURNS [r: REAL] = { <, or . 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: BOOL _ FALSE; 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]; }; ReadPoint: PUBLIC PROC [f: IO.STREAM] RETURNS [point: Vector2.VEC] = { <,]".>> ReadBlank[f]; ReadRope[f, "["]; point.x _ ReadBlankAndReal[f]; ReadRope[f, ","]; point.y _ ReadBlankAndReal[f]; ReadRope[f, "]"]; }; SyntaxError: PUBLIC SIGNAL [position: NAT, wasThere: Rope.ROPE, notThere: Rope.ROPE] = CODE; ReadRope: PROC [f: IO.STREAM, rope: Rope.ROPE] = { <> <> c: CHAR; endofstream: BOOL _ FALSE; FOR i: INT IN[1..Rope.Length[rope]] DO c _ IO.GetChar[f ! IO.EndOfStream => {endofstream _ TRUE; CONTINUE}]; IF endofstream THEN SIGNAL SyntaxError [IO.GetIndex[f], NIL, rope]; IF NOT c = Rope.Fetch[rope,i-1] THEN SIGNAL SyntaxError [IO.GetIndex[f], Rope.FromChar[c], rope]; ENDLOOP; }; ReadBlankAndWord: PUBLIC PROC [f: IO.STREAM] RETURNS [word: Rope.ROPE] = { ReadBlank[f]; word _ ReadWord[f]; }; ReadWord: PROC [f: IO.STREAM] RETURNS [word: Rope.ROPE] = { <> WordBreakProc: PROC [char: CHAR] RETURNS [IO.CharClass] = { 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}]; }; END.