-- TreeFind.mesa
-- written by Bill Paxton, June 1981
-- last edit by Bill Paxton, December 30, 1982 10:30 am
-- This module provides a "Find" operation for text in trees
-- The pattern matching is done by TextFind.Mesa
-- This module simply walks the tree (forward or backwards) applying the text
DIRECTORY
TextFind,
TextNode,
NameSymbolTable,
Rope;
TreeFind: CEDAR DEFINITIONS IMPORTS TextFind =
BEGIN
Ref: TYPE = TextNode.Ref;
RefTextNode: TYPE = TextNode.RefTextNode;
Offset: TYPE = TextNode.Offset;
ROPE: TYPE = Rope.ROPE;
MaxLen: Offset = LAST[Offset];
Finder: TYPE = TextFind.Finder;
Create: PROC [
pattern: RefTextNode, literal, word, ignoreLooks, ignoreCase, addBounds: BOOLEANFALSE,
patternStart: Offset ← 0, patternLen: Offset ← MaxLen]
RETURNS [Finder] = INLINE { RETURN [TextFind.Create[
pattern,literal,word,ignoreLooks,ignoreCase,addBounds,patternStart,patternLen]] };
-- creates a record containing a "compiled" version of the pattern
-- see TextFind.Mesa for more info about patterns
-- if literal is true, each character in pattern is taken literally
-- if word flag is true, pattern only matches if no adjacent letters or digits
-- if ignoreLooks if true, then ignore the looks of the pattern characters
-- if ignoreCase is false, then alpha chars in pattern must match case
-- otherwise, they can match either upper or lower
-- if addBounds is true, add |'s to both ends of pattern
CreateFromRope: PROC [pattern: ROPE, literal, word, ignoreCase, addBounds: BOOLEANFALSE,
patternStart: Offset ← 0, patternLen: Offset ← MaxLen]
RETURNS [Finder] = INLINE { RETURN [TextFind.CreateFromRope[
pattern,literal,word,ignoreCase,addBounds,patternStart,patternLen]] };
CommentControl: TYPE = { includeComments, excludeComments, commentsOnly };
Try: PROC [finder: Finder, first: Ref, start: Offset ← 0,
last: Ref ← NIL, lastLen: Offset ← MaxLen, looksExact: BOOLEANFALSE,
commentControl: CommentControl ← includeComments,
checkType: BOOLEANFALSE, type: TextNode.TypeName ← TextNode.nullTypeName,
checkStyle: BOOLEANFALSE, style: NameSymbolTable.Name ← NameSymbolTable.nullName,
styleProc: PROC [Ref] RETURNS [NameSymbolTable.Name] ← NIL,
interrupt: REF BOOLNIL]
RETURNS [found: BOOLEAN, where: RefTextNode, at, atEnd, before, after: Offset];
-- searches first node beginning at start
-- continues until finds a match or reaches last node
-- seaches lastLen chars in last node; seaches to end of other nodes
-- if finds a match, returns with found = true,
-- at = beginning of match or location corresponding to { in pattern
-- atEnd = end of match or location corresponding to } in pattern
-- after = end of entire match, which may be > atEnd if used } in pattern
-- before = start of entire match, which may be < at if used { in pattern
-- if looksExact is true, then match by equality, else by subset
-- commentControl allows restriction of search to comments/noncomments
-- if checkType is true, then only match in nodes with given type
-- if checkStyle is true, then only match in nodes with given style
-- styleProc is supplied so called can determine style for nodes
-- if just interested in type/style, can pass finder=NIL
-- if interrupt^ becomes true, will stop searching
TryBackwards: PROC [finder: Finder, first: Ref,
len: Offset ← MaxLen, last: Ref ← NIL, lastStart: Offset ← 0,
looksExact: BOOLEANFALSE, commentControl: CommentControl ← includeComments,
checkType: BOOLEANFALSE, type: TextNode.TypeName ← TextNode.nullTypeName,
checkStyle: BOOLEANFALSE, style: NameSymbolTable.Name ← NameSymbolTable.nullName,
styleProc: PROC [Ref] RETURNS [NameSymbolTable.Name] ← NIL,
interrupt: REF BOOLNIL]
RETURNS [found: BOOLEAN, where: RefTextNode, at, atEnd, before, after: Offset];
-- searches first node from start=0 to end=len
-- continues back through tree until finds a match or reaches last node
-- searches from lastStart in last node; searches from 0 in other nodes
Apply: PROC [finder: Finder, first: Ref, proc: ApplyProc, start: Offset ← 0,
last: Ref ← NIL, lastLen: Offset ← MaxLen, looksExact: BOOLEANFALSE,
commentControl: CommentControl ← includeComments,
checkType: BOOLEANFALSE, type: TextNode.TypeName ← TextNode.nullTypeName,
checkStyle: BOOLEANFALSE, style: NameSymbolTable.Name ← NameSymbolTable.nullName,
styleProc: PROC [Ref] RETURNS [NameSymbolTable.Name] ← NIL]
RETURNS [count: LONG INTEGER];
-- finds a span of text and calls proc
ApplyProc: TYPE = PROC [where: RefTextNode, at, atEnd, before, after: Offset]
RETURNS [continue, bumpCount: BOOLEAN, from, delta: Offset];
-- arg's are results from Try
-- if continue is true, Apply will Try again starting at "from" in "where"
-- delta tells change in length caused by the action
-- Apply does the following with delta
-- IF where=last AND lastLen < MaxLen THEN lastLen ← lastLen+delta
-- if bumpCount is true, Apply will increment its result counter
END.