IndexPropsImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Rick Beach, April 6, 1985 9:01:51 pm PST
DIRECTORY
Atom USING [GetPName],
Basics USING [Comparison],
IndexProps USING [IndexEntry, IndexEntryList, IndexEntryProc, IndexEntryRec, Phrases],
IO USING [GetRefAnyLine, RIS, rope, PutFR, EndOfStream],
Rope USING [Cat, Compare, Concat, IsEmpty, ROPE],
Rosary USING [Map, ActionType, FromItem, Substr, CatSegments];
=
BEGIN
OPEN IndexProps;
ROPE: TYPE = Rope.ROPE;
EntryToRope:
PUBLIC PROCEDURE [ix: IndexEntry]
RETURNS [rope:
ROPE] = {
Produce a rope describing the index entry:
$KindOfIndex $Phrases {"contents" "formatting"}* [$SeePhrases {"contents" "formatting"}*] [$SortAsPhrases {"contents" "formatting"}*] [$KindOFEntry]
ConcatPhrases:
PROC [phrases: Phrases]
RETURNS [r:
ROPE ←
NIL]~ {
WHILE phrases #
NIL
DO
r ← Rope.Concat[r, IO.PutFR["\"%q\" ", IO.rope[phrases.first]]];
phrases ← phrases.rest;
ENDLOOP;
};
rope ← Rope.Cat[Atom.GetPName[ix.kindOfIndex], " Phrases ", ConcatPhrases[ix.phrases]];
IF ix.seePhrases #
NIL
THEN
rope ← Rope.Cat[rope, "SeePhrases ", ConcatPhrases[ix.seePhrases]];
IF ix.sortAsPhrases #
NIL
THEN
rope ← Rope.Cat[rope, "SortAsPhrases ", ConcatPhrases[ix.sortAsPhrases]];
IF ix.kindOfEntry # $Ordinary
THEN
rope ← Rope.Cat[rope, " ", Atom.GetPName[ix.kindOfEntry]];
};
RopeToEntry:
PUBLIC
PROCEDURE [rope:
ROPE]
RETURNS [ix: IndexEntry] = {
PresumeAtom:
PROC [token:
REF]
RETURNS [
ATOM] ~ {
verify that this token is an ATOM; do not advance the token list pointer
WITH token
SELECT
FROM
a: ATOM => RETURN [a];
ENDCASE => ERROR KeywordExpectedButMissing;
};
PresumePhrases:
PROC [kind:
ATOM]
RETURNS [phrases: Phrases ←
NIL] ~ {
verify that the token list contains $KindOfPhrase {"contents" "formatting"}*
return with token list pointing to first token after the phrases
IF tokens = NIL THEN RETURN [NIL];
IF PresumeAtom[tokens.first] # kind THEN ERROR UnrecognizedKeyword;
TRUSTED { phrases ← LOOPHOLE[tokens.rest]; };
WHILE tokens.rest #
NIL
AND
ISTYPE[tokens.rest.first,
ROPE]
DO
tokens ← tokens.rest;
ENDLOOP;
IF tokens.rest #
NIL
THEN {
unhook the rest of the tokens from phrases list
t: LIST OF REF ← tokens.rest;
tokens.rest ← NIL;
tokens ← t;
}
ELSE tokens ← tokens.rest;
};
tokens: LIST OF REF;
IF rope.IsEmpty THEN RETURN;
tokens ← IO.GetRefAnyLine[IO.RIS[rope] ! IO.EndOfStream => ERROR MalformedPropRope];
IF tokens = NIL OR tokens.first = NIL THEN RETURN;
ix ← NEW[IndexEntryRec];
ix.kindOfIndex ← PresumeAtom[tokens.first];
tokens ← tokens.rest;
ix.phrases ← PresumePhrases[$Phrases];
ix.seePhrases ← PresumePhrases[$SeePhrases];
ix.sortAsPhrases ← PresumePhrases[$SortAsPhrases];
IF tokens #
NIL
THEN {
ix.kindOfEntry ← PresumeAtom[tokens.first];
tokens ← tokens.rest;
};
IF tokens # NIL THEN ERROR SuperfluousStuff;
RETURN [ix];
};
Compare:
PUBLIC
PROC [ix1, ix2: IndexEntry]
RETURNS [result: Basics.Comparison, unmatched: Phrases] = {
compare two index entries, field by field,
but substituting sortAsPhrases for corresponding phrases
phrase1: IndexProps.Phrases ← ix1.phrases;
phrase2: IndexProps.Phrases ← ix2.phrases;
sortAs1: IndexProps.Phrases ← ix1.sortAsPhrases;
sortAs2: IndexProps.Phrases ← ix2.sortAsPhrases;
a: ROPE;
b: ROPE;
UNTIL phrase1 =
NIL
DO
a ←
IF sortAs1 #
NIL
THEN sortAs1.first
ELSE
IF phrase1 # NIL THEN phrase1.first ELSE NIL;
b ←
IF sortAs2 #
NIL
THEN sortAs2.first
ELSE
IF phrase2 # NIL THEN phrase2.first ELSE NIL;
result ← Rope.Compare[a, b, FALSE];
IF result # equal THEN RETURN [result, phrase1];
phrase1 ← phrase1.rest;
IF sortAs1 # NIL THEN sortAs1 ← sortAs1.rest;
IF phrase2 # NIL THEN phrase2 ← phrase2.rest;
IF sortAs2 # NIL THEN sortAs2 ← sortAs2.rest;
ENDLOOP;
IF phrase2 # NIL THEN RETURN [less, phrase1];
RETURN [equal, NIL];
};
AddEntryToList:
PUBLIC
PROCEDURE [ix: IndexEntry, ixList: IndexEntryList]
RETURNS [IndexEntryList] ~ {
eliminate duplicates and maintain list in sorted order
IF ixList = NIL THEN RETURN [Rosary.FromItem[ix]]
ELSE {
n: INT ← 0;
CheckAndInsert: Rosary.ActionType ~ {
SELECT Compare[
NARROW[item], ix].result
FROM
equal => quit ← TRUE;
less => { n ← n + 1; quit ← FALSE; };
greater => {
ixList ← Rosary.CatSegments[[Rosary.Substr[ixList, 0, MAX[0, n-1]]], [Rosary.FromItem[ix]], [Rosary.Substr[ixList, n, INT.LAST]]];
quit ← TRUE;
};
ENDCASE;
};
[] ← Rosary.Map[[ixList], CheckAndInsert];
RETURN [ixList];
};
};
MapIndexEntryList:
PUBLIC
PROC [ixList: IndexEntryList, action: IndexEntryProc] ~ {
for each index entry on the list, perform the map action
CallActionProc: Rosary.ActionType ~ {
action[NARROW[item]];
};
[] ← Rosary.Map[[ixList], CallActionProc];
};
MalformedPropRope: PUBLIC ERROR = CODE;
KeywordExpectedButMissing: PUBLIC ERROR = CODE;
UnrecognizedKeyword: PUBLIC ERROR = CODE;
SuperfluousStuff: PUBLIC ERROR = CODE;
MalformedIndexPhrases: PUBLIC ERROR = CODE;