-- 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]};
}.