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];
IndexPropsImpl: CEDAR PROGRAM
IMPORTS Atom, IO, Rope, Rosary
EXPORTS IndexProps
= 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: ROPENIL]~ {
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;
END.