TiogaMesaOpsImpl.mesa
Copyright Ó 1989, 1991, 1992 by Xerox Corporation. All rights reserved.
Doug Wyatt, February 27, 1992 7:10 pm PST
DIRECTORY
Char USING [Widen, XCHAR],
CharOps USING [AlphaNumeric, XBlank],
EditSpanSupport USING [Apply],
IO USING [GetCedarToken, GetIndex, RIS, SetIndex, STREAM, TokenKind],
NodeReader USING [FetchChar, Free, New, Ref],
RefText USING [Equal, New],
Rope USING [Equal, ROPE, Size, Substr],
RuntimeError USING [BoundsFault],
TextEdit USING [ChangeLooks, DeleteText, PutComment, Size],
TextEditBogus USING [GetRope],
Tioga USING [Node, Span, Looks, noLooks, Event],
TiogaMesaOps USING [MesaLooksResult];
TiogaMesaOpsImpl: CEDAR PROGRAM
IMPORTS Char, CharOps, EditSpanSupport, IO, NodeReader, RefText, Rope, RuntimeError, TextEdit, TextEditBogus
EXPORTS TiogaMesaOps
= BEGIN
STREAM: TYPE ~ IO.STREAM;
Event: TYPE ~ Tioga.Event;
MesaLooksResult:
TYPE ~ TiogaMesaOps.MesaLooksResult;
namifyTypes:
BOOL ¬
FALSE;
MesaLooks:
PUBLIC
PROC [root: Tioga.Node, text: Tioga.Node,
start:
INT ¬ 0, len:
INT ¬
INT.
LAST, event: Event ¬
NIL]
RETURNS [MesaLooksResult] ~ {
node: Tioga.Node ~ text;
procs, comments, keywords: INT ¬ 0;
pStart, pLen: INT ¬ 0;
lastChar: CHAR ¬ '\000;
token: REF TEXT ¬ RefText.New[40];
Match:
PROC [a:
REF
READONLY
TEXT]
RETURNS [
BOOL] ~
INLINE {
RETURN [a.length=token.length AND RefText.Equal[a, token]]
};
tokenKind: IO.TokenKind ¬ tokenERROR;
CheckID:
PROC
RETURNS [alpha, keyword:
BOOL ¬
TRUE] = {
a keyword is a token longer than 1 char formed of all capitals and numerics
IF token = NIL THEN RETURN [FALSE, FALSE];
IF token.length = 1 THEN keyword ¬ FALSE;
FOR index:
NAT
IN [0..token.length)
DO
lastChar ¬ token[index];
IF NOT lastChar IN ['A..'Z] AND NOT lastChar IN ['0..'9] THEN keyword ¬ FALSE;
IF NOT CharOps.AlphaNumeric[lastChar] THEN alpha ¬ FALSE;
ENDLOOP;
};
allComments: BOOL ¬ TRUE;
nameLooks: Tioga.Looks ¬ Tioga.noLooks;
mesaLooks: Tioga.Looks ¬ Tioga.noLooks;
stream: STREAM ¬ NIL;
rope: Rope.ROPE ~ TextEditBogus.GetRope[node];
size: INT ~ Rope.Size[rope];
first: INT ~ MIN[start, size];
length: INT ~ MIN[len, size-start];
end: INT ~ start+length;
state: {null, procName, procNameColon, procNameDef} ¬ null;
stream ¬ IO.RIS[Rope.Substr[rope, 0, end]];
IO.SetIndex[stream, first];
mesaLooks['k] ¬ mesaLooks['c] ¬ mesaLooks['n] ¬ TRUE;
nameLooks['n] ¬ TRUE;
IF end > first THEN TextEdit.ChangeLooks[root: root, text: node,
start: first, len: end-first, remove: mesaLooks, event: event];
UNTIL tokenKind = tokenEOF
DO
add, alpha, keyword: BOOL ¬ FALSE;
addLooks, remLooks: Tioga.Looks ¬ Tioga.noLooks;
tokStart, tokLen: INT ¬ 0;
[tokenKind, token] ¬
IO.GetCedarToken[stream, token,
FALSE !
RuntimeError.BoundsFault => { tokenKind ¬ tokenERROR; token.length ¬ 0; CONTINUE }
];
tokLen ¬ token.length;
tokStart ¬ IO.GetIndex[stream]-tokLen;
remLooks ¬ mesaLooks;
SELECT tokenKind
FROM
tokenEOF => NULL;
tokenCOMMENT => {
add ¬ TRUE;
addLooks['c] ¬ TRUE;
remLooks['c] ¬ FALSE;
comments ¬ comments+1;
};
tokenID => {
allComments ¬ FALSE;
[alpha, keyword] ¬ CheckID[];
SELECT
TRUE
FROM
keyword => {
add ¬ TRUE;
addLooks['k] ¬ TRUE;
remLooks['k] ¬ FALSE;
keywords ¬ keywords+1;
IF NOT namifyTypes AND Match["TYPE"] THEN state ¬ null;
IF Match["PUBLIC"] OR Match["PRIVATE"] THEN NULL
ELSE {state ¬ IF state = procNameColon THEN procNameDef ELSE null};
};
alpha
AND token[0]
IN ['A..'Z]
AND state = null => {
save positions & text since may be a proc name
pStart ¬ tokStart;
pLen ¬ tokLen;
state ¬ procName;
};
alpha => {state ¬ IF state = procNameColon AND token[0] IN ['A..'Z] THEN procNameDef ELSE null}
ENDCASE;
};
tokenSINGLE => {
allComments ¬ FALSE;
state ¬
SELECT token[0]
FROM
': => SELECT state FROM procName => procNameColon ENDCASE => null,
ENDCASE => null;
};
ENDCASE => {allComments ¬ FALSE; state ¬ null};
IF add
THEN {
TextEdit.ChangeLooks[root: root, text: node, start: tokStart, len: tokLen,
remove: remLooks, add: addLooks, event: event];
add ¬ FALSE;
addLooks ¬ Tioga.noLooks;
remLooks ¬ mesaLooks;
};
IF state = procNameDef
THEN {
state ¬ null;
IF pLen > 0
THEN {
procs ¬ procs+1;
TextEdit.ChangeLooks[root: root, text: node, start: pStart, len: pLen,
add: nameLooks, event: event];
};
pLen ¬ 0;
};
ENDLOOP;
IF first=0
AND end = size
THEN {
doing entire node; check Comment property
isComment: BOOL ~ allComments AND comments > 0;
IF isComment
AND
NOT node.comment
THEN {
-- change it
rdr: NodeReader.Ref ~ NodeReader.New[node];
xDash: Char.XCHAR ~ Char.Widen['-];
state: {before, dash, after} ← before;
pos: INT ← 0;
FOR pos ← 0, pos+1
WHILE pos<size
DO
xchar: Char.XCHAR ~ NodeReader.FetchChar[rdr, pos];
SELECT state
FROM
before => IF CharOps.XBlank[xchar] THEN NULL
ELSE IF xchar=xDash THEN state ← dash
ELSE EXIT;
dash => IF xchar=xDash THEN state ← after
ELSE EXIT;
after => IF CharOps.XBlank[xchar] THEN NULL
ELSE EXIT;
ENDCASE;
ENDLOOP;
IF state=after
THEN {
commentLooks: Tioga.Looks ¬ Tioga.noLooks;
commentLooks['c] ¬ TRUE;
TextEdit.DeleteText[root: root, text: node, start: 0, len: pos, event: event];
TextEdit.ChangeLooks[root: root, text: node, remove: commentLooks, event: event];
};
NodeReader.Free[rdr];
TextEdit.PutComment[node, TRUE, event];
};
};
RETURN[[procs: procs, comments: comments, keywords: keywords]];
};
SpanMesaLooks:
PUBLIC
PROC [root: Tioga.Node, span: Tioga.Span,
event: Event ¬
NIL]
RETURNS [spanResult: MesaLooksResult ¬ [0, 0, 0]] ~ {
DoMesaLooks:
PROC [node: Tioga.Node, start, len:
INT]
RETURNS [stop:
BOOL ¬
FALSE] ~ {
IF node.comment
AND start=0
AND len>=TextEdit.Size[node]
THEN { -- skip the entire comment node -- }
ELSE {
textResult: MesaLooksResult ~ MesaLooks[root, node, start, len, event];
spanResult.procs ¬ spanResult.procs+textResult.procs;
spanResult.comments ¬ spanResult.comments+textResult.comments;
spanResult.keywords ¬ spanResult.keywords+textResult.keywords;
};
};
EditSpanSupport.Apply[span, DoMesaLooks];
};
END.