language-oberon-0.1.1: examples/AGRS/Speller.Mod
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<MAX(CHAR) THEN
ch:= CHR(ORD(ch)+1);
ELSE
EXIT
END
END;
Texts.Write(wr,'}');
RETURN NewText()
ELSE
RETURN AGRS.Failure
END;
END CharSetSpelling;
PROCEDURE StringSpelling(query: AGRS.Term): AGRS.Term;
BEGIN
WITH query: Library.String DO
Texts.Write(wr,'"');
Texts.WriteString(wr,query.value^);
Texts.Write(wr,'"');
RETURN NewText()
ELSE
RETURN AGRS.Failure
END;
END StringSpelling;
PROCEDURE ErrorSpelling(query: AGRS.Term): AGRS.Term;
BEGIN
WITH query: Library.Error DO
CASE query.value OF
Library.NotLogicalType: Texts.WriteString(wr,'Not the logical type!');
|Library.NotNumberType: Texts.WriteString(wr,'Not the number type!');
|Library.NotStringType: Texts.WriteString(wr,'Not the string type!');
|Library.NotCharacterType: Texts.WriteString(wr,'Not the character type!');
|Library.NotTextType: Texts.WriteString(wr,'Not the text type!');
|Library.SyntaxError: Texts.WriteString(wr,'Syntax error!');
|Library.NotFound: Texts.WriteString(wr,'Undefined word meaning!');
END;
RETURN NewText()
ELSE
RETURN AGRS.Failure
END;
END ErrorSpelling;
PROCEDURE VarSpelling(query: AGRS.Term): AGRS.Term;
BEGIN
HALT(255);
Texts.WriteString(wr,'VAR');
RETURN NewText()
END VarSpelling;
PROCEDURE TextSpelling(query: AGRS.Term): AGRS.Term;
BEGIN
RETURN query.Value()
END TextSpelling;
PROCEDURE pSpelling(query: AGRS.Term): AGRS.Term;
VAR
result: AGRS.Term;
BEGIN
IF query IS AGRS.Atomic THEN
thoughtName.Assign(query);
result:= spellingsName.Evaluate(query);
thoughtName.Restore;
RETURN result
ELSE
RETURN StandardSpelling(query);
END;
END pSpelling;
PROCEDURE (t: SpellingWrapper) Reduce;
VAR
text: AGRS.Term;
BEGIN
text:= t.handler(thoughtName.indirection);
text.Reduce;
END Reduce;
PROCEDURE NewSpeller(h: SpellingHandlerType): AGRS.Term;
VAR
newTerm: SpellingWrapper;
BEGIN
NEW(newTerm);
newTerm.Init(Names.SystemRoot);
newTerm.handler:= h;
RETURN newTerm
END NewSpeller;
BEGIN
spelled:= TextFrames.Text("");
Texts.OpenWriter(wr);
NEW(spelledTextName);
spelledTextName.Init(Names.SystemRoot);
NEW(collection);
collection.Init(Names.SystemRoot);
collection.AddProperty(Library.numberName,
NewSpeller(NumberSpelling));
collection.AddProperty(Library.stringName,NewSpeller(StringSpelling));
collection.AddProperty(Library.textName,NewSpeller(TextSpelling));
collection.AddProperty(Library.charName,NewSpeller(CharSpelling));
collection.AddProperty(Library.charSetName,NewSpeller(CharSetSpelling));
collection.AddProperty(Library.errorName,NewSpeller(ErrorSpelling));
collection.AddProperty(Names.VariableRoot,NewSpeller(VarSpelling));
Names.DefinePublicName(standardSpellingName,'StandardSpelling',
NewSpeller(StandardSpelling));
collection.AddProperty(AGRS.otherwise,standardSpellingName);
Names.DefinePublicName(spellingsName,'Spellings',collection);
Names.DefinePublicName(indentionName,'Indention',
Library.NewNumber(0));
Names.AddSystemName(nameSpellingName,'NameSpelling',pNameSpelling);
Names.DefinePublicName(spellingName,'Spelling',
NewSpeller(pSpelling));
Names.AddArgument(spelledTextName,'SpelledTree');
Names.AddArgument(thoughtName,'Thought');
FindSpelling:= pSpelling;
END Speller.