IMPLEMENTATION MODULE Decoder; FROM SYSTEM IMPORT TSIZE; FROM Lib IMPORT IncAddr; FROM Memory IMPORT ALLOCATE, AddMarker, MarkNeeded; FROM FIO IMPORT File, Create, Close, Seek, GetPos, WrChar, WrStr, WrLn, WrInt, WrLngHex, IOresult; FROM Buffers IMPORT output, FlushOut, WriteChars, CharPtr, CharSet; FROM Machine IMPORT EmptyClosure, link, HandlePackage, Reduce, Envelope, Root, result; FROM Machine IMPORT wPackage, tempDef, MakePrimitive, MakeDef, MakePacked, ExtractPacked; FROM Machine IMPORT ChangeDefinition, NewLayer, StartLayer, PopLayer, Equal; FROM Machine IMPORT Copy, RemoveEnv, MarkLink, Join; FROM Library IMPORT wChar, wCharSet, wString, wNumber, wError, errorCodes; FROM Library IMPORT wStruct, wProperty, wValue, wFile, wDescription; FROM Library IMPORT wAddProp, wAddValProp; FROM Grammars IMPORT wSequence, wLexSequence, wValSequence, wLexValSequence; FROM Grammars IMPORT wEndSeq, wChoice, wOption; FROM Grammars IMPORT wDummy, wFail, wDone, wDiscard, wRaise, wGrammar, wNext; FROM Grammars IMPORT wSeparator, wFrameGrammar, wCustomGrammar; FROM Grammars IMPORT wFirst, wTail, wIdentGrammar, wIdentifier, wCharSetGrammar; FROM Grammars IMPORT wCharGrammar, wStrGrammar, wNumGrammar, wErrorGrammar, wPackageGrammar; FROM Grammars IMPORT Failure, Confirmation, HoldDummy; FROM Names IMPORT DefName, DefEntry, wName, wMeaning; FROM Names IMPORT AddPrimWord; TYPE PassPtr=POINTER TO PassPoint; PassPoint=RECORD grammar,statement:closure; next:PassPtr END; VAR wStatement:link; oldChar, oldString, oldNumber, oldError, oldRoute:closure; separated:BOOLEAN; path:PassPtr; PROCEDURE PopPath; BEGIN Discard(path); path:=path^.next END PopPath; PROCEDURE PathClosed():BOOLEAN; VAR follow:PassPtr; BEGIN follow:=path; WHILE (follow#NIL) AND ((follow^.grammar#wGrammar^) OR (follow^.statement#wStatement^)) DO follow:=follow^.next END; IF follow=NIL THEN NEW(follow); Use(wGrammar^); Use(wStatement^); follow^.grammar:=wGrammar^; follow^.statement:=wStatement^; follow^.next:=path; path:=follow; RETURN FALSE ELSE RETURN TRUE END END PathClosed; PROCEDURE PhraseTheLetter; VAR chExpect,chIs:CHAR; BEGIN ExtractPacked(wPackage^,chExpect); IF wStatement^#EmptyClosure THEN ChangeDefinition(wChar,HandlePackage); Reduce(wStatement^); ExtractPacked(result,chIs); IF chExpect#chIs THEN Discard(result^); result:=Failure; RETURN END END; WrChar(output,chExpect); Discard(result^); result:=Confirmation END PhraseTheLetter; PROCEDURE PhraseTheString; VAR str:CharPtr; BEGIN IF wStatement^#EmptyClosure THEN ChangeDefinition(wString,HandlePackage); Reduce(wStatement^); IF NOT Equal(wPackage^,result) THEN Discard(result^); result:=Failure; RETURN END END; ExtractPacked(wPackage^,str); WriteChars(str); Discard(result^); result:=Confirmation END PhraseTheString; PROCEDURE PhraseTheCharSet; VAR s:POINTER TO CharSet; ch:CHAR; BEGIN ChangeDefinition(wChar,HandlePackage); Reduce(wStatement^); Discard(result^); IF Root(result)=wChar THEN ExtractPacked(result,ch); ExtractPacked(wPackage^,s); IF ch IN s^ THEN WrChar(output,ch); result:=Confirmation ELSE result:=Failure END ELSE result:=Failure END END PhraseTheCharSet; PROCEDURE PhraseChoice; BEGIN Reduce(wGrammar^); IF Root(result)=wFail THEN Reduce(wNext^) END END PhraseChoice; PROCEDURE PhraseOption; BEGIN Reduce(wGrammar^); IF Root(result)=wFail THEN Discard(result^); result:=HoldDummy END END PhraseOption; PROCEDURE PhraseSeqPrimitive(separate:BOOLEAN); VAR down:closure; downPtr:link; oldPos:LONGCARD; BEGIN downPtr:=Root(wProperty^); Use(downPtr); oldPos:=GetPos(output); StartLayer; IF downPtr#wDiscard THEN IF (downPtr#wRaise) THEN StartLayer; ChangeDefinition(downPtr,EmptyClosure); NewLayer(wStatement^); down:=downPtr^; Use(down); PopLayer; IF down=EmptyClosure THEN Discard(result); result:=Failure; PopLayer; RETURN END; ChangeDefinition(wStatement,down) END ELSE ChangeDefinition(wStatement,EmptyClosure); END; IF PathClosed() THEN Discard(result); result:=Failure; RETURN END; separated:=FALSE; Reduce(wGrammar^); PopPath; PopLayer; IF Root(result)#wFail THEN IF separate AND (GetPos(output)>oldPos) AND NOT separated THEN StartLayer; LinkPrimitive(wChar,PhraseTheLetter); LinkPrimitive(wString,PhraseTheString); ChangeDefinition(wStatement,EmptyClosure); Reduce(wSeparator^); PopLayer; separated:=TRUE END; Reduce(wNext^); IF Root(result)=wFail THEN Seek(output,oldPos) END END END PhraseSeqPrimitive; PROCEDURE PhraseSequence; BEGIN PhraseSeqPrimitive(TRUE) END PhraseSequence; PROCEDURE PhraseLexSequence; BEGIN PhraseSeqPrimitive(FALSE) END PhraseLexSequence; PROCEDURE PhraseEndSequence; BEGIN Discard(result); IF (Root(wStruct^)=wDummy) OR (Root(wStatement^)=Root(wStruct^)) THEN result:=Confirmation ELSE result:=Failure END END PhraseEndSequence; PROCEDURE PhraseNumber; VAR num:INTEGER; BEGIN IF Root(wStatement^)#wNumber THEN Discard(result); result:=Failure; RETURN END; ChangeDefinition(wNumber,HandlePackage); Reduce(wStatement^); ExtractPacked(result,num); WrInt(output,num,0); Discard(result); result:=Confirmation END PhraseNumber; PROCEDURE PhrasePackage; VAR contents:LONGCARD; BEGIN WrChar(output,'['); ExtractPacked(wStatement^,contents); WrLngHex(output,contents,0); WrChar(output,']') END PhrasePackage; PROCEDURE PhraseChar; VAR ch:CHAR; BEGIN IF Root(wStatement^)#wChar THEN Discard(result); result:=Failure; RETURN END; ChangeDefinition(wChar,HandlePackage); Reduce(wStatement^); ExtractPacked(result,ch); WrChar(output, "'"); WrChar(output,ch); WrChar(output, "'"); END PhraseChar; PROCEDURE PhraseCharSET; VAR s:SET OF CHAR; ch:CHAR; first:BOOLEAN; BEGIN IF Root(wStatement^)=wCharSet THEN ChangeDefinition(wCharSet,HandlePackage); Reduce(wStatement^); ExtractPacked(result,s); ch:=MIN(CHAR); WrChar(output,'{'); first:=TRUE; LOOP IF ch IN s THEN IF first THEN first:=FALSE ELSE WrChar(output,',') END; IF (ch=' ') OR (ch='}') OR (ch='{') OR (ch='\') THEN WrChar(output,'\') END; WrChar(output,ch); INC(ch); IF ch IN s THEN REPEAT INC(ch) UNTIL NOT (ch IN s); DEC(ch); WrChar(output,'-'); IF (ch=' ') OR (ch='}') OR (ch='{') OR (ch='\') THEN WrChar(output,'\') END; WrChar(output,ch); INC(ch) END ELSIF ch