<> <> <> 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] = { <> <<$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] ~ { <> 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.