PQuiltProc: Parquet.ModuleGeneratorProc =
BEGIN
BreakProc:
IO.BreakProc =
BEGIN
IF char
IN [
IO.
NUL ..
IO.
SP]
THEN
RETURN[sepr]
END;
-- user parameters
fileName, token, tileSetName: Rope.ROPE;
-- state information
tile: Parquet.Tile;
tiles: Parquet.Design;
module: Parquet.Module;
technology: Parquet.Technology;
prevTile: Parquet.PlacedTile; -- the previous tile placed
prevRow: Parquet.PlacedTile; -- the first tile in the previous row
newRow: BOOL ← TRUE;
orient: Parquet.Orientation ← Parquet.IdentityOrient;
-- constants
mirrorY: Parquet.Orientation ← CDOrient.ComposeOrient[CDOrient.ComposeOrient[CDOrient.rotate90, CDOrient.mirrorX], CDOrient.rotate270];
-- misc
stream: IO.STREAM;
endOfFile: BOOL ← FALSE;
-- query user for parameters
tileSetName ← TerminalIO.RequestRope["(PQuilt version 1) What file contains the tiles? "];
[tiles, technology, ] ← Parquet.ReadDesign[tileSetName];
IF tiles =
NIL
THEN
BEGIN
TerminalIO.WriteRope["Could not load tiles.\n"];
GOTO Punt;
END;
fileName ← TerminalIO.RequestRope["What file contains the array description? "];
stream ←
FS.StreamOpen[fileName !
FS.Error =>
IF error.group = user
THEN {
TerminalIO.WriteRope["Could not open input file: '"];
TerminalIO.WriteRope[error.explanation];
TerminalIO.WriteRope["'.\n"];
GOTO Punt;
}];
-- initialize data structures
[module, prevTile] ← Parquet.NewModule[technology];
prevRow ← prevTile;
-- main body of module generator
DO
[token, ] ← IO.GetTokenRope[stream, BreakProc !IO.EndOfStream => {endOfFile ← TRUE; CONTINUE} ];
IF endOfFile
THEN
BEGIN
-- pass result back to Parquet
TerminalIO.WriteRope["PQuilt done.\n"];
RETURN[module];
END;
SELECT
TRUE
FROM
(Rope.Equal[token, "$NEWROW", FALSE]) => newRow ← TRUE;
(Rope.Fetch[token, 0] = '#) =>
BEGIN
newOrient: Parquet.Orientation ← Parquet.IdentityOrient;
FOR i:
INT
IN [1..Rope.Length[token])
DO
badMessage: BOOL ← FALSE;
SELECT Rope.Fetch[token, i] FROM
-- remember that Parquet's rotations are counter-clockwise
'= => newOrient ← CDOrient.ComposeOrient[newOrient, orient];
'1 => newOrient ← CDOrient.ComposeOrient[newOrient, CDOrient.rotate180];
'2 => newOrient ← CDOrient.ComposeOrient[newOrient, CDOrient.rotate90];
'9 => newOrient ← CDOrient.ComposeOrient[newOrient, CDOrient.rotate270];
'x, 'X => newOrient ← CDOrient.ComposeOrient[newOrient, CDOrient.mirrorX];
'y, 'Y => newOrient ← CDOrient.ComposeOrient[newOrient, mirrorY];
ENDCASE =>
BEGIN
IF ~badMessage
THEN
BEGIN
TerminalIO.WriteRope["Bad rotation specification: '"];
TerminalIO.WriteRope[token];
TerminalIO.WriteRope["' -- illegal characters ignored.\n"];
badMessage ← TRUE;
END;
END;
ENDLOOP;
orient ← newOrient;
END;
(
TRUE) =>
BEGIN
tile ← Parquet.GetTile[tiles, token];
IF tile =
NIL
THEN
BEGIN
TerminalIO.WriteRope["Could not find tile '"];
TerminalIO.WriteRope[token];
TerminalIO.WriteRope["'.\n"];
GOTO Punt;
END;
IF newRow
THEN
BEGIN
prevRow ← prevTile ← Parquet.AdjacentTile[prevRow, tile, below, orient];
newRow ← FALSE;
END
ELSE
prevTile ← Parquet.AdjacentTile[prevTile, tile, rightOf, orient];
END;
ENDCASE;
ENDLOOP;
EXITS
Punt => RETURN[NIL];
END;