MODULE Speller; IMPORT AGRS,Names,Library,Texts,TextFrames; CONST SetBits= MAX(SET)+1; TabChar= 9X; TYPE SpellingHandlerType= PROCEDURE(t: AGRS.Term): AGRS.Term; SpellingWrapper= POINTER TO RECORD(AGRS.TermDesc) handler: SpellingHandlerType; END; VAR FindSpelling: SpellingHandlerType; spelledTextName,spellingName*,spellingsName*: AGRS.Name; thoughtName*,nameSpellingName,indentionName: AGRS.Name; standardSpellingName: AGRS.Name; sys: SpellingWrapper; collection: AGRS.ClosedClass; spelled: Texts.Text; (* Akumulira spelovani tekst. *) wr: Texts.Writer; firstAttr: BOOLEAN; (* Da li je prvi spelovani atribut ili ne. *) (* Sljedece je u planu. grammarSpellMeanings: AGRS.Class; grammarSpellingName: AGRS.Name; PROCEDURE GrammarTermSpellings(query: AGRS.Term): AGRS.Term; VAR result: AGRS.Term; BEGIN IF query=NIL THEN NEW(result); result.Init(AGRS.lastName); ELSE result:= Grammars.grammarsName.Evaluate(query); Grammars.grammarName.Assign(result); Library.thoughtName.Assign(query); result:= grammarSpellingName.Value(); Library.thoughtName.Restore(); Grammars.grammarName.Restore(); END; RETURN result END GrammarTermSpellings; PROCEDURE GrammarSpelling(): AGRS.Term; BEGIN RETURN grammarSpellMeanings.Evaluate(grammarName); END GrammarSpelling; *) PROCEDURE NewText(): Library.Text; VAR oldLength: LONGINT; BEGIN oldLength:= spelled.len; Texts.Append(spelled,wr.buf); RETURN Library.SubText(spelled,oldLength,spelled.len) END NewText; PROCEDURE pNameSpelling(); VAR s: AGRS.Term; BEGIN s:= Library.NewString(Names.NameSpelling(thoughtName.indirection)); s.Reduce; END pNameSpelling; PROCEDURE SpellAttribute(name: AGRS.Name; VAR t: AGRS.Term); VAR nameSpellPtr: Names.CharPtr; spelled: Library.Text; meaning,indention: AGRS.Term; i: INTEGER; BEGIN IF firstAttr THEN firstAttr:= FALSE; ELSE Texts.Write(wr,','); Texts.Write(wr,' '); END; Texts.WriteLn(wr); indention:= indentionName.Value(); IF indention IS Library.Number THEN FOR i:= 1 TO indention(Library.Number).value DO Texts.Write(wr,TabChar); END; END; nameSpellPtr:= Names.NameSpelling(name); Texts.WriteString(wr,nameSpellPtr^); Texts.Write(wr,'='); spelled:= spelledTextName.indirection(Library.Text); spelled.AppendBuffer(wr.buf); thoughtName.Assign(t); IF (t IS AGRS.SubTerm) & ~(t.indirection IS AGRS.Name) OR (t IS AGRS.Disjunction) THEN Texts.Write(wr,'('); Texts.WriteLn(wr); FOR i:= 1 TO indention(Library.Number).value+1 DO Texts.Write(wr,TabChar); END; indentionName.Assign( Library.NewNumber(indention(Library.Number).value+1)); spelled.AppendBuffer(wr.buf); meaning:= standardSpellingName.Value(); indentionName.Restore(); Texts.Write(wr,')'); meaning(Library.Text).AppendBuffer(wr.buf); ELSE meaning:= FindSpelling(t); END; thoughtName.Restore(); IF meaning IS Library.Text THEN spelled.AppendText(meaning(Library.Text)); ELSE Texts.WriteString(wr,'!@# Unspellable! '); spelled.AppendBuffer(wr.buf); END; END SpellAttribute; PROCEDURE StandardSpelling(query: AGRS.Term): AGRS.Term; VAR result: Library.Text; nameSpellPtr: Names.CharPtr; rest,indention: AGRS.Term; i: INTEGER; BEGIN IF query IS AGRS.SystemTerm THEN IF query=AGRS.GuardTrap THEN Texts.WriteString(wr,'GUARD'); ELSE Texts.WriteString(wr,'#SYSTEM!'); END; RETURN NewText() END; indention:= indentionName.Value(); IF (query IS AGRS.SubTerm) OR (query IS AGRS.Field) OR (query IS AGRS.Disjunction) THEN rest:= FindSpelling(query.indirection); IF query IS AGRS.Disjunction THEN Texts.WriteString(wr,' | '); result:= rest(Library.Text); rest:= query(AGRS.Disjunction).alternative; ELSE IF query.indirection IS AGRS.Name THEN Texts.Write(wr,'.'); ELSE Texts.Write(wr,';'); Texts.WriteLn(wr); FOR i:= 1 TO indention(Library.Number).value DO Texts.Write(wr,TabChar); END; END; result:= rest(Library.Text); rest:= query(AGRS.SubTerm).query; END; result.AppendBuffer(wr.buf); rest:= FindSpelling(rest); result.AppendText(rest(Library.Text)); RETURN result ELSIF query IS AGRS.Name THEN nameSpellPtr:= Names.NameSpelling(query); Texts.WriteString(wr,nameSpellPtr^); RETURN NewText() ELSE IF query IS AGRS.Block THEN Texts.WriteString(wr,'LOCAL '); ELSE nameSpellPtr:= Names.NameSpelling(query.indirection); Texts.WriteString(wr,nameSpellPtr^); END; Texts.Write(wr,'('); result:= NewText(); IF query IS AGRS.Tree THEN WITH query: AGRS.Tree DO spelledTextName.Assign(result); firstAttr:= TRUE; WITH indention: Library.Number DO indentionName.Assign( Library.NewNumber(indention.value+1)); query.ProcessAttributes(SpellAttribute); indentionName.Restore(); ELSE query.ProcessAttributes(SpellAttribute); END; result:= spelledTextName.indirection(Library.Text); spelledTextName.Restore(); END; END; Texts.Write(wr,')'); result(Library.Text).AppendBuffer(wr.buf); IF query IS AGRS.Block THEN Texts.WriteString(wr,' IN '); result(Library.Text).AppendBuffer(wr.buf); rest:= FindSpelling(query.indirection); result.AppendText(rest(Library.Text)); END; RETURN result END; END StandardSpelling; PROCEDURE NumberSpelling(query: AGRS.Term): AGRS.Term; BEGIN WITH query: Library.Number DO Texts.WriteInt(wr,query.value,0); RETURN NewText() ELSE RETURN AGRS.Failure END; END NumberSpelling; PROCEDURE CharSpelling(query: AGRS.Term): AGRS.Term; BEGIN WITH query: Library.Character DO Texts.Write(wr,"'"); Texts.Write(wr,query.value); Texts.Write(wr,"'"); RETURN NewText() ELSE RETURN AGRS.Failure END; END CharSpelling; PROCEDURE CharSetSpelling(query: AGRS.Term): AGRS.Term; VAR ch: CHAR; first: BOOLEAN; BEGIN WITH query: Library.CharSet DO ch:= MIN(CHAR); Texts.Write(wr,'{'); first:= TRUE; LOOP IF ((ch=0DX) & (0AH MOD SetBits IN query.value[0AH DIV SetBits])) THEN ch:= CHR(ORD(ch)+1); END; IF ORD(ch) MOD SetBits IN query.value[ORD(ch) DIV SetBits] THEN IF ~first THEN Texts.Write(wr,','); END; first:= FALSE; IF (ch<=' ') THEN Texts.Write(wr,'\'); CASE ch OF |9X: Texts.Write(wr,'T'); |' ': Texts.Write(wr,'S'); |0AX,0DX: Texts.Write(wr,'N'); |0X: Texts.Write(wr,'0'); ELSE Texts.Write(wr,'?'); END; ELSE IF (ch=',') OR (ch='}') OR (ch='{') OR (ch='\') THEN Texts.Write(wr,'\'); END; Texts.Write(wr,ch); IF (ORD(ch)+1) MOD SetBits IN query.value[(ORD(ch)+1) DIV SetBits] THEN REPEAT ch:= CHR(ORD(ch)+1); UNTIL ~(ORD(ch) MOD SetBits IN query.value[ORD(ch) DIV SetBits]); ch:= CHR(ORD(ch)-1); Texts.Write(wr,'-'); IF (ch=',') OR (ch='}') OR (ch='{') OR (ch='\') THEN Texts.Write(wr,'\'); END; Texts.Write(wr,ch); END; END; END; IF ch