IMPLEMENTATION MODULE ParseLow;
FROM SYSTEM IMPORT TSIZE;
FROM Buffers IMPORT Rewind, position;
FROM Memory IMPORT ALLOCATE, AddMarker, DropMarker, MarkNeeded;
FROM Machine IMPORT MarkLink, MarkClosure, tempDef, EmptyClosure;
FROM Machine IMPORT closure, result, MakeDef, Reduce;
FROM Machine IMPORT Root, AddEnv, AddValuedEnv, Join, Copy;
FROM Library IMPORT wProperty, wStruct;
FROM Grammars IMPORT wDummy, wFail, wRaise, wDiscard, wGrammar, wNext;
FROM Grammars IMPORT Failure, HoldDummy;
TYPE
RestPtr=POINTER TO RestRec;
RestRec=RECORD
grammar:closure;
next:RestPtr
END;
ParsedPtr=POINTER TO ParsedRec;
ParsedRec=RECORD
CASE leaf:BOOLEAN OF
FALSE:
property:closure;
valued:BOOLEAN
|TRUE:
result:closure
END;
next:ParsedPtr
END;
StackPtr=POINTER TO StackRec;
StackRec=RECORD
restRec:RestRec;
prevLink:ParsedPtr;
pos:LONGCARD;
(* layer:CARDINAL; *)
next:StackPtr
END;
VAR
current:closure;
parsed,parsedNew,linked:ParsedPtr;
rest,restNew:RestPtr;
stack,stackNew:StackPtr;
(* layers:CARDINAL; *)
PROCEDURE MarkRest(list:RestPtr);
VAR
fresh:BOOLEAN;
BEGIN
WHILE list#NIL DO
MarkNeeded(list,TSIZE(RestRec),fresh);
IF NOT fresh THEN
RETURN
END;
MarkClosure(list^.grammar);
list:=list^.next
END
END MarkRest;
PROCEDURE MarkParsed(list:ParsedPtr);
VAR
fresh:BOOLEAN;
BEGIN
WHILE list#NIL DO
MarkNeeded(list,TSIZE(ParsedRec),fresh);
IF NOT fresh THEN
RETURN
END;
IF list^.leaf THEN
MarkClosure(list^.result)
ELSE
MarkClosure(list^.property)
END;
list:=list^.next
END
END MarkParsed;
PROCEDURE MarkAll;
VAR
s:StackPtr;
fresh:BOOLEAN;
BEGIN
s:=stack;
fresh:=TRUE;
WHILE fresh AND (s#NIL) DO
MarkNeeded(s,TSIZE(StackRec),fresh);
MarkRest(s^.restRec.next);
MarkParsed(s^.prevLink);
s:=s^.next
END;
MarkClosure(current);
MarkRest(rest);
MarkParsed(parsed)
END MarkAll;
PROCEDURE MarkLinked;
BEGIN
MarkParsed(linked)
END MarkLinked;
PROCEDURE LinkParsed;
VAR
swap:ParsedPtr;
BEGIN
linked:=NIL;
AddMarker(MarkLinked);
WHILE parsed#NIL DO
IF parsed^.leaf THEN
swap:=parsed^.next;
parsed^.next:=linked;
linked:=parsed;
parsed:=swap;
ELSE
IF Root(parsed^.property)#wDiscard THEN
IF Root(parsed^.property)=wRaise THEN
IF Root(linked^.result)#wDummy THEN
IF linked^.leaf THEN
Copy(linked^.result,tempDef);
linked^.next^.leaf:=FALSE
ELSE
tempDef:=linked^.result
END;
Join(tempDef,linked^.next^.result);
linked^.next^.result:=tempDef
END
ELSE
IF linked^.next^.leaf THEN
tempDef:=linked^.next^.result;
Copy(tempDef,linked^.next^.result);
linked^.next^.leaf:=FALSE
END;
IF parsed^.valued THEN
AddValuedEnv(linked^.next^.result,Root(parsed^.property),linked^.result)
ELSE
AddEnv(linked^.next^.result,Root(parsed^.property),linked^.result)
END
END
END;
linked:=linked^.next;
parsed:=parsed^.next
END
END;
tempDef:=EmptyClosure;
IF linked^.next=NIL THEN
result:=linked^.result
ELSE
result:=Failure
END;
DropMarker
END LinkParsed;
PROCEDURE ParsePrimitive;
VAR
prevPos:LONGCARD;
BEGIN
NEW(stackNew);
WITH stackNew^ DO
(* layer:=layers; *)
restRec.next:=rest;
restRec.grammar:=NIL;
prevLink:=parsed;
pos:=MAX(LONGCARD);
next:=stack
END;
stack:=stackNew;
(* layers:=0; *)
NEW(rest);
WITH rest^ DO
grammar:=wGrammar^;
next:=NIL
END;
parsed:=NIL;
REPEAT
REPEAT
buildTree:=TRUE;
current:=rest^.grammar;
rest:=rest^.next;
Reduce(current);
IF Root(result)=wFail THEN
rest:=NIL
ELSIF (parsed#NIL) AND NOT parsed^.leaf AND
((Root(parsed^.property)=wDiscard) OR
(Root(parsed^.property)=wRaise) AND (Root(result)=wDummy)) THEN
parsed:=parsed^.next
ELSE
NEW(parsedNew);
parsedNew^.leaf:=TRUE;
parsedNew^.result:=result;
parsedNew^.next:=parsed;
parsed:=parsedNew
END
UNTIL rest=NIL;
IF Root(result)#wFail THEN
WHILE stack^.pos#MAX(LONGCARD) DO
stack:=stack^.next
END;
LinkParsed;
(* WHILE layers>0 DO
PopLayer;
DEC(layers)
END *)
END;
prevPos:=stack^.pos;
IF prevPos#MAX(LONGCARD) THEN
Rewind(prevPos)
END;
rest:=ADR(stack^.restRec);
parsed:=stack^.prevLink;
(* WHILE layers>stack^.layer DO
PopLayer;
DEC(layers)
END;
layers:=stack^.layer; *)
stack:=stack^.next;
UNTIL prevPos=MAX(LONGCARD);
rest:=rest^.next;
current:=NIL
END ParsePrimitive;
PROCEDURE ParseSequencePrimitive(valuedProperty:BOOLEAN);
VAR
buildOld:BOOLEAN;
BEGIN
NEW(restNew);
restNew^.grammar:=wNext^;
restNew^.next:=rest;
rest:=restNew;
buildOld:=buildTree;
IF Root(wProperty^)=wDiscard THEN
buildTree:=FALSE
END;
NEW(parsedNew);
WITH parsedNew^ DO
leaf:=FALSE;
property:=wProperty^;
valued:=valuedProperty;
next:=parsed;
END;
parsed:=parsedNew;
Reduce(wGrammar^);
buildTree:=buildOld
END ParseSequencePrimitive;
PROCEDURE ParseEndSequence;
BEGIN
result:=wStruct^
END ParseEndSequence;
PROCEDURE ParseChoice;
BEGIN
NEW(stackNew);
WITH stackNew^ DO
(* StartLayer;
INC(layers);
layer:=layers; *)
pos:=position;
prevLink:=parsed;
next:=stack;
stack:=stackNew;
restRec.grammar:=wNext^;
restRec.next:=rest
END;
Reduce(wGrammar^)
END ParseChoice;
PROCEDURE ParseOption;
BEGIN
NEW(stackNew);
WITH stackNew^ DO
(* StartLayer;
INC(layers);
layer:=layers; *)
pos:=position;
prevLink:=parsed;
next:=stack;
stack:=stackNew;
restRec.grammar:=wGrammar^;
restRec.next:=rest
END;
result:=HoldDummy
END ParseOption;
BEGIN
rest:=NIL;
stack:=NIL;
parsed:=NIL;
current:=NIL;
AddMarker(MarkAll)
END ParseLow.