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 SaveDefinition, 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 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); 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 SaveDefinition(wChar); wChar^:=HandlePackage; Reduce(wStatement^); ExtractPacked(result,chIs); IF chExpect#chIs THEN result:=Failure; RETURN END END; WrChar(output,chExpect); result:=Confirmation END PhraseTheLetter; PROCEDURE PhraseTheString; VAR str:CharPtr; BEGIN IF wStatement^#EmptyClosure THEN SaveDefinition(wString); wString^:=HandlePackage; Reduce(wStatement^); IF NOT Equal(wPackage^,result) THEN result:=Failure; RETURN END END; ExtractPacked(wPackage^,str); WriteChars(str); result:=Confirmation END PhraseTheString; PROCEDURE PhraseTheCharSet; VAR s:POINTER TO CharSet; ch:CHAR; BEGIN SaveDefinition(wChar); wChar^:=HandlePackage; Reduce(wStatement^); 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 result:=HoldDummy END END PhraseOption; PROCEDURE PhraseSeqPrimitive(separate:BOOLEAN); VAR down:closure; downPtr:link; oldPos:LONGCARD; BEGIN downPtr:=Root(wProperty^); oldPos:=GetPos(output); SaveDefinition(wStatement); StartLayer; SaveDefinition(wStatement); IF downPtr#wDiscard THEN IF (downPtr#wRaise) THEN StartLayer; SaveDefinition(downPtr); downPtr^:=EmptyClosure; NewLayer(wStatement^); down:=downPtr^; PopLayer; IF down=EmptyClosure THEN result:=Failure; PopLayer; RETURN END; wStatement^:=down END ELSE wStatement^:=EmptyClosure END; IF PathClosed() THEN result:=Failure; RETURN END; separated:=FALSE; Reduce(wGrammar^); PopPath; PopLayer; IF Root(result)#wFail THEN (* IF (Root(wProperty^)=wRaise) AND (Root(result)=wDone) THEN MakeDef(tempDef,wDummy); Join(tempDef,wStatement^); wStatement^:=tempDef END; *) IF separate AND (GetPos(output)>oldPos) AND NOT separated THEN StartLayer; SaveDefinition(wChar); SaveDefinition(wString); SaveDefinition(wStatement); MakePrimitive(wChar^,PhraseTheLetter); MakePrimitive(wString^,PhraseTheString); 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 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 result:=Failure; RETURN END; SaveDefinition(wNumber); wNumber^:=HandlePackage; Reduce(wStatement^); ExtractPacked(result,num); WrInt(output,num,0); 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 result:=Failure; RETURN END; SaveDefinition(wChar); 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 SaveDefinition(wCharSet); 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