OPEN Convert, Graph; Type: TYPE = {int, real, rope, bool}; RopeArray: TYPE = ARRAY [0..0) OF Rope.ROPE; TypeArray: TYPE = ARRAY [0..0) OF Type; ValueArray: TYPE = ARRAY [0..0) OF IO.Value; ROPE: TYPE = Rope.ROPE; Value: TYPE = IO.Value; STREAM: TYPE = IO.STREAM; Error: SIGNAL[pos: INT, type: Atom, info: ROPE] = CODE; -- Error types may be: -- $UnknownKey: unrecognized keyword in a record. ParseWithKeyProc: TYPE = PROC[stream: IO.STREAM, buffer, token: REF TEXT] RETURNS [stop: BOOL _ FALSE, tokenKind: TokenKind, token: REF TEXT]; ParseWithoutKeyProc: TYPE = PROC[stream: IO.STREAM, buffer: REF TEXT] RETURNS [stop: BOOL _ FALSE, tokenKind: TokenKind, token: REF TEXT]; typeRope: ARRAY [0..4) OF rope Value = ["number", "real number", "string of text enclosed by double quotes", "true or false"]; GetToken: PROC[stream: STREAM] RETURNS [tokenKind: TokenKind, token: REF TEXT] = { buffer: REF TEXT = RefText.ObtainScratch[100]; error: IO.TokenError; [tokenKind: tokenKind, token: token, error: error] _ IO.GetCedarToken[stream, buffer, TRUE]; IF error # none THEN Error[ pos: stream.GetPosition, atom: $GetCedarTokenError, info: SELECT error FROM extendedChar => "extendedChar", numericLiteral, charLiteral, stringLiteral, atomLiteral => "error in parsing indicated type", singleChar => "first non-whitespace char is not legal as first char of token", ENDCASE => "Impossible !? - #1." ]; }; -- GetToken ValueFromNextToken: PROC[line: REF TEXT _ NIL, start: INT _ 0, type: Type _ int, default: Value] RETURNS [end: INT _ 0, value: Value, ok: BOOL _ FALSE] = { c: CHAR; from: INT; negative: BOOL _ FALSE; number: INT _ 0; realNumber: REAL _ 0.0; max: NAT _ line.length; -- skip to the first non-blank char to get the "from" index from _ end _ start; WHILE from < max DO SELECT line[from] FROM <= SP, 140C, DEL => from _ from + 1; ENDCASE => EXIT; ENDLOOP; IF (end _ from) >= max THEN RETURN[]; -- not ok SELECT type FROM int => { c _ line[end]; IF c = '+ OR c = '- THEN { IF c = '- THEN negative _ TRUE; IF (end _ end + 1) = max THEN RETURN[]; -- just the sign }; WHILE (c _ line[end]) IN ['0..'9] DO number _ number*10 + (c - '0); IF (end _ end + 1) = max THEN EXIT; ENDLOOP; RETURN[end, IF negative THEN -number ELSE number, TRUE]; }; -- int real => { c _ line[end]; IF c = '+ OR c = '- THEN { IF c = '- THEN negative _ TRUE; IF (end _ end + 1) = max THEN RETURN[]; -- just the sign }; WHILE (c _ line[end]) IN ['0..'9] DO realNumber _ realNumber*10.0 + Real.Float[c - '0]; IF (end _ end + 1) = max THEN GOTO done; ENDLOOP; IF c = '. THEN { end _ end + 1; IF end = max THEN GOTO done; WHILE c _ text.Fetch[end] IN ['0..'9] DO end _ end + 1; IF end = max THEN GOTO done; ENDLOOP; IF c = 'E OR c = 'e THEN { end _ end + 1; IF end = max THEN GOTO done; WHILE c _ text.Fetch[end] IN ['0..'9] DO end _ end + 1; IF end = max THEN GOTO done; ENDLOOP; }; }; EXITS done => IF type = real THEN { IF negative THEN realNumber _ -realNumber; RETURN[end, realNumber, TRUE]; } ELSE { IF negative THEN number _ -number; RETURN[end, number, TRUE]; }; }; real => { c: CHAR; WHILE (c _ text.Fetch[end]) IN ['0..'9] DO end _ end + 1; IF end = max THEN EXIT; ENDLOOP; SELECT c FROM '. => end _ end + 1; 'e, 'E token _ text.Substr[start, end-start]; }; -- GetTokenFromRope GetValues: PROC[s: IO.STREAM, args, defaults: RopeArray, types: TypeArray, numArgs: INT] RETURNS [values: Values] = { pos: INT _ s.GetPosition; lineRope: ROPE _ ReadUpTo[s, '] ! => Error[PutFR["Can't find the closing square braket ']' starting from %g.", int[pos]]]; lineText: REF TEXT = FromRefText[rope]; len: NAT _ lineText.length; start, end: NAT _ 0; colon: INTEGER _ -1; FOR i: NAT IN [0..lineText.length) DO IF lineText[i] = ': THEN {colon _ i; EXIT}; ENDLOOP; IF colon < 0 THEN { -- no keywords FOR i: INT IN [0..numArgs) DO IF start >= len THEN values[i] _ defaults[i] ELSE [end, values[i], ok] _ ValueFromNextToken[lineText, start, types[i], defaults[i]]; IF NOT ok THEN Error[ PutFR[ "Had difficulty at [%g], parsing %g .... to get the value of argument # %g, which I think should be a %g with default %g.", int[pos + start], rope[lineRope.Substr[0, MIN[len, 20]]], int[i+1], typeRope[i], defaults[i] ]; ]; start _ end + 1; ENDLOOP; } ELSE { keyword: rope Value; values _ defaults; start _ end _ 0; UNTIL start >= len DO [end, keyword, ok] _ ValueFromNextToken[line, start, rope, len]; IF NOT ok THEN Error[ "Had difficulty at [%g] parsing\n %g ....\n to get a keyword.", int[pos + start], rope[rope.Substr[0, MIN[len, 20]]], ]; FOR i: INT IN [0..numArgs) DO IF keyword.Equal[args[i], FALSE] THEN { start _ end + 1; [end, values[i]] _ GetTokenFromRope[line, start, types[i], len]; IF values[i] = NIL THEN values[i] _ defaults[i]; end _ start + 1; EXIT; }; REPEATS FINISHED => Error["Illegal argument."]; ENDLOOP; ENDLOOP; }; }; -- GetValues Parse: PROC[stream: IO.STREAM, var: REF ANY] = { WITH var SELECT FROM t: Text => t_ ParseText ParseRGB: PROC[stream: IO.STREAM] RETURNS [ImagerColor.RGB] = { ParseColors: PROC[stream: IO.STREAM, graph: GRAPH] RETURNS [tokenKind: TokenKind, token: REF TEXT] = { tokenKind: IO.TokenKind; token: REF TEXT; buffer: REF TEXT = RefText.ObtainScratch[100]; error: IO.TokenError; ParseWithKey: ParseWithKeyProc = { UNTIL stop DO rgb: {r, g, b}; c: CHAR; SELECT token[0] FROM 'R, 'r => rgb _ r, 'G, 'g => rgb _ g, 'B, 'b => rgb _ b, ENDCASE => Error[ pos: s.GetPosition[], atom: $UnknownKey info: "`r', `g', or `b' are expected." ]; c _ IO.GetCharLiteral[stream]; [tokenKind: tokenKind, token: token] _ GetToken[stream]; SELECT tokenKind FROM tokenID => [tokenKind, token] _ ParseWithKey[stream, token]; Parse[stream, graph, GetToken[s] hasKeyword _ ParseIndex args: ARRAY [0..4) OF ROPE = ["index", "r", "g", "b"]; defaults: ARRAY [0..4) OF Value = [int[0], real[0.0], real[0.0], real[0.0]]; types: ARRAY [0..4) OF Type = [int, real, real, real]; values: ARRAY [0..4) OF Value _ GetValues[s, args, defaults, types, 4 ! => { msg _ IO.PutFR["Had difficulty processing 'Color' command at pos = [%g].", IO.int[s.GetPosition[]]]; CONTINUE; } ]; graph.color[values[1].value] _ IF msg = NIL THEN SetColor[ viewer: viewer, index: IntFromRope[values[0]], r: RealFromRope[values[1]], g: RealFromRope[values[2]], b: RealFromRope[values[3]] ]; }; -- Color }. –GraphData.mesa, Copyright c 1985 by Xerox Corporation. All rights reserved. Last edited: Sweetsun Chen, October 9, 1985 6:33:27 pm PDT Commands: Color, Font, Label, Text, CrossHair, Target, Grid, Division, Bounds, Auto, CurveSet, X, Y, Names, NameCount, DataSet. position index can not be >= max. -- now lets get the "end" index, by skipping alphanumeric assume stream, var, and key are not nil. Κ j˜JšœΟmœ1™L™ Icode™-—K™KšΟkœ˜J˜J™Jšœžœ˜%Jš œ žœžœžœžœ˜,Jšœ žœžœžœ˜'Jš œ žœžœžœžœ˜,J˜Jšžœžœžœ˜Jšœžœžœ˜Jšžœžœžœžœ˜š œžœžœžœžœ˜7J˜J˜1J˜—JšΟnœžœžœ žœžœžœžœžœžœžœžœžœ˜ŽJšœŸœžœžœ žœžœ žœžœžœžœžœžœžœ˜ŠK™Kšœ žœžœe˜~š œžœžœžœžœ˜RJšœžœžœ˜.Kšœžœ ˜Kšœ5žœžœ˜\šžœžœ˜K˜K˜šœžœž˜Kšœ˜Kšœ]˜]KšœN˜NKšžœ˜ —K˜—Kšœ˜K˜—šŸœžœžœžœ žœ'žœžœžœžœ˜›Kšœžœ˜Kšœžœ˜ Kšœ žœžœ˜Kšœžœ˜Kšœ žœ˜šœžœ˜K™!—K˜KšΟc;˜;Kšœ˜šžœ ž˜šžœ ž˜Kšœžœžœ˜$Kšžœžœ˜—Kšžœ˜—Kšžœžœžœ  ˜/K™Kšœ9™9šžœž˜˜Kšœ˜šžœžœžœ˜Kšžœžœ žœ˜Kšžœžœžœ ˜8K˜—šžœžœ ž˜$K˜Kšžœžœžœ˜#Kšžœ˜—Kš žœžœ žœ žœ žœ˜8K˜ —K˜šœ ˜ Kšœ˜šžœžœžœ˜Kšžœžœ žœ˜Kšžœžœžœ ˜8K˜—šžœžœ ž˜$Kšœ2˜2Kšžœžœžœ˜(Kšžœ˜—šžœžœ˜Kšœ˜Kšžœ žœžœ˜šžœžœ ž˜(K˜Kšžœ žœžœ˜Kšžœ˜——šžœžœžœ˜Kšœ˜Kšžœ žœžœ˜šžœžœ ž˜(K˜Kšžœ žœžœ˜Kšžœ˜K˜—K˜—šž˜šœ˜šžœ žœ˜Kšžœ žœ˜*Kšžœžœ˜K˜—šžœ˜Kšžœ žœ˜"Kšžœžœ˜K˜———Kšœ˜—˜ Kšœžœ˜šžœžœ ž˜*K˜Kšžœ žœžœ˜Kšžœ˜—šžœž˜ K˜K˜—šœ&˜&K˜———Kšœ ˜—K˜š Ÿ œžœžœžœ8žœ˜XKšžœ˜Kšœžœ˜šœ žœ˜!KšœX˜X—Kšœ žœ˜'Kšœžœ˜Kšœ žœ˜Kšœžœ˜šžœžœžœž˜%Kšžœžœ žœ˜+Kšžœ˜—K˜šžœ žœ ˜"šžœžœžœž˜Kšžœžœ˜,KšžœS˜Wšžœžœžœ˜šœ˜KšœŠ˜ŠKšœ˜Kšœžœ ˜'Kšœ ˜ K˜Kšœ˜—K˜—K˜Kšžœ˜—K˜—šžœ˜Kšœ˜K˜K˜šžœž˜Kšœ@˜@šžœžœžœ˜KšœC˜CKšœ˜Kšœžœ ˜#Kšœ˜—šžœžœžœž˜šžœžœžœ˜'K˜Kšœ@˜@Kšžœ žœžœ˜0K˜Kšžœ˜K˜—šž˜Kšžœ˜'—Kšžœ˜—Kšžœ˜—K˜—Kšœ  ˜—K˜š Ÿœžœ žœžœžœžœ˜0Kšœ(™(šžœžœž˜Kšœ˜——K˜Kš Ÿœžœ žœžœžœžœ˜?K˜šŸ œžœ žœžœ žœžœžœžœ˜fKšœ žœžœžœ˜*Jšœžœžœ˜.Jšœžœ ˜J˜šœ"˜"šžœž˜ Kšœ˜Kšœžœ˜šžœ ž˜Kšœ8˜8šžœ ˜K˜K˜K˜&K˜——KšœŸœ ˜K˜K˜——Jšœ8˜8šžœ ž˜Jšœ<˜<—J˜J˜ J˜Jšœžœžœžœ˜6Jšœ žœžœ3˜LJšœžœžœ ˜6šœžœžœ0˜Gšœ˜šœžœB˜JJ˜—Jšžœ˜ Jšœ˜—Jšœ˜—Jšœ ˜ šžœžœžœ ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜J˜—˜ J˜——J˜—…—Ž#Ž