[ivy]<Satterthwaite>SML>SMCommentTableImpl.mesa!6

SMCommentTableImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
last edit by Satterthwaite, May 12, 1986 11:46:07 am PDT
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𡤀];
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 {
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
ELSE IF notBefore > lval THEN low ← lastx+1
ELSE {
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}
ELSE IF start >= lval THEN low ← last+1;
ENDLOOP;
};
};
Explode: PUBLIC PROC[ref: Ref] RETURNS[start: Index, text: Text, lastToken, prefix: Index] ~ {
RETURN (IF ref = NIL
THEN [Index.LAST, NIL, Index.LAST, 0]
ELSE [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]};
}.