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] = { 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 => { 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 { 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 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. 6 TiogaMesaOpsImpl.mesa Copyright Σ 1989, 1991, 1992 by Xerox Corporation. All rights reserved. Doug Wyatt, February 27, 1992 7:10 pm PST a keyword is a token longer than 1 char formed of all capitals and numerics save positions & text since may be a proc name doing entire node; check Comment property Κ–(cedarcode) style•NewlineDelimiter ™codešœ™Kšœ Οeœ=™HKšœ)™)—K˜šΟk ˜ Kšœžœ žœ˜Kšœžœ˜%Kšœžœ ˜Kšžœžœžœ žœ ˜EKšœ žœ˜-Kšœžœ˜Kšœžœ žœ˜'Kšœ žœ˜!Kšœ žœ-˜;Kšœžœ ˜Kšœžœ%˜0Kšœ žœ˜%—K˜KšΟnœžœž˜Kšžœ!žœB˜lKšžœ ˜Kšœž˜K˜Kšžœžœžœžœ˜Kšœžœ˜šœžœ ˜5K˜—šœ žœžœ˜K˜—šŸ œžœžœ.žœ žœžœžœžœžœ˜“Kšœ˜Kšœžœ˜#Kšœžœ˜Kšœ žœ ˜Kšœžœžœ˜"šŸœžœžœžœžœžœžœžœ˜˜>Kšœ>˜>K˜——K˜—Kšœ)˜)K˜K˜—Kšžœ˜—…—ΐ