The program described here is the implementation of the TREE-META dimensional flowchart definition (see Appendix 1) to generate FR80 produced dimensional flowcharts. (Ref: FR80 Technical Paper 21 - DRIVER SOFTWARE CONSTRUCTION).
The dimensional flowchart generator is a program to which the input is a machine readable specification of the flowchart, and the output is a dimensional flowchart drawn on FR80.
The program is written in ALGOL, and it uses the GROATS graphics package.
The top-down structured design approach was followed in developing the program.
A dimensional flowchart definition consists of:
DIM FLOWCHART: = .NAME '\' NODE;
drawing the flowchart consists of:
The 3-D aspect is implemented by recognizing 3 levels:
A statement can be either an ACTION statement or a CONDITIONAL statement. To differentiate between these 2 categories a conditional expression is denoted by drawing a half square around the beginning of its text.
The idea of scoped comments is implemented by using labels.to:
The following dimensional flowchart represents the physical layout (construction), of the program. It was generated using the data file listed in Appendix 4.
The dimensional flowchart representing the logical flow of the program is listed at the end of this paper.
DRAW NODE DIMFLOWCHART:=.NAME'\' NODE
SERIAL := STATEMENT(REFINE/EMPTY) $ (PARALLEL)Draw a SERIAL consists of:
DRAW HORIZONTAL LINE. DRAW NODE.
STATEMENT:= ACTION/CONDITIONALDraw a statement consists of:
ALGOBEY (S)
This is a semi-compiled procedure which issues GEORGE commands from within the ALGOL program. It is a Boolean procedure; it returns "true" if the command is issued successfully, and "false" otherwise (see Appendix 3).
Because of the recursive nature of the procedures used in the program, it may be helpful to list the interaction between different procedures. Below are 3 different representations of the procedures hierarchy and interaction.
NAME OF PROCEDURE | PROCEDURE CALLED |
---|---|
DRAW THE FLOWCHART | GCHAR DRAW NEXT LEVEL PRINT OUT POINTERS DRAW NODE LOOP ERROR |
DRAW NODE | DRAW SERIAL LOOP ERROR DRAW HORIZONNTAL LINE DRAW NODE GET NON BLANK CHAR |
DRAW SERIAL | DRAW VERTICAL LINE DRAW STATEMENT GET NON BLANK CHAR DRAW NEXT LEVEL DRAW NODE PRINT OUT POINTERS DRAW HORIZONTAL LINE LOOP ERROR |
DRAW STATEMENT | GET NON BLANK CHAR LOOP ERROR GCHAR |
LOOP ERROR | PRINT OUT POINTERS |
VAR NAMES (1) |
SCOPE (2) |
DESCRIPTION |
---|---|---|
TR tr 5 |
Block 0 | Set to 'true' if the GEORGE command is issued successfully, and false otherwise. |
XMAX,YMAX | Block 1 | Delimits size of single frame of output. |
CH WIDTH, CH HEIGHT | Block 1 | Defines character width and height respectively in the selected region units (see Appendix 2). |
CH SPACE | Block 1 | Sets up the horizontal spacing left between 2 consecutive characters (see Appendix 2). |
WIDTH 3 CH CH 2 HEIGHT |
Block 1 | Set up horizontal and vertical offset for the starting position of drawing next level (diagonal line) (see Appendix 2). |
DTB | Block 1 | Length of vertical line between two serial statements (see Appendix 2). |
DRP | Block 1 | Horizontal offset for next parallel node. |
DELTA MLP | Block 1 | Horizontal offset for minimum length parallel. |
RJ, RK | Block 1 | Used as loop parameters in drawing the big picture (ie in defining the new LIMITS). |
TOP, LEFT, BOTTOM, RIGHT | Block 2 | These are the pointers throughout DRAW 3.D FLOWCHART to update the drawing positions, they are also used as formal parameters of the program procedures. |
CH | A character; defined in all procedures. | |
J | Used as a loop counter throughout. | |
A, B | PROC MAX | Formal parameters of the procedure. |
CHARACTER | PROC GCHAR | Formal parameter of the procedure. |
NEW LEFT, NEW RIGHT, NEW TOP, NEW BOTTOM | PROC DRAW THE FLOWCHART | Used to reset pointers to new positions to draw next level. They are redefined in DRAW NODE to control drawing positions; they are updated after a drawing instruction has been issued. |
DIAGONAL | PROC DRAW NEXT LEVEL | Length of X and Y components of diagonal line. |
MAX NEW RIGHT, MAX NEW LEFT | DRAW NODE | Pointers to control drawing positions, updated after a drawing instruction has been issued. |
TOP MLP, LEFT MLP, BOTTOM MLP, RIGHT MLP, MAX BOTTOM MLP, MAX RIGHT MLP | DRAW NODE | Pointers to denote coordinates of minimum length parallel; used in calling DRAW HORIZONTAL LINE for m.l.p. |
TOP SERIAL, LEFT SERIAL, BOTTOM SERIAL, RIGHT SERIAL | DRAW SERIAL | Pointers to denote serial drawing positions. |
NEXT TOP, NEXT LEFT, NEXT RIGHT, NEXT BOTTOM | DRAW SERIAL | Pointers to denote coordinates for drawing next node. |
TOP PARA, LEFT PARA, BOTTOM PARA, RIGHT PARA | DRAW SERIAL | Denote coordinates for drawing positions of minimum width parallel. |
TOP TEXT, RIGHT TEXT | DRAW STATEMENT | Denote X coordinates of starting and finishing of text. |
ACTION | DRAW STATEMENT | Set to 'true' if starting character is (') (ie SERIAL) and 'false' if starting character is (?) (ie CONDITIONAL). |
(1) Variable names are of integer type except the following: RJ, RK : REAL TRS, ACTION : BOOLEAN
(2) BLOCK O: the most outer block BLOCK 1 : the second most outer block BLOCK 2: the draw 3-D flow block
Data is presented in a form which uses the following symbols as reserve symbols to implement different features of a 3-D flowchart.
SYMBOL | MEANING | DRAWING ACTION |
---|---|---|
! | Denotes R-dimension (ie next level) | Draw diagonal line |
# | Denotes the end of a node | Reset pointers to previous level |
? text ? | Denotes a conditional node | Draw a half square around text |
' text ' | Denotes an action statement | Text without half square |
- | Denotes a serial-parallel | Draw horizontal line of length DRP followed by DRAW NODE |
= | Denotes a minimum length parallel | Draw horizontal line of length DELTA MLP followed by DRAW NODE |
The first data record is of the form:
N .NAME text;
where:
N is the scaling factor for the whole flowchart, text describes the title of the flowchart.
The second record will be always a R dimension symbol (!).
the last data record is of the form:
. text ;
Note: An example of the input data used to generate the physical construction of the program is included in Appendix 4.
ERROR IN COPY TITLE.
ERROR MESSAGE | CAUSE |
---|---|
ERROR IN COPY TITLE | Either: (a) text exceeding 82-characters (b) (;) missing |
.ERROR | (.) end of data marker not encountered |
ERROR IN NON BLANK CHAR | Loop to get non blank characters exhausted |
ONE OR MORE SERIALS ERROR | More than 5000 serials |
MIN LEN PAR LOOP ERROR | More than 50 consecutive min len Parallel nodes |
# ERROR | (#) end of node marker not encountered (often when a statement is started by an illegal character) |
PARALLEL LOOP ERROR | More than 82 consecutive serial - parallels encountered |
? OR ' ERROR | Wrong statement type (ie not an action nor a conditional statement) |
WRITE OUT TEXT ERROR | More than 999 chs in statement text |
ACTION OR ' OR ? ERROR | Delimiters of a statement not compatible (eg starting delimiter ', and terminating delimiter ?) |
A LOOP ERROR HAS OCCURRED | This will normally follow the error messages: (a) one or more serials error (b) parallel loop error (c) write out text error (d) .ERROR (e) min len par loop error |
Throughout the program, a number of trace statements recording the progress of the program execution are built in as 'comments' statements of the form:
'COMMENT' WRITE TEXT ('text'); 'COMMENT' PRINT OUT POINTERS (top, left, bottom, right);
Leaving out the ALGOL words 'COMMENT' will result in a full trace of the program execution; this is to be used in extreme necessity as it results in a large amount of printer paper.
META DIMFLOWCHART DIMFLOWCHART := .NAME '\' FLOWC ; FLOWC := NODE ; NODE := SERIAL $ (SERIAL) '#' ; SERIAL := STATEMENT (REFINE/.EMPTY) $ (PARALLEL) ; REFINE := '\. FLOWC ; PARALLEL := '¬' FLOWC ; STATEMENT := ACTION/CONDITIONAL ; ACTION := 'TEXT' ; CONDITIONAL := '?' BOOLEAN EXPRESSION OR TEXT '?' ;
1 CH WIDTH = 8 2 CH HEIGHT = 8 3 CH SP = 2 4 CH 2 HEIGHT = 16 5 DIAGONAL = 40 6 WIDTH 3 CH = 20 7 DTB = 20 8 DRAW NEXT LEVEL 9 DRAW VERTICAL LINE
This procedure issues GEORGE commands from within an ALGOL program. Most commands which do not cause deletion or suspension of the program may be issued by this procedure. The routine returns TRUE if the GEORGE command was issued successfully and FALSE otherwise.
Since GEORGE parameter substitution involving use of % characters these cannot be used directly in an ALGOL string, the routine will convert any £ characters in the string to % characters before issuing the command. Parameter substitution is therefore accomplished using £ characters in the original string in positions where GEORGE would require % characters. % characters in the original string will of course be converted at compile time into space characters.
(a) In the following example NEWFILE will he assigned to *CRO
'IF' 'NOT' ALGOBEY ('('AS%*CRO,NEWFILE')') 'THEN' 'BEGIN' 'COMMENT' ERROR ROUTINE; ... ... ... 'END' 'ELSE' 'BEGIN' 'COMMENT' COMMAND OBEYED OK;
(b) If a call to the macro that runs a program includes the parameter:
PARAM (F1 FILE1, F2 FILE2)
then to issue the GEORGE commands:
AS *CRO,%(F1) AS *CPO,%(F2)
from within the ALGOL program, the calls to ALGOLOBEY should be:
IF' 'NOT' (ALGOBEY('('AS%*CRO ,£(FI')')) 'AND' ALGOBEY('('AS%*CPO,£(F2)')')) 'THEN' 'GOTO' L99;
1500 .NAME FLOWB-SRC; | 'PROGRAM DESCRIPTION' 'BEGIN' | 'DECLARE VARIABLES &,INITIALISE PARAMS' 'BEGIN' | 'DEFINE LIMITS AND REGIONS' 'DRAW 3D FLOW CHART' | 'DECLARE VARIABLES' 'DEFINE PROCEDURES' | 'PROCEDURE MAX' 'INTEGER PROCEDURE GET CHAR' 'PROCEDURE DRAW THE FLOW CHART' 'PROCEDURE GET NON BLANK CHAR' 'PROCEDURE DRAW NEXT LEVEL' 'PROCEDURE PRINTOUT POINTERS' 'PROCEDURE DRAW NODE' 'PROCEDURE DRAW SERIAL' 'PROCEDURE DRAW VERTICAL LINE' 'PROCEDURE DRAW HORIZONTAL LINE' 'PROCEDURE LOOP ERROR' # 'DRAW BIG PICTURE' | 'LOOP' | 'LOOP' | 'INITIALISE PARAMS& SELECT ISO UNITS' 'CALL DRAW THE FLOW CHART' 'ADVANCE FILM' 'END' # 'END' # 'END' # 'END' # 'END' # 'END' # 'END' # .END OF FLOW; ****
08/02/77 COMPILED BY XALH MK. 1C 'LIST' (LP) 'LIBRARY' (ED,A.SUBROUTINES) 'PROGRAM' (SWA) 'INPUT' 0,7=CR0 'INPUT' 5 = TR5 'OUTPUT' 0=LP0 'OUTPUT' 2=LP0 'OUTPUT' 4=LP0 'OUTPUT' 5 = LP5 'OUTPUT' 12= LP1 'OUTPUT' 13=LP2 'SPACE' 15000 'BEGIN' 'BOOLEAN' 'PROCEDURE' ALGOBEY (S); 'STRING' S; 'EXTERNAL'; 'BOOLEAN' TR5; SELECT CAMERA (7); IDENTIFICATION; 'BEGIN' 'INTEGER' XMAX,YMAX; 'INTEGER' CH HEIGHT,CH WIDTH; 'INTEGER' HEIGHT 2 CH,WIDTH 3 CH,CH SP; 'INTEGER' DTB,DRP,DNS; 'INTEGER' DELTA MLP; 'REAL' RJX,RKY; 'REAL' TOP WINDOW,LEFT WINDOW,BOTTOM WINDOW,RIGHT WINDOW; 'BOOLEAN' FIRST TIME, INTERSECT; 'INTEGER' COUNT, NODE NUM; 'INTEGER' 'ARRAY' NODE TABLE [1:2,1:5000]; 'INTEGER' BLANK,SHRIEK,HYPHEN,BACKSLASH,HASH; 'INTEGER' ENDLINE,EQUALS,QUERY,SQUOTE,SEMICOLON; 'INTEGER' FULLSTOP; BLANK := CODE('('%')'); SHRIEK := CODE('('!')'); HYPHEN := CODE('('-')'); BACKSLASH := CODE('('$')'); HASH := CODE('('#')'); ENDLINE := CODE('('EL')'); EQUALS := CODE('('=')'); QUERY := CODE('('?')'); SQUOTE := COOE('(''')'); SEMICOLON := CODE('(';')'); FULLSTOP := CODE('('.')'); SELECT INPUT (5): XMAX := YMAX := READ; CH HEIGHT := CH WIDTH := 8; HEIGHT 2 CH := 16; WIDTH 3 CH := 20; CH SP := 2; DNS := 10; 'COMMENT' NODE SPACING; DTB := 5; 'COMMENT' LENGTH OF VERTICAL STATEMENT LINE: DRP := 40; 'COMMENT' HORIZONTAL OFFSET FOR NEXT PARALLEL NODE; DELTA MLP := 100; 'COMMENT' HORIZ OFFSET FOR ML PARAS; 'BEGIN' LIMITS ( 0,0,16383,16383 ); REGION ( 1995,1995,14393,14393,0 ); LIMITS ( 0,YMAX,XMAX,0 ); REGION ( 0,YMAX,XMAX,0,1 ); SELECT REGION (1); LIMITS ( 0,YMAX,XMAX,0 ); CHARACTER SIZE ( CH HEIGHT,CH WIDTH ); 'BEGIN' DRAW 30 FLOWCHART: 'BEGIN' 'INTEGER' TOP,LEFT,BOTTOM,RIGHT; 'INTEGER' CH; 'INTEGER' J; 'INTEGER' 'PROCEDURE' MAX (A,B); 'VALUE' A,B; 'INTEGER' A,B; 'BEGIN' MAX := 'IF' A 'GT' B 'THEN' A 'ELSE' B; 'END'; 'INTEGER' 'PROCEDURE' GCHAR (CHARACTER); 'VALUE' CHARACTER; 'INTEGER' CHARACTER; 'BEGIN' 'COMMENT' NEWLINE {1); 'COMMENT' PRINT CH (CH); 'COMMENT' PRINT ( CHARACTER,12,0 ); 'IF' CHARACTER= ENDLINE 'THEN' 'BEGIN' WRITE TEXT ('('EL%ERROR')'); 'GOTO' FINI; 'END'; 'IF' CHARACTER 'GE' 0 'AND' CHARACTER 'LE' 9 'THEN' CHARACTER := CHARACTER + 16 'ELSE' 'IF' CHARACTER 'GE' 3873 'AND' CHARACTER 'LE' 3898 'THEN' CHARACTER := CHARACTER - 3840 'ELSE' 'IF' CHARACTER = 29 'OR' CHARACTER = 30 'THEN' CHARACTER := CHARACTER + 1 'ELSE' 'IF' CHARACTER = 24 'OR' CHARACTER = 25 'THEN' CHARACTER := CHARACTER - 16 'ELSE' 'IF' CHARACTER = 18 'OR' CHARACTER = 31 'THEN' CHARACTER := CHARACTER - 16 'ELSE' 'IF' CHARACTER = 17 'OR' CHARACTER = 21 'THEN' CHARACTER := CHARACTER + 49 'ELSE' 'IF' CHARACTER = 16 'THEN' CHARACTER := 1 'ELSE' 'IF' CHARACTER = 28 'THEN' CHARACTER := 10 'ELSE' 'IF' CHARACTER = 26 'THEN' CHARACTER := 14 'ELSE' 'IF' CHARACTER = 27 'THEN' CHARACTER := 29 'ELSE' 'IF' CHARACTER = 10 'THEN' CHARACTER := 79 'ELSE' 'IF' CHARACTER = 11 'THEN' CHARACTER := 78 'ELSE' 'IF' CHARACTER = 12 'THEN' CHARACTER := 26 'ELSE' 'IF' CHARACTER = 13 'THEN' CHARACTER := 28 'ELSE' 'IF' CHARACTER = 14 'THEN' CHARACTER := 27 'ELSE' 'IF' CHARACTER = 15 'THEN' CHARACTER := 12 'ELSE' 'IF' CHARACTER = 19 'THEN' CHARACTER := 69 'ELSE' 'IF' CHARACTER = 22 'THEN' CHARACTER := 13 'ELSE' 'IF' CHARACTER = 23 'THEN' CHARACTER := 32 'ELSE' 'IF' CHARACTER = 20 'THEN' CHARACTER := 67 'ELSE' 'IF' CHARACTER = 3872 'THEN' CHARACTER := 96 'ELSE' 'IF' CHARACTER = 3899 'THEN' CHARACTER := 81 'ELSE' 'IF' CHARACTER = 4020 'THEN' CHARACTER := 75 'ELSE' 'IF' CHARACTER = 4021 'THEN' CHARACTER := 82 'ELSE' 'IF' CHARACTER = 4022 'THEN' CHARACTER := 68 'ELSE' 'IF' CHARACTER = 4023 'THEN' CHARACTER := 91 'ELSE' CHARACTER := -1; 'COMMENT' PRINT ( CHARACTER,12,0 ); GCHAR := CHARACTER; 'END'; 'PROCEDURE' DRAW THE FLOWCHART (TOP,LEFT,BOTTOM,RIGHT); 'VALUE' TOP,LEFT; 'INTEGER' TOP,LEFT,BOTTOM,RIGHT; 'BEGIN' 'INTEGER' NEW TOP,NEW LEFT,NEW BOTTOM,NEW RIGHT; 'INTEGER' J; WRITE HEADING: 'BEGIN' NEWLINE (1); 'COMMENT' WRITE TEXT ('('FLOWCHART')'); 'COMMENT' NEWLINE (1); 'END'; PRINT NAME OF FLOWCHART: 'BEGIN' JUMP OVER NAME: 'BEGIN' 'FOR' J := 1 'STEP' 1 'UNTIL' 7 'DO' CH := READCH; 'END'; MOVE TYPE TO ( LEFT,TOP ); J := 0; 'FOR' J := J + 1 'WHILE' CH 'NE' SEMICOLON 'AND' J < 82 'DO' 'BEGIN' PRINT CH (CH); TYPE ( GCHAR(CH) ); CHARACTER SPACE ( CH SP ); CH := READCH; 'END'; 'IF' J = 82 'THEN' 'BEGIN' WRITE TEXT ('('ERR0R%IN%COPY%TILL%;')'); 'GOTO' FINI: 'END'; COPYTEXT ('('!')'): 'END'; RESET POINTERS TO DRAW NEXT LEVEL: 'BEGIN' NEW TOP := NEW BOTTOM := TOP + HEIGHT 2CH; NEW LEFT := NEW RIGHT := LEFT; 'END'; DRAW NEXT LEVEL (NEW TOP,NEW LEFT,NEW BOTTOM,NEW RIGHT); RESET POINTERS TO TOP OF NEW RECTANGLE: 'BEGIN' NEW TOP := NEW BOTTOM: NEW LEFT := NEW RIGHT; 'END': PRINT OUT POINTERS (NEW TOP,NEW LEFT,NEW BOTTOM,New RIGHT): DRAW NODE (NEW TOP,NEW LEFT,NEW BOTTOM,NEW RIGHT); PRINT OUT POINTERS (NEW TOP,NEW LEFT,NEW BOTTOM,NEW RIGHT); J := 0; 'FOR' J := J + 1 'WHILE' CH 'NE' FULLSTDP 'AND' ( J < 82) 'DO' CH := READCH; 'IF' J = 82 'THEN' 'BEGIN' WRITE TEXT ('('.ERROR')'); PRINT CH (CH); LOOP ERROR (NEW TOP,NEW LEFT,NEW BOTTOM,NEW RIGHT); 'END' ; BOTTOM := NEW BOTTOM; RIGHT := NEW RIGHT; COPY TEXT('(';')'); 'END'; 'PROCEDURE' GET NON BLANK CHAR (CH); 'INTEGER' CH; 'BEGIN' 'INTEGER' J; SKIP CH; CH := NEXTCH; J := 0; 'FOR' J := J + 1 'WHILE' ( CH = BLANK 'OR' CH = ENDLINE) 'AND' ( J < 82 ) 'DO' 'BEGIN' SKIP CH; CH := NEXTCH: 'END'; 'IF' J = 82 'THEN' 'BEGIN' WRITE TEXT ('('ERROR%IN%NON%BLANK%CHAR')'); PRINT CH (CH); 'GOTO' FINI; 'END'; 'END'; 'PROCEDURE' DRAW NEXT LEVEL (TOP,LEFT,BOTTOM,RIGHT): 'VALUE' TOP,LEFT; 'INTEGER' TOP,LEFT,BOTTOM,RIGHT; 'BEGIN' 'INTEGER' DIAGONAL; DIAGONAL := 25; WRITE NEXT LEVEL: 'BEGIN' 'COMMENT' NEWLINE(1); 'COMMENT' WRITE TEXT ('('NEXT%LEVEL')'); 'COMMENT' NEWLINE (1); 'END'; DRAW DIAGONAL LINE: 'BEGIN' RIGHT := ( LEFT + WIDTH 3 CH ) + DIAGONAL; BOTTOM := TOP + DIAGONAL; VECTOR ( LEFT + WIDTH 3CH,TOP,RIGHT,BOTTOM); 'END'; 'END'; 'PROCEDURE' PRINT OUT POINTERS (TOP,LEFT,BOTTOM,RIGHT); 'VALUE' T0P,LEFT,BOTTOM,RIGHT; 'INTEGER' TOP,LEFT,BOTTOM,RIGHT; 'BEGIN' NEWLINE (1); PRINT ( TOP,6,0 ); PRINT ( LEFT,6,0 ); PRINT ( BOTTOM,6,0 ); PRINT ( RIGHT,6,0 ); NEWLINE (1); 'END'; 'PROCEDURE' DRAW NODE (TOP,LEFT,BOTTOM,RIGHT); 'VALUE' TOP, LEFT; 'INTEGER' TOP,LEFT,BOTTOM,RIGHT; 'BEGIN' 'INTEGER' NWTOP,NWLEFT,NWBOTTOM,NWRIGHT; 'INTEGER' NODE ENTRY; NUTOP := TOP; NWLEFT := LEFT; NWBOTTOM := BOTTOM; NWRIGHT := RIGHT; 'COMMENT' NODE WINDOWING MECHANISM; 'IF' NODE NUM < 5000 'THEN' NODE NUM := NODE NUM + 1 'ELSE' 'BEGIN' WRITE TEXT ('('NODETABLE OVERFLOW')'); 'GOTO' FINI 'END'; NODE ENTRY := NODE NUM; 'IF' FIRST TIME 'THEN' 'BEGIN' 'COMMENT' ALLWAYS DRAW; INTERSECT := 'TRUE'; 'END' 'ELSE' 'BEGIN' NWBOTTOM := NODE TABLE[1,NODENUM]; NWRIGHT := NODE TABLE[2,NODENUM]; INTERSECT := 'IF' NWRIGHT < RJX 'THEN' 'FALSE' 'ELSE' 'IF' RJX+XMAX < NWLEFT 'THEN' 'FALSE' 'ELSE' 'IF' NWTOP > RKY+YMAX 'THEN' 'FALSE' 'ELSE' 'IF' RKY > NWLBOTTOM 'THEN' 'FALSE' 'ELSE' 'TRUE'; 'END'; 'IF' INTERSECT 'THEN' 'BEGIN' DRAW THE NODE (NWTOP,NWLEFT,NWBOTTOM,NWRIGHT); NODE TABLE[1,NODE ENTRY] := NWBOTTOM; NODE TABLE[2,NODE ENTRYJ := NWRIGHT; 'END' 'ELSE' 'BEGIN' 'COMMENT' SKIP TO CORRESPONDING HASH; CH := READCH; COUNT := 1; 'FOR' COUNT:=COUNT 'WHILE' COUNT 'NE' 0 'DO' 'BEGIN' CH := READCH; 'IF' (CH = SHRIEK) 'OR' (CH = EQUALS) 'OR' (CH = HYPHEN) 'THEN' 'BEGIN' COUNT := COUNT + 1; NODENUM := NODENUM + 1; 'END' 'ELSE' 'IF' CH = HASH 'THEN' COUNT:= COUNT + 1 'ELSE' 'IF' CH = SQUOTE 'THEN' 'BEGIN' 'FOR' CH := READCH 'WHILE' CH 'NE' SQUOTE 'DO' 'END' 'ELSE' 'IF' CH = QUERY 'THEN' 'BEGIN' 'FOR' CH := READCH 'WHILE' CH 'NE' QUERY 'DO' 'END' 'ELSE' 'END'; 'COMMENT' SKIP OVER HASH; 'IF' CH = HASH 'THEN' GET NON BLANK CHAR (CH) 'ELSE' 'BEGIN' WRITE TEXT ('('NODE%WINDOW%ERROR')'); PRINT CH (CH); 'END': 'END'; BOTTOM := NWBOTTOM; RIGHT := NWRIGHT; 'GOTO' MISS OUT PRINTING; NEWLINE (4); WRITE TEXT ('(' NODE%TABLE ')'); PRINT (NODE ENTRY,10,0); PRINT (NODE NUM,10,0); NEWLINE (1); 'FOR' COUNT := 1 'STEP' 1 'UNTIL' NODE NUM 'DO' 'BEGIN' PRINT (COUNT,10,0); PRINT (NODETABLE[1,COUNT],10,0); PRINT (NODETABLE[2,COUNT],10,0); NEWLINE (1); 'END'; PRINT OUT POINTERS (TOP,LEFT,BOTTOM,RIGHT); MISS OUT PRINTING; 'END' NODE WINDOWING PROC; 'PROCEDURE' DRAW THE NODE (TOP,LEFT,BOTTOM,RIGHT); 'VALUE' TOP,LEFT, 'INTEGER' TOP,LEFT,BOTTOM,RIGHT; 'BEGIN' 'INTEGER' NEW TOP,NEW LEFT,NEW BOTTOM,NEW RIGHT; 'INTEGER' MAX NEW BOTTOM,MAX NEW RIGHT; 'INTEGER' TOP MLP, LEFT MLP, BOTTOM MLP, RIGHT MLP; 'INTEGER' MAX BOTTOM MLP, MAX RIGHT MLP; 'INTEGER' J; WRITE NODE: 'BEGIN' 'COMMENT' NEWLINE (1); 'COMMENT' WRITE TEXT ('('NODE')'); 'END'; 'COMMENT' PRINT OUT POINTERS (TOP,LEFT,BOTTOM,RIGHT); RESET POINTERS FOR NODE: 'BEGIN' NEW TOP := TOP; NEW LEFT := LEFT; NEW BOTTOM := MAX NEW BOTTOM := TOP + DNS; NEW RIGHT := MAX NEW RIGHT := LEFT: 'END'; GET NON BLANK CHAR (CH); DRAW ONE OR MORE SERIALS: 'BEGIN' J := 0; 'FOR' J := J + 1 'WHILE' ( CH = SQUOTE 'OR' CH = QUERY ) 'AND' ( J < 5000 ) 'DO' 'BEGIN' DRAW SERIAL (NEW TOP,NEW LEFT,NEW BOTTOM,NEW RIGHT); MAX NEW BOTTOM := MAX ( NEW BOTTOM,MAX NEW BOTTOM ); MAX NEW RIGHT := MAX ( NEW RIGHT,MAX NEW RIGHT ); 'END'; 'IF' J = 5000 'THEN' 'BEGIN' WRITE TEXT ('('ONE%OR%MORE%SERIALS%ERROR')'); PRINT CH (CH); LOOP ERROR (NEW TOP,NEW LEFT,NEW BOTTOM,NEW RIGHT); 'END'; 'COMMENT' DRAW ZERO OR MORE MIN LENGTH PARALLEL NODES; 'IF' CH = EQUALS 'THEN' 'BEGIN' SETUP MIN LEN PARALLELS: 'BEGIN' TOP MLP := BOTTOM MLP := MAX BOTTOM MLP := TOP; LEFT MLP := LEFT; RIGHT MLP := MAX RIGHT MLP := MAX NEW RIGHT; 'END'; DRAW MLP S: 'BEGIN' J := 0; 'FOR' J:=J+1 'WHILE' ((CH = EQUALS) 'AND' (J<50)) 'DO' 'BEGIN' 'COMMENT' NEWLINE(1); 'COMMENT' WRITE TEXT ('('MIN%LEN%PARALLEL')'); 'COMMENT' PRINT OUT POINTERS (TOP MLP, LEFT MLP, BOTTOM MLP, RIGHT MLP); DRAW HORIZONTAL LINE (TOP MLP, LEFT MLP, BOTTOM MLP, RIGHT MLP+DELTA MLP); LEFT MLP := RIGHT MLP := RIGHT MLP + DELTA MLP; BOTTOM MLP := TOP MLP; DRAW NODE (TOP MLP, LEFT MLP, BOTTOM MLP, RIGHT MLP); MAX BOTTOM MLP := MAX ( BOTTOM MLP, MAX BOTTOM MLP); MAX RIGHT MLP := MAX ( RIGHT MLP, MAX RIGHT MLP); 'END' OF WHILE LOOP; 'IF' J 'GE' 50 'THEN' 'BEGIN' WRITE TEXT ('('MIN%LEN%PAR%LOOP%ERROR')'); PRINT CH (CH); LOOP ERROR (TOP MLP, LEFT MLP, BOTTOM MLP, RIGHT MLP); 'END'; MAX NEW BOTTOM := MAX ( MAX BOTTOM MLP, MAX NEW BOTTOM); MAX NEW RIGHT := MAX ( MAX RIGHT MLP, MAX NEW RIGHT); 'END' OF DRAW MLP S; 'END' OF MIN LEN PARALLELS; 'IF' CH 'NE' HASH 'THEN' 'BEGIN' WRITE TEXT ('('#ERROR')'); PRINT CH (CH); 'GOTO' FINI; 'END'; GET NON BLANK CHAR (CH); BOTTOM := MAX ( BOTTOM, (MAX NEW BOTTOM + DNS) ) ; RIGHT := MAX ( RIGHT,MAX NEW RIGHT ); 'END'; 'COMMENT' WRITE TEXT ('('END%OF%NODE')'); 'COMMENT' PRINT OUT POINTERS (TOP,LEFT,BOTTOM,RIGHT); 'END'; 'PROCEDURE' DRAW SFRIAL (TOP,LEFT,BOTTOM,RIGHT)'; 'INTEGER' TOP,LEFT,BOTTOM,RIGHT; 'BEGIN' 'INTEGER' TOP SERIAL,LEFT SERIAL,BOTTOM SERIAL,RIGHT SERIAL; 'INTEGER' NEXT TOP,NEXT LEFT,NEXT BOTTOM,NEXT RIGHT; 'INTEGER' TOP PARA,LEFT PARA,BOTTOM PARA, RIGHT PARA; 'INTEGER' MAX BOTTOM PARA,MAX RIGHT PARA; 'INTEGER' J; WRITE SERIAL: 'BEGIN' 'COMMENT' NEWLINE ( 1 ); 'COMMENT' WRITE TEXT ('('SERIAL')'); 'COMMENT' PRINT OUT POINTERS (TOP,LEFT,BOTTOM,RIGHT); 'END'; DRAW VERTICAL LINE (TOP,LEFT,(BOTTOM + DTB),RIGHT); RESET SERIAL POINTERS; 'BEGIN' TOP SERIAL := BOTTOM SERIAL := BOTTOM + DTB: LEFT SERIAL := RIGHT SERIAL := LEFT; 'END'; DRAW STATEMENT (TOP SERIAL,LEFT SERIAL, BOTTOM SERIAL, RIGHT SERIAL); SET PARALLEL POINTERS: 'BEGIN' TOP PARA := BOTTOM PARA := MAX BOTTOM PARA := TOP; LEFT PARA := LEFT; RIGHT PARA := MAX RIGHT PARA := RIGHT SERIAL; 'END'; NEXT LEVEL: 'BEGIN' GET NON BLANK CHAR (CH); NEXT TOP := NEXT BOTTOM := 0; NEXT LEFT := NEXT RIGHT := 0; 'IF' CH = SHRIEK 'THEN' 'BEGIN' RESET NEXT LEVEL POINTERS: 'BEGIN' NEXT TOP := BOTTOM SERIAL; NEXT LEFT := LEFT; 'END'; 'COMMENT' NEWLINE (1); 'COMMENT' WRITE TEXT ('('SERIAL~NEXT%LEVEL')'); DRAW NEXT LEVEL (NEXT TOP,NEXT LEFT,NEXT BOTTOM, NEXT RIGHT); NEXT TOP := NEXT BOTTOM; NEXT LEFT := NEXT RIGHT; DRAW NODE (NEXT TOP,NEXT LEFT,NEXT BOTTOM,NEXT RIGHT); RIGHT PARA := MAX RIGHT PARA := MAX ( RIGHT PARA, NEXT RIGHT); 'END'; 'END'; PARALLEL: 'BEGIN' J := 0; 'FOR' J := J + 1 'WHILE' CH = HYPHEN 'AND' ( J < 82 ) 'DO' 'BEGIN' 'COMMENT' NEWLINE (1); 'COMMENT' WRITE TEXT ('('SERIAL-PARALLEL')'); 'COMMENT' PRINT OUT POINTERS (TOP PARA,LEFT PARA,BOTTOM PARA, RIGHT PARA); DRAW HORIZONTAL LINE (TOP PARA,LEFT PARA,BOTTOM PARA, (RIGHT PARA + DRP )); LEFT PARA := RIGHT PARA := RIGHT PARA+ DRP: BOTTOM PARA := TOP PARA; DRAW NODE (TOP PARA,LEFT PARA,BOTTOM PARA,RIGHT PARA); MAX BOTTOM PARA := MAX ( BOTTOM PARA,MAX BOTTOM PARA ); MAX RIGHT PARA := MAX ( RIGHT PARA,MAX RIGHT PARA ); 'END'; 'IF' J = 82 'THEN' 'BEGIN' WRITE TEXT ('('PARALLEL%LOOP%ERROR')'); PRINT CH (CH); LOOP ERROR (TOP PARA,LEFT PARA,BOTTOM PARA,RIGHT PARA); 'END'; 'END'; OVERALL SIZES: 'BEGIN' TOP := BOTTOM SERIAL; BOTTOM := MAX ( BOTTOM SERIAL,MAX (NEXT BOTTOM,BOTTOM PARA) ); RIGHT := MAX ( RIGHT SERIAL,MAX (NEXT RIGHT,RIGHT PARA) ); 'END'; 'COMMENT' NEWLINE (1); 'COMMENT' WRITE TEXT ('('END%OF%SERIAL')'); 'COMMENT' PRINT OUT POINTERS (TOP,LEFT,BOTTOM,RIGHT); 'END'; 'PROCEDURE' DRAW VERTICAL LINE (TOP,LEFT,BOTTOM,RIGHT); 'VALUE' TOP,LEFT,BOTTOM,RIGHT; 'INTEGER' TOP,LEFT,BOTTOM,RIGHT; 'BEGIN' 'COMMENT' NEWLINE (1); 'COMMENT' WRITE TEXT ('('VERTICAL%LINE')'); 'COMMENT' PRINT OUT POINTERS (TOP,LEFT,BOTTOM,RIGHT); VECTOR ( LEFT,TOP,LEFT,BOTTOM ); 'END'; 'PROCEDURE' DRAW STATEMENT (TOP,LEFT,BOTTOM,RIGHT); 'VALUE' TOP,LEFT; 'INTEGER' TOP,LEFT,BOTTOM,RIGHT; 'BEGIN' 'INTEGER' TOP TEXT, RIGHT TEXT; 'INTEGER' J; 'BOOLEAN' ACTION; 'IF' CH = SQUOTE 'THEN' ACTION := 'TRUE' 'ELSE' 'IF' CH = QUERY 'THEN' ACTION := 'FALSE' 'ELSE' 'BEGIN,' WRITE TEXT ('('?%OR%'%ERR0R')'); PRINT CH (CH); 'GOTO' FINI; 'END': WRITE OUT TEXT: 'BEGIN' SET TEXT POINTERS: 'BEGIN' TOP TEXT :=T OP+ CH HEIGHT: RIGHT TEXT := RIGHT := LEFT; 'END'; 'COMMENT' NEWLINE (1); GET NON BLANK CHAR (CH); MOVE TYPE TO ( LEFT,TOP TEXT); J := O; 'FOR' J := J + 1 'WHILE' 'NOT' ((CH= ('IF' ACTION 'THEN' $QUOTE 'ELSE' QUERY)) 'OR' J 'GE' 999) 'DO' 'BEGIN' 'IF' CH = ENDLINE 'THEN' START NEW LINE OF TEXT: 'BEGIN' RIGHT := MAX (RIGHT, RIGHT TEXT); TOP TEXT := TOP TEXT+ HEIGHT 2 CH; MOVE TYPE TO (LEFT, TOP TEXT); RIGHT TEXT := LEFT: GET NON BLANK CHAR (CH): 'END' 'ELSE' 'BEGIN' 'COMMENT' PRINT CH (CH); 'COMMENT' WINDOWING FRIG ; 'IF' ( LEFT WINDOW < RIGHT TEXT) 'THEN' 'BEGIN' 'IF' (RIGHT TEXT < RIGHT WINDOW) 'THEN' 'BEGIN' 'IF' (TOP WINDOW < TOP TEXT) 'THEN' 'BEGIN' 'IF' (TOP TEXT < BOTTOM WINDOW) 'THEN' 'BEGIN' MOVE TYPE TO (RIGHT TEXT,TOP TEXT); TYPE ( GCHAR(CH) ); CHARACTER SPACE ( CH SP ); 'END' 'END' 'END' 'END' ; RIGHT TEXT := RIGHT TEXT+ CH WIDTH+ CH SP; SKIP CH; CH := NEXTCH; 'END'; 'END' ; 'IF' J = 999 'THEN' 'BEGIN' NEWLINE (1); WRITE TEXT ('('WRITE%OUT%TEXT%ERR0R')'); PRINT CH (CH); LOOP ERROR (TOP,LEFT,BOTTOM,RIGHT); 'END'; OVERALL SIZE OF TEXT 'BEGIN' BOTTOM : = TOP TEXT := CH HEIGHT; RIGHT := MAX(RIGHT, RIGHT TEXT); 'END'; 'END'; 'IF' ((ACTION 'EQUIV' 'TRUE') 'AND' (CH= QUERY)) 'OR' ((ACTION 'EQUIV' 'FALSE') 'AND' (CH = SQUOTE)) 'THEN' 'BEGIN' WRITE TEXT ('('ACTION%OR%'%OR%?%ERROR')'); PRINT CH (CH); 'GOTO' FINI; 'END'; 'IF' ACTION 'EQUIV' 'TRUE' 'THEN' 'BEGIN' 'COMMENT' SPACE OVER TEXT I,E, DO NOTHING; 'END'; 'IF' ACTION 'EQUIV' 'FALSE' 'THEN' 'BEGIN' DRAW HALF SQUARE: 'BEGIN' 'COMMENT' NEWLINE (1); 'COMMENT' WRITE TEXT ('('HALF-SQUARE')'); VECTOR ( LEFT,TOP,(LEFT - CH WIDTH),TOP); VECTOR ((LEFT - CH WIDTH),TOP,(LEFT ~ CH WIDTH),BOTTOM ); VECTOR ((LEFT - CH WIDTH),BOTTOM,LEFT,BOTTOM ); 'END'; 'END'; 'END'; 'PROCEDURE' DRAW HORIZONTAL LINE (TOP,LEFT,BOTTOM,RIGHT); 'VALUE' TOP,LEFT,BOTTOM,RIGHT; 'INTEGER' TOP,LEFT,BOTTOM,RIGHT; 'BEGIN' 'COMMENT' NEWLINE (1); 'COMMENT' WRITE TEXT ('('HORIZONTAL%LINE')'); 'COMMENT' PRINT OUT POINTERS (TOP,LEFT,BOTTOM,RIGHT); VECTOR ( LEFT,TOP,RIGHT,TOP ); 'END'; 'PROCEDURE' LOOP ERROR (TOP,LEFT,BOTTOM,RIGHT); 'VALUE' TOP,LEFT,BOTTOM,RIGHT; 'INTEGER' TOP,LEFT,BOTTOM,RIGHT; 'BEGIN' WRITE TEXT ('('A%L00P%ERR0R%HAS%0CCURRED')'); PRINT CH (CH); PRINT OUT POINTERS (TOP,LEFT,BOTTOM,RIGHT); 'GOTO' FINI; 'END'; DECIDE ON INPUT OUTPUT STREAMS: 'BEGIN' SELECT INPUT (5); SELECT OUTPUT (5); 'END'; SET INITIAL VALUES OF POINTERS: 'BEGIN' TOP := BOTTOM := 100; LEFT := RIGHT := 100; 'END'; 'COMMENT' INITIALISE NODE WINDOWING: FIRST TIME := 'TRUE'; DRAW THE BIG PICTURE: 'BEGIN' 'FOR' RJX := 0 'STEP' XMAX 'UNTIL' RIGHT 'DO' 'BEGIN' 'FOR' RKY := 0 'STEP' YMAX 'UNTIL' BOTTOM 'DO' 'BEGIN' FREE INPUT; TR5 :; ALGOBEY ('('RL%*TR5')'); TR5 := ALGOBEY ('('AS%*TR5,£E')'); SELECT INPUT (5); TOP := BOTTOM := 100; LEFT := RIGHT := 100; XMAX := YMAX := READ; TOP WINDOW := RKY - 50; LEFT WINDOW := RJX - 50; BOTTOM WINDOW := RKY + YMAX - 50; RIGHT WINDOW := RJX + XMAX - 50; NODE NUM := O; LIMITS (RJX,RKY+YMAX,RJX+XMAX,RKY); DRAW THE FLOWCHART (TOP,LEFT,BOTTOM,RIGHT); VECTOR (RJX+XMAX,RKY,RJX+XMAX,RKY+YMAX); VECTOR (RJX ,RKY,RJX ,RKY+YMAX); ADVANCE FILM; FIRST TIME := 'FALSE'; 'END'; ADVANCE FILM; 'END': 'END': FINI : 'BEGIN' NEWLINE (3); 'END'; 'END': 'END'; 'END'; 'END'; ENDPLOTTING; 'END';