<> <> <> <> <<>> DIRECTORY ExpressToken, IO USING [BreakProc, EndOfStream, GetTokenRope], Rope USING [Equal, Length]; ExpressTokenImpl: CEDAR PROGRAM IMPORTS IO, Rope EXPORTS ExpressToken ~ { OPEN ExpressToken; DefinedTokens: TYPE ~ LIST OF RECORD [rope: ROPE, kind: ATOM]; <> <> <> definedTokens: DefinedTokens _ LIST[ <<["", $],>> [NIL, $Id1], [NIL, $Id2], [NIL, $Id3], [NIL, $Id4], [NIL, $Id5], [NIL, $Constant], ["+", $Add], ["-", $Subtract], ["*", $Multiply], ["/", $Divide], ["(", $LPar], [")", $RPar], ["[", $LBracket], ["]", $RBracket], [",", $Comma], ["IF", $If], ["THEN", $Then], ["ELSE", $Else], ["min", $min], ["max", $max], ["or", $or], ["and", $and], ["xor", $xor], [">", $GT], ["<", $LT], ["=", $EQ], [">=", $GE], ["<=", $LE], ["#", $NE], ["~", $not] ]; GetNextToken: PUBLIC PROC [ts: TokenStream, symbols: Symbols, cProcs: ClientProcList] RETURNS [token: Token] ~ { TokenBreak: IO.BreakProc ~ { RETURN[SELECT char FROM IN ['\000 .. ' ] => sepr, '>, '<, '=, '#, '~, '[, '], '(, '), '+, '-, '*, '/, '^, ', => break, ENDCASE => other ]; }; Pos: PROC [size: INT] RETURNS [INT] ~ { ts.position _ ts.position+size; RETURN[size]; }; ids: INT _ 1; --Counts identifiers as they go by... rope: ROPE; size: INT; <> IF ts.buffer#NIL THEN {token _ ts.buffer.first; ts.buffer _ts.buffer.rest; []_Pos[token.size]; RETURN}; <<>> <> [rope, size] _ IO.GetTokenRope[ts.stream, TokenBreak ! IO.EndOfStream => { token _ ["", $EndOfStream, Pos[size]]; GOTO ReturnEOS; }]; size _ size+Rope.Length[rope]; <> FOR sym: Symbols _ symbols, sym.rest UNTIL sym=NIL DO IF Rope.Equal[sym.first, rope, FALSE] THEN RETURN [[rope, SELECT ids FROM 1=>$Id1, 2=>$Id2, 3=>$Id3, 4=>$Id4, 5=>$Id5, ENDCASE=>ERROR, Pos[size]]]; ids _ ids+1; ENDLOOP; <> FOR cProc: ClientProcList _ cProcs, cProc.rest UNTIL cProc=NIL DO IF Rope.Equal[cProc.first.userRope, rope, FALSE] THEN RETURN [[rope, $CProc, Pos[size]]]; ENDLOOP; <> FOR builtIn: DefinedTokens _ definedTokens, builtIn.rest UNTIL builtIn=NIL DO IF Rope.Equal[builtIn.first.rope, rope, FALSE] THEN RETURN [[rope, builtIn.first.kind, Pos[size]]]; ENDLOOP; <> RETURN[[rope, $Constant, Pos[size]]]; EXITS ReturnEOS => RETURN; }; PushToken: PUBLIC PROC [ts: TokenStream, token: Token] ~ { ts.buffer _ CONS[token, ts.buffer]; ts.position _ ts.position - token.size; }; RegisterToken: PUBLIC PROC [rope: ROPE, kind: ATOM] ~ { <> definedTokens _ CONS[ [rope, kind], definedTokens]; }; TokenStreamFromIOStream: PUBLIC PROC [s: STREAM] RETURNS [ts: TokenStream] ~ { <> RETURN [NEW[TokenStreamRec _ [stream: s]]]; }; }.