TextFindImpl.mesa
Copyright Ó 1985, 1986, 1987, 1988 by Xerox Corporation. All rights reserved.
derived from EditorFind.Mesa of Laurel 6
Paxton, February 23, 1983 4:13 pm
Maxwell, January 5, 1983 4:03 pm
Russ Atkinson, July 25, 1983 3:21 pm
Michael Plass, October 19, 1987 10:14:15 am PDT
Doug Wyatt, February 19, 1988 11:04:04 am PST
DIRECTORY
Basics USING [BITAND],
Rope USING [Cat, Equal, Fetch, FromChar, Map, MaxLen, ROPE, Size, Substr],
RopeEdit USING [AlphaNumericChar, BlankChar, CharProperty, GetCharProp, LowerCase, MaxLen, UpperCase],
RopeReader USING [Backwards, Create, Get, GetIndex, GetRope, Peek, ReadOffEnd, Ref, SetIndex, SetPosition],
TextFind USING [Finder, PatternErrorCode, Try, TryBackwards],
TextFindPrivate,
TextLooks USING [FetchLooks, Looks, noLooks, Runs],
TextNode USING [Node];
TextFindImpl: CEDAR PROGRAM
IMPORTS Basics, TextLooks, Rope, RopeEdit, RopeReader, TextFind, TextFindPrivate
EXPORTS TextFind, TextFindPrivate
= BEGIN OPEN TextFind;
ROPE: TYPE ~ Rope.ROPE;
noLooks: TextLooks.Looks ~ TextLooks.noLooks;
Node: TYPE ~ TextNode.Node;
MalformedPattern: PUBLIC ERROR [ec:PatternErrorCode] = CODE;
Support
IsWord: PUBLIC PROC [rope: ROPE, at, atEnd: INT] RETURNS [BOOL] = {
IF at > 0 AND RopeEdit.GetCharProp[Rope.Fetch[rope, at-1]] = alphaNumeric THEN RETURN [FALSE];
IF atEnd < Rope.Size[rope] AND RopeEdit.GetCharProp[Rope.Fetch[rope, atEnd]] = alphaNumeric THEN RETURN [FALSE];
RETURN [TRUE];
};
Operations
NameLoc: PUBLIC PROC [finder: Finder, name: ROPE] RETURNS [at, atEnd: INT ← 0] = {
IF finder # NIL THEN {
nameArray: REF TextFindPrivate.NameArray ~ finder.nameArray;
IF nameArray = NIL THEN RETURN;
FOR i: NAT IN [0..nameArray.length) DO
IF Rope.Equal[nameArray[i].name, name] THEN
RETURN [nameArray[i].at, nameArray[i].atEnd];
ENDLOOP;
};
};
NameLooks: PUBLIC PROC [finder: Finder, name: ROPE] RETURNS [TextLooks.Looks ← TextLooks.noLooks] = {
IF finder # NIL THEN {
nameArray: REF TextFindPrivate.NameArray ~ finder.nameArray;
IF nameArray = NIL THEN RETURN;
FOR i: NAT IN [0..nameArray.length) DO
IF Rope.Equal[nameArray[i].name, name] THEN RETURN [nameArray[i].looks];
ENDLOOP;
};
};
Find: PUBLIC PROC [pattern, text: Node, literal, word, ignoreLooks, ignoreCase, looksExact, addBounds: BOOLFALSE, patternStart: INT ← 0, patternLen: INTLAST[INT], textStart: INT ← 0, textLen: INTLAST[INT], interrupt: REF BOOLNIL] RETURNS [found: BOOL, at, atEnd, before, after: INT] = {
[found,at,atEnd,before,after] ←
TextFind.Try[Create[pattern,literal,word,ignoreLooks,ignoreCase,addBounds,patternStart,patternLen],
text,textStart,textLen,looksExact,interrupt]
};
BackwardsFind: PUBLIC PROC [pattern, text: Node, literal, word, ignoreLooks, ignoreCase, looksExact, addBounds: BOOLFALSE, patternStart: INT ← 0, patternLen: INTLAST[INT], textStart: INT ← 0, textLen: INTLAST[INT], interrupt: REF BOOLNIL] RETURNS [found: BOOL, at, atEnd, before, after: INT] = {
[found,at,atEnd,before,after] ← TextFind.TryBackwards[
Create[pattern,literal,word,ignoreLooks,ignoreCase,addBounds,patternStart,patternLen],
text,textStart,textLen,looksExact,interrupt]
};
Create: PUBLIC PROC [pattern: Node, literal, word, ignoreLooks, ignoreCase, addBounds: BOOLFALSE, patternStart: INT ← 0, patternLen: INTLAST[INT]] RETURNS [finder: Finder] = {
patternRope: ROPE ← pattern.rope;
patternRuns: TextLooks.Runs ← pattern.charLooks;
RETURN [CreateFromParts[patternRope, patternRuns, literal, word, ignoreLooks, ignoreCase, addBounds, patternStart, patternLen]]
};
CreateFromRope: PUBLIC PROC [pattern: ROPE, literal, word, ignoreCase, addBounds: BOOLFALSE, patternStart: INT ← 0, patternLen: INTLAST[INT]] RETURNS [finder: Finder] = {
RETURN [CreateFromParts[pattern, NIL, literal, word, TRUE, ignoreCase, addBounds, patternStart, patternLen]]
};
CreateFromParts: PROC [patternRope: ROPE, patternRuns: TextLooks.Runs, literal, word, ignoreLooks, ignoreCase, addBounds: BOOLFALSE, patternStart: INT ← 0, patternLen: INTLAST[INT]] RETURNS [finder: Finder] = {
RETURN[NIL];
}; -- of Create
Forward
SearchRope: PUBLIC PROC [finder: Finder, rope: Rope.ROPE, start: INT ← 0, len: INT ← RopeEdit.MaxLen, interrupt: REF BOOLNIL] RETURNS [found: BOOL, at, atEnd, before, after: INT] = {
[found, at, atEnd, before, after] ← Search[finder, rope, NIL, start, len, FALSE, interrupt]
};
Try: PUBLIC PROC [finder: Finder, text: Node, start: INT ← 0, len: INT ← RopeEdit.MaxLen, looksExact: BOOLFALSE, interrupt: REF BOOLNIL] RETURNS [found: BOOL, at, atEnd, before, after: INT] = {
[found, at, atEnd, before, after] ← Search[
finder, text.rope, text.charLooks, start, len, looksExact, interrupt]
};
Search: PROC [finder: Finder, rope: ROPE, runs: TextLooks.Runs, start: INT, len: INT, looksExact: BOOL, interrupt: REF BOOLNIL] RETURNS [found: BOOL, at, atEnd, before, after: INT] = {
IF finder.wordSearch THEN DO -- repeat search until find a word
[found, at, atEnd, before, after] ← TryToFind[finder, rope, runs, start, len, looksExact, interrupt];
IF NOT found OR (interrupt#NIL AND interrupt^) THEN RETURN; -- failed
IF IsWord[rope, at, atEnd] THEN RETURN; -- got it
start ← after; -- try again
ENDLOOP;
[found, at, atEnd, before, after] ←
TryToFind[finder, rope, runs, start, len, looksExact, interrupt]
};
TryToFind: PROC [finder: Finder, rope: ROPE, runs: TextLooks.Runs, start: INT ← 0, len: INT ← RopeEdit.MaxLen, looksExact: BOOLFALSE, interrupt: REF BOOLNIL] RETURNS [found: BOOL, at, atEnd, before, after: INT] = {
RETURN[FALSE, 0, 0, 0, 0];
}; -- of Try --
Backwards
SearchRopeBackwards: PUBLIC PROC [finder: Finder, rope: Rope.ROPE,
start: INT ← 0, len: INT ← RopeEdit.MaxLen, interrupt: REF BOOLNIL]
RETURNS [found: BOOL, at, atEnd, before, after: INT] = {
[found, at, atEnd, before, after] ←
SearchBackwards[finder, rope, NIL, start, len, FALSE, interrupt]
};
TryBackwards: PUBLIC PROC [finder: Finder, text: Node,
start: INT ← 0, len: INT ← RopeEdit.MaxLen,
looksExact: BOOLFALSE, interrupt: REF BOOLNIL]
RETURNS [found: BOOL, at, atEnd, before, after: INT] = {
[found, at, atEnd, before, after] ←
SearchBackwards[finder, text.rope, text.charLooks,
start, len, looksExact, interrupt]
};
SearchBackwards: PROC [finder: Finder, rope: ROPE, runs: TextLooks.Runs,
start: INT, len: INT, looksExact: BOOL, interrupt: REF BOOLNIL]
RETURNS [found: BOOL, at, atEnd, before, after: INT] = {
IF finder.wordSearch THEN DO -- repeat search until find a word
[found, at, atEnd, before, after] ← TryToFindBackwards[finder, rope, runs, start, len, looksExact];
IF NOT found OR (interrupt#NIL AND interrupt^) THEN RETURN; -- failed
IF IsWord[rope, at, atEnd] THEN RETURN; -- got it
len ← before-start; -- try again
ENDLOOP;
[found, at, atEnd, before, after] ←
TryToFindBackwards[finder, rope, runs, start, len, looksExact, interrupt]
};
TryToFindBackwards: PROC [finder: Finder, rope: ROPE, runs: TextLooks.Runs, start: INT ← 0, len: INT ← RopeEdit.MaxLen, looksExact: BOOLFALSE, interrupt: REF BOOLNIL] RETURNS [found: BOOL, at, atEnd, before, after: INT] = {
RETURN[FALSE, 0, 0, 0, 0];
};
END.