-- SMCommentTableImpl.mesa -- last edit by Satterthwaite, April 29, 1983 10:19 am -- last edit by Schmidt, May 3, 1982 3:35 pm DIRECTORY SMCommentTable: TYPE USING [ BreakSequence, BreakTab, Index, Node, Ref, Table, TableNode, Text], SMCommentTableOps: TYPE USING []; SMCommentTableImpl: CEDAR PROGRAM EXPORTS SMCommentTableOps ~ { OPEN SMCommentTable; CommentManager: PUBLIC TYPE ~ RECORD[ z: ZONE←, commentTable: SMCommentTable.Table←NIL, breakTable: SMCommentTable.BreakTab←NIL, ending: INT←0]; CommentM: TYPE ~ REF CommentManager; TableOverflow: PUBLIC ERROR ~ CODE; TableOrder: PUBLIC ERROR ~ CODE; Create: PUBLIC PROC[zone: ZONE] RETURNS [CommentM] ~ { RETURN [zone.NEW[CommentManager ← [z~zone]]]}; Reset: PUBLIC PROC[cm: CommentM] ~ { IF cm.commentTable # NIL THEN { cm.commentTable.size ← 0; cm.commentTable.last ← NIL; cm.commentTable.lastx ← 0}; IF cm.breakTable # NIL THEN cm.breakTable.size ← 0; cm.ending ← 0}; Add: PUBLIC PROC[cm: CommentM, start: Index, text: Text, lastToken,prefix: Index] ~ { ref: Ref ~ (cm.z).NEW[Node ← [start, text, lastToken, prefix]]; size: NAT ~ (IF cm.commentTable = NIL THEN 0 ELSE cm.commentTable.size); max: NAT ~ (IF cm.commentTable = NIL THEN 0 ELSE cm.commentTable.max); last: Ref ~ (IF size > 0 THEN cm.commentTable[size-1] ELSE NIL); IF lastToken > start THEN RETURN; IF last # NIL THEN { IF last.start > start OR lastToken < last.lastToken THEN RETURN; IF last.start = start THEN { -- merge the blank line comment with the actual comment IF last.text # NIL THEN RETURN; ref.prefix ← prefix + last.prefix; cm.commentTable[size-1] ← ref; RETURN} }; IF size >= max THEN { newMax: NAT ~ (IF max > (NAT.LAST/2 - 2) THEN NAT.LAST ELSE max*2 + 4); IF newMax <= size THEN ERROR TableOverflow; {newTable: Table ~ (cm.z).NEW[TableNode[newMax]]; newTable.last ← NIL; FOR i: NAT IN [0..size) DO newTable[i] ← cm.commentTable[i]; cm.commentTable[i] ← NIL; ENDLOOP; cm.commentTable ← newTable; }}; cm.commentTable[size] ← ref; cm.commentTable.size ← size + 1}; AddBreakHint: PUBLIC PROC[cm: CommentM, index: Index] ~ { size: NAT ~ (IF cm.breakTable = NIL THEN 0 ELSE cm.breakTable.size); max: NAT ~ (IF cm.breakTable = NIL THEN 0 ELSE cm.breakTable.max); last: Index ~ (IF size = 0 THEN 0 ELSE cm.breakTable[size-1]); IF index <= last THEN RETURN; IF size >= max THEN { -- must extend the table new: BreakTab ← NIL; nmax: NAT ← MAX[200, IF max < NAT.LAST/2 THEN max+max ELSE NAT.LAST]; IF nmax <= max THEN ERROR TableOverflow; new ← (cm.z).NEW[BreakSequence[nmax]]; FOR i: NAT IN [0..size) DO new[i] ← cm.breakTable[i]; ENDLOOP; cm.breakTable ← new}; cm.breakTable[size] ← index; cm.breakTable.size ← size + 1}; FindNext: PUBLIC PROC[cm: CommentM, notBefore: Index] RETURNS[Ref] ~ { IF cm.commentTable # NIL AND cm.commentTable.size > 0 THEN { low: NAT ← 0; high: NAT ← cm.commentTable.size-1; last: Ref ← cm.commentTable.last; lastx: NAT ← cm.commentTable.lastx; lval: Index ← 0; IF last # NIL THEN { lval ← last.start; IF notBefore = lval THEN RETURN [last]; IF notBefore < lval THEN high ← lastx ELSE low ← lastx+1}; WHILE low < high DO lval ← (last ← cm.commentTable[lastx ← (low+high)/2]).start; IF notBefore < lval THEN {high ← lastx; LOOP}; IF notBefore > lval THEN {low ← lastx+1; LOOP}; cm.commentTable.lastx ← lastx; RETURN [cm.commentTable.last ← last]; ENDLOOP; IF high # lastx OR last = NIL THEN lval ← (last ← cm.commentTable[lastx ← high]).start; IF notBefore <= lval THEN { cm.commentTable.lastx ← lastx; RETURN [cm.commentTable.last ← last]}}; RETURN [NIL]}; TestBreakHint: PUBLIC PROC[cm: CommentM, start: Index, next: Index] RETURNS[BOOL] ~ { IF start = 0 OR next <= start THEN RETURN [TRUE]; IF cm.breakTable = NIL OR cm.breakTable.size <= 1 THEN RETURN [FALSE]; {low: NAT ← 0; high: NAT ← cm.breakTable.size - 1; DO last: NAT ← (low+high)/2; lval: Index ← cm.breakTable[last]; IF low = high THEN RETURN [start < lval AND next > lval]; IF start < lval THEN { IF next > lval THEN RETURN [TRUE]; high ← last; LOOP}; IF start >= lval THEN {low ← last+1; LOOP}; ENDLOOP; }}; Explode: PUBLIC PROC[ref: Ref] RETURNS[start: Index, text: Text, lastToken, prefix: Index] ~ { IF ref = NIL THEN RETURN [Index.LAST, NIL, Index.LAST, 0]; RETURN [ref.start, ref.text, ref.lastToken, ref.prefix]}; SetEnding: PUBLIC PROC[cm: CommentM, end: Index] ~ {cm.ending ← end}; GetEnding: PUBLIC PROC[cm: CommentM] RETURNS[Index] ~ {RETURN [cm.ending]}; }.