-- PPCommentTableImpl.mesa -- last edit by Russ Atkinson, 30-May-81 21:36:01 DIRECTORY PPCommentTable; PPCommentTableImpl: PROGRAM EXPORTS PPCommentTable = PUBLIC BEGIN OPEN PPCommentTable; Ref: TYPE = REF Node; Node: TYPE = RECORD [start: Index, text: Text, lastToken,prefix: Index]; Table: TYPE = REF TableNode; TableNode: TYPE = RECORD [ last: Ref, size: NAT, lastx: NAT, data: SEQUENCE max: NAT OF Ref]; BreakTab: TYPE = REF BreakSequence; BreakSequence: TYPE = RECORD [ size: NAT, indexes: SEQUENCE max: NAT OF Index ]; TableOverflow: ERROR = CODE; TableOrder: ERROR = CODE; -- variables in the global frame commentTable: Table _ NIL; breakTable: BreakTab _ NIL; ending: Index _ 0; Reset: PROC = { commentTable _ NIL; breakTable _ NIL; ending _ 0; }; AddComment: PROC [start: Index, text: Text, lastToken,prefix: Index] = { ref: Ref _ NEW[Node _ [start, text, lastToken, prefix]]; size: NAT _ IF commentTable = NIL THEN 0 ELSE commentTable.size; max: NAT _ IF commentTable = NIL THEN 0 ELSE commentTable.max; last: Ref _ IF size > 0 THEN 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; commentTable[size-1] _ ref; RETURN}; }; IF size >= max THEN { newMax: NAT _ IF max > (LAST[NAT]/2 - 2) THEN newMax _ LAST[NAT] ELSE newMax _ max*2 + 4; IF newMax <= size THEN ERROR TableOverflow; {newTable: Table _ NEW[TableNode[newMax]]; newTable.last _ NIL; FOR i: NAT IN [0..size) DO newTable[i] _ commentTable[i]; commentTable[i] _ NIL; ENDLOOP; commentTable _ newTable; }}; commentTable[size] _ ref; commentTable.size _ size + 1; }; AddBreakHint: PROC [index: Index] = { size: NAT _ IF breakTable = NIL THEN 0 ELSE breakTable.size; max: NAT _ IF breakTable = NIL THEN 0 ELSE breakTable.max; last: Index _ IF size = 0 THEN 0 ELSE 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 < LAST[NAT]/2 THEN max+max ELSE LAST[NAT]]; IF nmax <= max THEN ERROR TableOverflow; new _ NEW[BreakSequence[nmax]]; FOR i: NAT IN [0..size) DO new[i] _ breakTable[i]; ENDLOOP; breakTable _ new; }; breakTable[size] _ index; breakTable.size _ size + 1; }; FindNextComment: PROC [notBefore: Index] RETURNS [Ref] = { IF commentTable # NIL AND commentTable.size > 0 THEN { low: NAT _ 0; high: NAT _ commentTable.size-1; last: Ref _ commentTable.last; lastx: NAT _ 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 _ commentTable[lastx _ (low+high)/2]).start; IF notBefore < lval THEN {high _ lastx; LOOP}; IF notBefore > lval THEN {low _ lastx+1; LOOP}; commentTable.lastx _ lastx; RETURN [commentTable.last _ last]; ENDLOOP; IF high # lastx OR last = NIL THEN lval _ (last _ commentTable[lastx _ high]).start; IF notBefore <= lval THEN {commentTable.lastx _ lastx; RETURN [commentTable.last _ last]}; }; RETURN [NIL]; }; TestBreakHint: PROC [start: Index, next: Index] RETURNS [BOOLEAN] = { IF start = 0 OR next <= start THEN RETURN [TRUE]; IF breakTable = NIL OR breakTable.size <= 1 THEN RETURN [FALSE]; {low: NAT _ 0; high: NAT _ breakTable.size - 1; DO last: NAT _ (low+high)/2; lval: Index _ 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: PROC [ref: Ref] RETURNS [start: Index, text: Text, lastToken,prefix: Index] = { IF ref = NIL THEN RETURN [LAST[Index], NIL, LAST[Index], 0]; RETURN [ref.start, ref.text, ref.lastToken, ref.prefix]; }; SetEnding: PROC [end: Index] = {ending _ end}; GetEnding: PROC RETURNS [Index] = {RETURN [ending]}; END.