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] = { 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] ~ { WITH token SELECT FROM a: ATOM => RETURN [a]; ENDCASE => ERROR KeywordExpectedButMissing; }; PresumePhrases: PROC [kind: ATOM] RETURNS [phrases: Phrases _ NIL] ~ { 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 { 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] = { 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] ~ { 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] ~ { 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. IndexPropsImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Rick Beach, April 6, 1985 9:01:51 pm PST Produce a rope describing the index entry: $KindOfIndex $Phrases {"contents" "formatting"}* [$SeePhrases {"contents" "formatting"}*] [$SortAsPhrases {"contents" "formatting"}*] [$KindOFEntry] verify that this token is an ATOM; do not advance the token list pointer verify that the token list contains $KindOfPhrase {"contents" "formatting"}* return with token list pointing to first token after the phrases unhook the rest of the tokens from phrases list compare two index entries, field by field, but substituting sortAsPhrases for corresponding phrases eliminate duplicates and maintain list in sorted order for each index entry on the list, perform the map action ΚD˜codešœ™Kšœ Οmœ1™—K˜KšΠblœžœž˜Kšžœžœ˜Kšžœ ˜šœžœžœ ˜K˜Kšžœžœžœ˜K˜šΟn œžœžœžœ˜GK™*Kšœ”™”š   œžœžœžœžœ˜Ašžœ žœž˜Kšœžœžœ˜@K˜Kšž˜—K˜—KšœW˜Wšžœžœžœ˜KšœC˜C—šžœžœžœ˜KšœI˜I—šžœž˜"Kšœ:˜:—K˜K˜—•StartOfExpansion[]š   œžœž œžœžœ˜Gš   œžœ žœžœžœ˜1Kšœžœ'™Hšžœžœž˜Kšœžœžœ˜Kšžœžœ˜+—K˜—š  œžœžœžœžœ˜FKšœL™LK™@Kš žœ žœžœžœžœ˜"Kšžœ"žœžœ˜CK–[]šžœ žœ˜-š žœžœžœžœžœž˜>K˜Kšž˜—šžœžœžœ˜Kšœ/™/Kšœžœžœ˜Kšœžœ˜K˜ Kšœ˜—Kšžœ˜K˜—Kšœžœžœžœ˜Kšžœ žœžœ˜Kš œ žœžœžœ žœžœ˜TKš žœ žœžœžœžœžœ˜2Kšœžœ˜Kšœ+˜+K˜K˜&K˜,K˜2šžœ žœžœ˜Kšœ+˜+K˜Kšœ˜—Kšžœ žœžœžœ˜,Kšžœ˜ K˜K™—š œžœžœžœ4˜gK™cKšœ*˜*Kšœ*˜*Kšœ0˜0Kšœ0˜0Kšœžœ˜Kšœžœ˜šžœ žœž˜š œžœ žœžœžœ˜-Kš žœ žœžœžœžœ˜-—š œžœ žœžœžœ˜-Kš žœ žœžœžœžœ˜-—Kšœžœ˜#Kšžœžœžœ˜0Kšœ˜Kšžœ žœžœ˜-Kšžœ žœžœ˜-Kšžœ žœžœ˜-Kšžœ˜—Kšžœ žœžœžœ˜-Kšžœ žœ˜K˜K˜—–[]š œžœž œ*žœ˜fK™6Jšžœ žœžœžœ˜1šžœ˜Jšœžœ˜ š œ˜%šžœ žœž˜,Jšœžœ˜Jšœžœžœ˜%šœ ˜ Jšœ6žœ=žœžœ˜‚Jšœžœ˜ Jšœ˜—Jšžœ˜—J˜—J˜*Jšžœ ˜Jšœ˜—Jšœ˜K˜—–[]š œžœžœ5˜SK™8š œ˜%Jšœžœ˜J˜—J˜*Jšœ˜K˜—Kšœžœ˜'Kšœžœ˜/Kšœžœ˜)Kšœžœ˜&Kšœžœ˜+—K˜K˜Kšžœ˜—…—~