<> <> <> DIRECTORY Ascii, CodeB, IO, RefText, Rope; CodeBImpl: CEDAR PROGRAM IMPORTS Ascii, IO, RefText, Rope EXPORTS CodeB = {OPEN CodeB; StringNotInAlphabet: PUBLIC ERROR [ Code: TYPE = REF CodePrivate; CodePrivate: PUBLIC TYPE = RECORD [ membership: Membership, ]; DecisionTree: TYPE = REF DecisionTreePrivate; DecisionTreePrivate: TYPE = RECORD [ variant: SELECT kind: * FROM branch => [a: ARRAY CHAR OF DecisionTree _ ALL[NIL]], leaf => [ ENDCASE]; Branch: TYPE = REF DecisionTreePrivate[branch]; Leaf: TYPE = REF DecisionTreePrivate[leaf]; CharClass: TYPE = {None, CreateCode: PUBLIC PROC [membership: Membership, code _ NEW [CodePrivate _ [ membership: membership, FOR IF CharIn[ ENDLOOP; code _ code; }; DTAdd: PROC [old: DecisionTree, c: CHAR, path: ROPE] RETURNS [new: DecisionTree] = { SELECT path.Length[] FROM =0 => { IF old # NIL THEN ERROR; new _ NEW [DecisionTreePrivate[leaf] _ [leaf[c]]]; }; >0 => { br: Branch _ IF old # NIL THEN NARROW[old] ELSE NEW [DecisionTreePrivate[branch] _ [branch[]]]; c0: CHAR = path.Fetch[0]; br.a[c0] _ DTAdd[br.a[c0], c, path.Substr[start: 1]]; new _ br; }; ENDCASE => ERROR; new _ new; }; Encode: PUBLIC PROC [code: Code, FOR i: INT IN [0 .. IF NOT CharIn[ THEN ERROR StringNotInAlphabet[ ENDLOOP; }; Decode: PUBLIC PROC [code: Code, IF NOT CharIn[ THEN ERROR StringNotInAlphabet[ FOR i: INT IN [1 .. IF NOT CharIn[ THEN ERROR StringNotInAlphabet[ ENDLOOP; }; Shrink: PROC [code: Code, OPEN code; buff: REF TEXT _ RefText.New[10]; AddChar: PROC [c: CHAR, times: NAT _ 1] = { buff _ RefText.InlineReserveChars[buff, times]; THROUGH [1 .. times] DO buff _ RefText.InlineAppendChar[buff, c] ENDLOOP; }; AddRope: PROC [r: ROPE] = { buff _ RefText.InlineReserveChars[buff, r.Length[]]; buff _ RefText.AppendRope[buff, r]; }; start: INT _ 0; lLen: INT = WHILE start < lLen DO non Add AddChar[ }; WHILE non IF non IF CharIn[ THEN {Add ELSE { found: BOOL; [found, next] _ DTLookup[ IF found THEN Add ELSE { Add DO IF next >= lLen THEN EXIT; IF CharIn[ next _ next + 1; ENDLOOP; }; AddRope[ }; start _ next; ENDLOOP; }; UnShrink: PROC [code: Code, OPEN code; buff: REF TEXT _ RefText.New[10]; AddChar: PROC [c: CHAR, times: NAT _ 1] = { buff _ RefText.InlineReserveChars[buff, times]; THROUGH [1 .. times] DO buff _ RefText.InlineAppendChar[buff, c] ENDLOOP; }; AddRope: PROC [r: ROPE] = { buff _ RefText.InlineReserveChars[buff, r.Length[]]; buff _ RefText.AppendRope[buff, r]; }; start: INT _ 0; mLen: INT = WHILE start < mLen DO non Add AddChar[ }; Add found: BOOL; WHILE non n _ non IF non IF NOT CharIn[ [found, next, SELECT TRUE FROM NOT found => { Add WHILE next < mLen AND Add }; n MOD 2 = 1 => {Add ENDCASE => {Add start _ next; ENDLOOP; }; DTLookup: PROC [dt: DecisionTree, path: ROPE, start: INT] RETURNS [found: BOOL, next: INT, c: CHAR] = { pathLen: INT = path.Length[]; next _ start; DO WITH dt SELECT FROM leaf: Leaf => RETURN [TRUE, next, leaf. br: Branch => { ndt: DecisionTree; IF next = pathLen OR (ndt _ br.a[path.Fetch[next]]) = NIL THEN RETURN [FALSE, next, '?]; dt _ ndt; next _ next + 1; }; ENDCASE => ERROR; ENDLOOP; }; Initialize: PROC [code: Code, OPEN code; }; UnInitialize: PROC [code: Code, }; Verboten: PROC [ OPEN code; len: INT = i: INT _ 0; FOR i _ 0, i+1 WHILE i < len AND ( b _ i < len AND CharIn[ }; CharIn: PROC [c: CHAR, class: CharClass, code: Code] RETURNS [in: BOOL] = INLINE { in _ SELECT class FROM None => code.membership[c] = None, ENDCASE => ERROR, None => FALSE, ENDCASE => ERROR, ENDCASE => ERROR; }; Lowercase: PUBLIC PROC [r: ROPE] RETURNS [lr: ROPE] = { i: INT _ -1; Generate: PROC RETURNS [CHAR] = {RETURN [Ascii.Lower[r.Fetch[i _ i + 1]]]}; lr _ Rope.FromProc[r.Length[], Generate]; }; Start: PROC = { FOR c: CHAR IN CHAR DO }; Start[]; }.