DIRECTORY Ascii USING [Lower], BasicTime USING [GMT, OutOfRange, Pack, Unpacked], Convert, IO, RefText, Rope; IOScanImpl: CEDAR PROGRAM IMPORTS Ascii, BasicTime, Convert, IO, Rope, RefText EXPORTS IO = BEGIN STREAM: TYPE = IO.STREAM; ROPE: TYPE = Rope.ROPE; BreakProc: TYPE = IO.BreakProc; TokenKind: TYPE = IO.TokenKind; GetToken: PUBLIC PROC [stream: STREAM, breakProc: BreakProc, buffer: REF TEXT] RETURNS[token: REF TEXT, charsSkipped: INT] = { quit, include: BOOL _ FALSE; anySeen: BOOL _ FALSE; charsSkipped _ 0; buffer.length _ 0; DO char: CHAR _ stream.GetChar[ ! IO.EndOfStream => IF buffer.length > 0 THEN EXIT ELSE REJECT]; SELECT breakProc[char] FROM break => {include _ NOT anySeen; quit _ TRUE}; sepr => {include _ FALSE; quit _ anySeen }; other => {include _ TRUE; quit _ FALSE; anySeen _ TRUE}; ENDCASE => ERROR; SELECT TRUE FROM include => {buffer _ RefText.InlineAppendChar[buffer, char]; IF quit THEN EXIT}; quit => {stream.Backup[char]; EXIT}; ENDCASE => charsSkipped _ charsSkipped + 1; ENDLOOP; RETURN[buffer, charsSkipped]; }; GetTokenRope: PUBLIC PROC [stream: STREAM, breakProc: BreakProc] RETURNS [token: ROPE, charsSkipped: INT] = { buffer: REF TEXT = RefText.ObtainScratch[100]; { ENABLE UNWIND => RefText.ReleaseScratch[buffer]; tokenText: REF TEXT; [tokenText, charsSkipped] _ GetToken[stream, breakProc, buffer]; token _ Rope.FromRefText[tokenText]; }; RefText.ReleaseScratch[buffer]; RETURN [token, charsSkipped]; }; IDProc: PUBLIC BreakProc = { RETURN[SELECT char FROM IN [IO.NUL .. IO.SP] => sepr, ',, ':, '; => sepr, ENDCASE => other]; }; TokenProc: PUBLIC BreakProc = { RETURN[SELECT char FROM '[, '], '(, '), '{, '}, '", '+, '-, '*, '/, '@, '_ => break, IN [IO.NUL .. IO.SP] => sepr, ',, ':, '; => sepr, ENDCASE => other]; }; GetLine: PUBLIC PROC [stream: STREAM, buffer: REF TEXT] RETURNS [line: REF TEXT] = { buffer.length _ 0; DO char: CHAR _ stream.GetChar[ ! IO.EndOfStream => IF buffer.length > 0 THEN EXIT ELSE REJECT]; IF char # IO.CR THEN buffer _ RefText.InlineAppendChar[buffer, char] ELSE EXIT; ENDLOOP; RETURN [buffer]; }; GetLineRope: PUBLIC PROC [stream: STREAM] RETURNS [line: ROPE] = { buffer: REF TEXT = RefText.ObtainScratch[100]; { ENABLE UNWIND => RefText.ReleaseScratch[buffer]; line _ Rope.FromRefText[GetLine[stream, buffer]]; }; RefText.ReleaseScratch[buffer]; RETURN [line]; }; SkipWhitespace: PUBLIC PROC [stream: STREAM, flushComments: BOOL] RETURNS [charsSkipped: INT] = { char: CHAR; { charsSkipped _ 0; DO char _ stream.GetChar[ ! IO.EndOfStream => GOTO End]; SELECT char FROM IN [IO.NUL .. IO.SP] => charsSkipped _ charsSkipped + 1; '- => { IF NOT flushComments THEN GOTO Backup; char _ stream.GetChar[ ! IO.EndOfStream => {stream.Backup[char]; GOTO End}]; IF char # '- THEN { -- false alarm, first minus is not start of comment stream.Backup[char]; char _ '-; GOTO Backup } ELSE { -- start of comment, consume rest of comment charsSkipped _ charsSkipped + 2; DO SELECT (char _ stream.GetChar[ ! IO.EndOfStream => GOTO End]) FROM '\n => EXIT; '- => { charsSkipped _ charsSkipped + 1; IF stream.GetChar[ ! IO.EndOfStream => GOTO End] = '- THEN EXIT; }; ENDCASE => charsSkipped _ charsSkipped + 1; ENDLOOP; charsSkipped _ charsSkipped + 1; }; }; ENDCASE => GOTO Backup; ENDLOOP; EXITS Backup => { stream.Backup[char]; RETURN [charsSkipped] }; End => RETURN [charsSkipped]; }}; GetCedarToken: PUBLIC PROC [stream: STREAM, buffer: REF TEXT, flushComments: BOOL _ FALSE] RETURNS [tokenKind: TokenKind, token: REF TEXT, charsSkipped: INT, error: IO.TokenError] = { char: CHAR; NextChar: PROC RETURNS [CHAR] = { char _ stream.GetChar[]; token _ RefText.InlineAppendChar[token, char]; RETURN[Ascii.Lower[char]] }; PutbackChar: PROC = { stream.Backup[token[token.length _ token.length - 1]]; }; AcceptExtendedChar: PROC RETURNS [success: BOOL] = { ENABLE IO.EndOfStream => GOTO Failure; SELECT NextChar[] FROM 'n, 'r, 't, 'b, 'f, 'l, '\', '\", '\\ => RETURN[TRUE]; IN ['0..'9] => { THROUGH [1..2] DO IF NextChar[] NOT IN ['0..'9] THEN GOTO Failure ENDLOOP; RETURN[TRUE]; }; ENDCASE EXITS Failure => { error _ $extendedChar; RETURN[FALSE] } }; AcceptRealTail: PROC [] = { DO SELECT NextChar[ ! IO.EndOfStream => GOTO Accept] FROM IN ['0..'9] => NULL; 'e => { [] _ AcceptExponent[]; RETURN }; ENDCASE => { PutbackChar[]; RETURN }; ENDLOOP; EXITS Accept => RETURN }; AcceptExponent: PROC RETURNS [success: BOOL] = { SELECT NextChar[ ! IO.EndOfStream => GOTO Failure] FROM '-, '+ => [] _ NextChar[ ! IO.EndOfStream => GOTO Failure]; ENDCASE => NULL; IF char NOT IN ['0..'9] THEN GOTO Failure; DO IF NextChar[ ! IO.EndOfStream => GOTO Success] NOT IN ['0..'9] THEN { PutbackChar[]; GOTO Success } ENDLOOP; EXITS Success => RETURN [TRUE]; Failure => { error _ $numericLiteral; RETURN [FALSE] }; }; AcceptHexTail: PROC [] RETURNS [success: BOOL] = { length: NAT = token.length; { DO SELECT NextChar[ ! IO.EndOfStream => GOTO Undo] FROM IN ['0..'9], IN ['a..'f] => NULL; 'h => EXIT; ENDCASE => GOTO Undo; ENDLOOP; WHILE NextChar[ ! IO.EndOfStream => GOTO Accept] IN ['0..'9] DO ENDLOOP; GOTO PutbackAccept; EXITS Accept => { tokenKind _ $tokenHEX; RETURN [TRUE] }; PutbackAccept => { PutbackChar[]; tokenKind _ $tokenHEX; RETURN [TRUE] }; Undo => { FOR i: NAT DECREASING IN [length .. token.length) DO PutbackChar[] ENDLOOP; token.length _ length; RETURN [FALSE] } } }; error _ $none; token _ buffer; token.length _ 0; charsSkipped _ 0; { -- EXITS ErrorReturn, DoubleReturn, Return, PutbackReturn, EOFReturn DO -- first arm loops, second may loop; others terminate SELECT NextChar[ ! IO.EndOfStream => GOTO EOFReturn] FROM IN [IO.NUL .. IO.SP] => { -- white space charsSkipped _ charsSkipped + 1; token.length _ 0; }; '- => {-- minus or comment prev: CHAR _ IO.CR; endOfComment: BOOL _ FALSE; tokenKind _ $tokenSINGLE; IF NextChar[ ! IO.EndOfStream => GOTO Return] # '- THEN GOTO PutbackReturn; tokenKind _ $tokenCOMMENT; IF flushComments THEN { charsSkipped _ charsSkipped + 1; token.length _ 0 }; DO { SELECT NextChar[ ! IO.EndOfStream => GOTO EndOfStream] FROM IO.CR => endOfComment _ TRUE; '- => IF prev = '- THEN endOfComment _ TRUE; ENDCASE; IF flushComments THEN { charsSkipped _ charsSkipped + 1; token.length _ 0 }; EXITS EndOfStream => endOfComment _ TRUE }; IF endOfComment THEN IF flushComments THEN EXIT ELSE GOTO Return; prev _ char; ENDLOOP; }; IN ['a .. 'z] => { -- identifier tokenKind _ $tokenID; DO SELECT NextChar[ ! IO.EndOfStream => GOTO Return] FROM IN ['a..'z], IN ['0..'9] => NULL; ENDCASE => GOTO PutbackReturn; ENDLOOP; }; IN ['0 .. '9] => { -- numeric literal, this gets hairy tokenKind _ $tokenDECIMAL; WHILE NextChar[ ! IO.EndOfStream => GOTO Return] IN ['0..'9] DO ENDLOOP; SELECT Ascii.Lower[char] FROM '. => { IF NextChar[ ! IO.EndOfStream => GOTO Invalid] IN ['0 .. '9] THEN { -- REAL tokenKind _ $tokenREAL; AcceptRealTail[]; GOTO Return } ELSE { -- DECIMAL followed by dotdot PutbackChar[]; GOTO PutbackReturn } }; 'a, 'f => { IF AcceptHexTail[] THEN GOTO Return ELSE GOTO Invalid; }; 'b, 'd => { IF Ascii.Lower[char] = 'b THEN tokenKind _ $tokenOCTAL; IF AcceptHexTail[] THEN GOTO Return; WHILE NextChar[ ! IO.EndOfStream => GOTO Return] IN ['0..'9] DO ENDLOOP; GOTO PutbackReturn; }; 'c => { IF AcceptHexTail[] THEN GOTO Return; tokenKind _ $tokenCHAR; GOTO Return; }; 'e => { IF AcceptHexTail[] THEN GOTO Return; IF AcceptExponent[] THEN { tokenKind _ $tokenREAL; GOTO Return } ELSE GOTO ErrorReturn; }; 'h => { tokenKind _ $tokenHEX; WHILE NextChar[ ! IO.EndOfStream => GOTO Return] IN ['0..'9] DO ENDLOOP; GOTO PutbackReturn; }; ENDCASE => GOTO PutbackReturn; EXITS Invalid => { error _ $numericLiteral; GOTO ErrorReturn } }; '. => {-- either a dotdot or a REAL or a dot tokenKind _ $tokenSINGLE; SELECT NextChar[ ! IO.EndOfStream => GOTO Return] FROM '. => GOTO DoubleReturn; -- dotdot IN ['0..'9] => NULL; -- REAL ENDCASE => GOTO PutbackReturn; -- dot tokenKind _ $tokenREAL; AcceptRealTail[]; GOTO Return; }; ',, ';, ':, '_, '#, '~, '+, '*, '/, '^, '@, '!, '(, '), '[, '], '{, '}, '| => { tokenKind _ $tokenSINGLE; GOTO Return }; '\' => { -- CHAR literal tokenKind _ $tokenCHAR; SELECT NextChar[ ! IO.EndOfStream => GOTO Illegal] FROM '\\ => IF NOT AcceptExtendedChar[] THEN GOTO ErrorReturn ELSE GOTO Return; IN [' ..'~] => GOTO Return; ENDCASE => GOTO Illegal; EXITS Illegal => { error _ $charLiteral; GOTO ErrorReturn }; }; '\" => { -- ROPE, REF TEXT, or STRING literal quoteSeen: BOOL _ FALSE; tokenKind _ $tokenROPE; DO SELECT NextChar[ ! IO.EndOfStream => IF quoteSeen THEN GOTO Return ELSE GOTO Illegal] FROM '\" => quoteSeen _ NOT quoteSeen; '\\ => IF quoteSeen THEN EXIT ELSE IF NOT AcceptExtendedChar[] THEN GOTO ErrorReturn; IN [' ..'~], '\n, '\t => IF quoteSeen THEN EXIT; ENDCASE => GOTO Illegal; ENDLOOP; SELECT Ascii.Lower[char] FROM 'l => GOTO Return; ENDCASE => GOTO PutbackReturn; EXITS Illegal => { error _ $stringLiteral; GOTO ErrorReturn }; }; '$ => { -- ATOM literal tokenKind _ $tokenATOM; { SELECT NextChar[ ! IO.EndOfStream => GOTO Invalid] FROM IN ['a..'z] => NULL; ENDCASE => GOTO Invalid; EXITS Invalid => { error _ $atomLiteral; GO TO ErrorReturn }; }; DO SELECT NextChar[ ! IO.EndOfStream => GOTO Return] FROM IN ['a..'z], IN ['0..'9] => NULL; ENDCASE => GOTO PutbackReturn; ENDLOOP; }; '= => { -- either '=' or '=>' tokenKind _ $tokenSINGLE; IF NextChar[ ! IO.EndOfStream => GOTO Return] = '> THEN GOTO DoubleReturn ELSE GOTO PutbackReturn }; '>, '< => { -- either '>' or '>=' (or '<' or '<=') tokenKind _ $tokenSINGLE; IF NextChar[ ! IO.EndOfStream => GOTO Return] = '= THEN GOTO DoubleReturn ELSE GOTO PutbackReturn }; ENDCASE => { error _ $singleChar; GOTO ErrorReturn }; ENDLOOP; EXITS Return => { RETURN }; PutbackReturn => { PutbackChar[]; RETURN }; DoubleReturn => { tokenKind _ $tokenDOUBLE; RETURN }; EOFReturn => { tokenKind _ $tokenEOF; RETURN }; ErrorReturn => { tokenKind _ $tokenERROR; RETURN }; } }; GetCedarTokenRope: PUBLIC PROC [stream: STREAM, flushComments: BOOL] RETURNS [tokenKind: TokenKind, token: ROPE, charsSkipped: INT] = { buffer: REF TEXT = RefText.ObtainScratch[100]; { ENABLE UNWIND => RefText.ReleaseScratch[buffer]; tokenText: REF TEXT; [tokenKind: tokenKind, token: tokenText, charsSkipped: charsSkipped] _ GetCedarToken[stream, buffer, flushComments]; SELECT tokenKind FROM tokenEOF => ERROR IO.EndOfStream[stream]; tokenERROR => ERROR IO.Error[$SyntaxError, stream]; ENDCASE; token _ Rope.FromRefText[tokenText]; }; RefText.ReleaseScratch[buffer]; RETURN [tokenKind, token, charsSkipped]; }; GetInt: PUBLIC PROC [stream: STREAM] RETURNS [INT] = { LastInt: LONG CARDINAL = INT.LAST; card: LONG CARDINAL; negative: BOOL; [card, negative] _ GetNumber[stream, TRUE]; IF negative THEN { IF card <= LastInt+1 THEN RETURN[-card] } ELSE { IF card <= LastInt THEN RETURN[card] }; ERROR IO.Error[$Overflow, stream]; }; GetCard: PUBLIC PROC [stream: STREAM] RETURNS [LONG CARDINAL] = { RETURN[GetNumber[stream, FALSE].card]; }; GetNumber: PUBLIC PROC [stream: STREAM, negativeOK: BOOL] RETURNS [card: LONG CARDINAL, negative: BOOL] = { tokenKind: TokenKind; token: REF TEXT; signSeen: BOOL _ FALSE; buffer: REF TEXT = RefText.ObtainScratch[100]; negative _ FALSE; { ENABLE Convert.Error => IF reason = $overflow THEN GOTO Overflow; DO -- executed once or twice [tokenKind: tokenKind, token: token] _ GetCedarToken[stream, buffer, TRUE]; SELECT tokenKind FROM tokenDECIMAL => { card _ Convert.CardFromDecimalLiteral[RefText.TrustTextAsRope[token]]; EXIT }; tokenOCTAL => { card _ Convert.CardFromOctalLiteral[RefText.TrustTextAsRope[token]]; EXIT }; tokenHEX => { card _ Convert.CardFromHexLiteral[RefText.TrustTextAsRope[token]]; EXIT }; tokenSINGLE => { IF signSeen THEN GOTO SyntaxError; signSeen _ TRUE; SELECT token[0] FROM '- => IF negativeOK THEN negative _ TRUE ELSE GOTO SyntaxError; '+ => NULL; ENDCASE => GOTO SyntaxError; }; tokenEOF => IF signSeen THEN GOTO SyntaxError ELSE GOTO EndOfStream; ENDCASE => GOTO SyntaxError; ENDLOOP; RefText.ReleaseScratch[buffer]; RETURN [card, negative]; EXITS EndOfStream => { RefText.ReleaseScratch[buffer]; ERROR IO.EndOfStream[stream] }; SyntaxError => { RefText.ReleaseScratch[buffer]; ERROR IO.Error[$SyntaxError, stream] }; Overflow => { RefText.ReleaseScratch[buffer]; ERROR IO.Error[$Overflow, stream] }; }; }; GetReal: PUBLIC PROC [stream: STREAM] RETURNS [REAL] = { tokenKind: TokenKind; token: REF TEXT; signSeen, negative: BOOL _ FALSE; real: REAL; buffer: REF TEXT = RefText.ObtainScratch[100]; { DO -- executed once or twice [tokenKind: tokenKind, token: token] _ GetCedarToken[stream, buffer, TRUE]; SELECT tokenKind FROM tokenDECIMAL => { real _ Convert.CardFromDecimalLiteral[RefText.TrustTextAsRope[token]]; EXIT }; tokenOCTAL => { real _ Convert.CardFromOctalLiteral[RefText.TrustTextAsRope[token]]; EXIT }; tokenHEX => { real _ Convert.CardFromHexLiteral[RefText.TrustTextAsRope[token]]; EXIT }; tokenREAL => { real _ Convert.RealFromLiteral[RefText.TrustTextAsRope[token]]; EXIT }; tokenSINGLE => { IF signSeen THEN GOTO SyntaxError; signSeen _ TRUE; SELECT token[0] FROM '- => negative _ TRUE; '+ => NULL; ENDCASE => GOTO SyntaxError; }; tokenEOF => IF signSeen THEN GOTO SyntaxError ELSE GOTO EndOfStream; ENDCASE => GOTO SyntaxError; ENDLOOP; RefText.ReleaseScratch[buffer]; RETURN [IF negative THEN -real ELSE real]; EXITS EndOfStream => { RefText.ReleaseScratch[buffer]; ERROR IO.EndOfStream[stream] }; SyntaxError => { RefText.ReleaseScratch[buffer]; ERROR IO.Error[$SyntaxError, stream] }; }; }; GetTime: PUBLIC PROC [stream: STREAM] RETURNS [BasicTime.GMT] = { RETURN[BasicTime.Pack[stream.GetUnpackedTime[] ! BasicTime.OutOfRange => ERROR IO.Error[$Overflow, stream]]]; }; GetBool: PUBLIC PROC [stream: STREAM] RETURNS [bool: BOOL] = { tokenKind: TokenKind; token: REF TEXT; buffer: REF TEXT = RefText.ObtainScratch[100]; [tokenKind: tokenKind, token: token] _ GetCedarToken[stream, buffer, TRUE]; SELECT tokenKind FROM tokenID => NULL; tokenEOF => ERROR IO.EndOfStream[stream]; ENDCASE => ERROR IO.Error[$SyntaxError, stream]; bool _ Convert.BoolFromRope[RefText.TrustTextAsRope[token] ! Convert.Error => IF reason = $syntax THEN ERROR IO.Error[$SyntaxError, stream]]; RefText.ReleaseScratch[buffer]; }; GetAtom: PUBLIC PROC [stream: STREAM] RETURNS [atom: ATOM] = { tokenKind: TokenKind; token: REF TEXT; buffer: REF TEXT = RefText.ObtainScratch[100]; [tokenKind: tokenKind, token: token] _ GetCedarToken[stream, buffer, TRUE]; SELECT tokenKind FROM tokenID => NULL; tokenATOM => NULL; tokenEOF => ERROR IO.EndOfStream[stream]; ENDCASE => ERROR IO.Error[$SyntaxError, stream]; atom _ Convert.AtomFromRope[RefText.TrustTextAsRope[token] ! Convert.Error => IF reason = $syntax THEN ERROR IO.Error[$SyntaxError, stream]]; RefText.ReleaseScratch[buffer]; }; GetRopeLiteral: PUBLIC PROC [stream: STREAM] RETURNS [r: ROPE] = { tokenKind: TokenKind; token: REF TEXT; buffer: REF TEXT = RefText.ObtainScratch[100]; [tokenKind: tokenKind, token: token] _ GetCedarToken[stream, buffer, TRUE]; SELECT tokenKind FROM tokenROPE => NULL; tokenEOF => ERROR IO.EndOfStream[stream]; ENDCASE => ERROR IO.Error[$SyntaxError, stream]; r _ Convert.RopeFromLiteral[RefText.TrustTextAsRope[token]]; RefText.ReleaseScratch[buffer]; }; GetCharLiteral: PUBLIC PROC [stream: STREAM] RETURNS [c: CHAR] = { tokenKind: TokenKind; token: REF TEXT; buffer: REF TEXT = RefText.ObtainScratch[100]; [tokenKind: tokenKind, token: token] _ GetCedarToken[stream, buffer, TRUE]; SELECT tokenKind FROM tokenCHAR => NULL; tokenEOF => ERROR IO.EndOfStream[stream]; ENDCASE => ERROR IO.Error[$SyntaxError, stream]; c _ Convert.CharFromLiteral[RefText.TrustTextAsRope[token] ! Convert.Error => IF reason = $overflow THEN ERROR IO.Error[$Overflow, stream]]; RefText.ReleaseScratch[buffer]; }; GetID: PUBLIC PROC [stream: STREAM] RETURNS [r: ROPE] = { tokenKind: TokenKind; token: REF TEXT; buffer: REF TEXT = RefText.ObtainScratch[100]; [tokenKind: tokenKind, token: token] _ GetCedarToken[stream, buffer, TRUE]; SELECT tokenKind FROM tokenID => NULL; tokenEOF => ERROR IO.EndOfStream[stream]; ENDCASE => ERROR IO.Error[$SyntaxError, stream]; r _ Rope.FromRefText[token]; RefText.ReleaseScratch[buffer]; }; GetRefAny: PUBLIC PROC [stream: STREAM] RETURNS [REF ANY] = { RightParen: ERROR = CODE; Comma: ERROR = CODE; GetRefAny0: PROC [stream: STREAM, buffer: REF TEXT] RETURNS [REF ANY] = { ENABLE Convert.Error => IF reason = $syntax THEN ERROR IO.Error[$SyntaxError, stream] ELSE IF reason = $overflow THEN ERROR IO.Error[$Overflow, stream]; tokenKind: IO.TokenKind; token: REF TEXT; DO [tokenKind: tokenKind, token: token] _ GetCedarToken[stream, buffer, TRUE]; SELECT tokenKind FROM tokenERROR => ERROR IO.Error[$SyntaxError, stream]; tokenID => RETURN[ IF Rope.Equal[RefText.TrustTextAsRope[token], "NIL"] THEN NIL ELSE IF Rope.Equal[RefText.TrustTextAsRope[token], "TRUE"] THEN NEW[BOOL _ TRUE] ELSE IF Rope.Equal[RefText.TrustTextAsRope[token], "FALSE"] THEN NEW[BOOL _ FALSE] ELSE Convert.AtomFromRope[RefText.TrustTextAsRope[token]]]; IN [tokenDECIMAL .. tokenHEX] => RETURN[ NEW[INT _ Convert.IntFromRope[RefText.TrustTextAsRope[token]]]]; tokenREAL => RETURN[ NEW[REAL _ Convert.RealFromLiteral[RefText.TrustTextAsRope[token]]]]; tokenROPE => RETURN[Convert.RopeFromLiteral[RefText.TrustTextAsRope[token]]]; tokenCHAR => RETURN[ NEW[CHAR _ Convert.CharFromLiteral[RefText.TrustTextAsRope[token]]]]; tokenATOM => RETURN[Convert.AtomFromRope[RefText.TrustTextAsRope[token]]]; tokenSINGLE => {c: CHAR = token[0]; SELECT c FROM '( => {lst, tail: LIST OF REF ANY _ NIL; obj: REF ANY; UNTIL IO.EndOf[stream] DO obj _ GetRefAny0[stream, buffer ! RightParen, IO.EndOfStream => EXIT; Comma => LOOP]; IF tail # NIL THEN {tail.rest _ LIST[obj]; tail _ tail.rest} ELSE {tail _ LIST[obj]; lst _ tail}; ENDLOOP; RETURN[lst]; }; ') => ERROR RightParen; '^ => NULL; -- e.g. ^3, makes print and read be inverses. ', => ERROR Comma; '-, '+ => {obj: REF ANY = GetRefAny0[stream, buffer]; WITH obj SELECT FROM x: REF INT => IF c = '- THEN x^ _ -x^; x: REF REAL => IF c = '- THEN x^ _ -x^; ENDCASE => ERROR IO.Error[$SyntaxError, stream]; RETURN[obj]; }; ENDCASE => ERROR IO.Error[$SyntaxError, stream]; }; tokenDOUBLE => ERROR IO.Error[$SyntaxError, stream]; tokenCOMMENT => NULL; tokenEOF => ERROR IO.EndOfStream[stream]; ENDCASE => ERROR; ENDLOOP; }; object: REF ANY; buffer: REF TEXT = RefText.ObtainScratch[512]; { object _ GetRefAny0[stream, buffer ! RightParen => ERROR IO.Error[$SyntaxError, stream]; Comma => ERROR IO.Error[$SyntaxError, stream]]; }; RefText.ReleaseScratch[buffer]; RETURN [object]; }; GetRefAnyLine: PUBLIC PROC [stream: STREAM] RETURNS [LIST OF REF ANY] = { lst, tail: LIST OF REF ANY _ NIL; lst _ tail _ LIST[GetRefAny[stream]]; UNTIL stream.EndOf[] DO IF stream.PeekChar[] = IO.CR THEN { [] _ stream.GetChar[]; EXIT }; tail.rest _ LIST[GetRefAny[stream]]; tail _ tail.rest; ENDLOOP; RETURN[lst]; }; END. $IOScanImpl.mesa Copyright c 1984 by Xerox Corporation. All rights reserved. MBrown on January 13, 1984 2:35 pm Maxwell on September 1, 1983 3:50 pm Paul Rovner on May 20, 1983 5:05 pm Teitelman on April 6, 1983 3:46 pm Russ Atkinson on November 7, 1984 12:06:40 pm PST GetToken, GetLine, SkipWhitespace GetCedarToken NOTE: the acceptance procs below return with no extra chars read in case of acceptance, and (with exception of AcceptHexTail) with the first erroneous char read in case of non-acceptance. have seen '\\; looking for rest of extendedChar have seen ?num.digit; looking for ?num?exponent have seen (E|e); looking for ?(+|-)num have seen num(A|a|B|b|C|c|D|d|E|e|F|f); looking for rest of hex constant if not success then restore state, since may not be an error Get Other conversion errors are detected by GetCedarToken. Conversion errors are detected by GetCedarToken. GetRefAny CHANGE LOG Last edited by MBrown on October 7, 1983 10:29 am Bug in GetCedarToken: did not allow '\n, '\t to be included in or to follow a string literal. Κ– "Cedar" style˜headšœ™Jšœ Οmœ1™J˜JšœŸœŸœ˜JšœŸœŸœ˜.JšœEŸœ˜KšŸœ Ÿ˜Jšœ Ÿœ˜Jšœ Ÿ œ˜)JšŸœŸœ˜0—šœM˜MJšŸœŸœŸœŸœ˜@—Jšœ˜J˜—š ‘œŸœŸœ ŸœŸœŸœ˜>J˜JšœŸœŸœ˜JšœŸœŸœ˜.JšœEŸœ˜KšŸœ Ÿ˜Jšœ Ÿœ˜Jšœ Ÿœ˜Jšœ ŸœŸœ˜)JšŸœŸœ˜0—šœM˜MJšŸœŸœŸœŸœ˜@—Jšœ˜J˜—š ‘œŸœŸœ ŸœŸœŸœ˜BJ˜JšœŸœŸœ˜JšœŸœŸœ˜.JšœEŸœ˜KšŸœ Ÿ˜Jšœ Ÿœ˜Jšœ Ÿ œ˜)JšŸœŸœŸœ˜0—Jšœ<˜—Jšœ˜J˜—š ‘œŸœŸœ ŸœŸœŸœ˜9J˜JšœŸœŸœ˜JšœŸœŸœ˜.JšœEŸœ˜KšŸœ Ÿ˜Jšœ Ÿœ˜Jšœ Ÿ œ˜)JšŸœŸœ˜0—Jšœ˜Jšœ˜J˜——šœ ™ š‘ œŸœŸœ ŸœŸœŸœŸœ˜=Jšœ ŸœŸœ˜JšœŸœŸœ˜š‘ œŸœ Ÿœ ŸœŸœŸœŸœŸœ˜IšŸœ˜JšŸœŸœŸœŸœ˜=Jš ŸœŸœŸœŸœŸœ˜B—Jšœ Ÿœ ˜JšœŸœŸœ˜šŸœ˜šœ&˜&JšœŸœ˜$—šŸœ Ÿ˜JšœŸœŸœ˜3šœ Ÿœ˜JšŸœ3ŸœŸ˜=šŸœŸœ4Ÿ˜?JšŸœŸœŸœ˜—šŸœŸœ5Ÿ˜@JšŸœŸœŸœ˜—JšŸœ7˜;—šŸœŸœ˜(JšŸœŸœ9˜@—šœ Ÿœ˜JšŸœŸœ=˜E—Jšœ Ÿœ:˜Mšœ Ÿœ˜JšŸœŸœ=˜E—Jšœ Ÿœ7˜Jšœ˜JšœŸœ ˜šŸœŸ˜ šœ˜Jš œ ŸœŸœŸœŸ œ˜"JšœŸœŸœ˜ šŸœŸœŸ˜šœ!˜!Jšœ ŸœŸœ Ÿœ˜3—JšŸœŸœŸœŸœ˜