procedure AlgolEdit(characterset, linelimit); string characterset; integer linelimit; comment If this procedure is presented an ALGOL 60 program or procedure in the form of a sequence of basic symbols, it will transmit to the output medium a copy of the text with indentations between each begin-end pair and some rearrangement of the blank spaces within the text. This procedure is an example of its own output. It is used to edit ALGOL 60 text that is difficult to read because, for example, the ALGOL has been transcribed from printed documents, or written by inexperienced programmers, or stored in compressed form (i.e., with all redundant blank spaces removed). The integer “-1” will represent the nonbasic symbol “carriage return”, “-2” will represent an end-of-file mark, other symbols will have the integer value corresponding to their position in the parametric string “characterset”. The string must contain exactly the 116 basic symbols of ALGOL 60. The parameter line-limit” sets an upper bound on the number of basic symbols that the user wishes to appear on a line of output. The identifiers “lsq” and “rsq” will be used in place of strings of length one whose only elements are “‘” and “’”, respectively; begin integer array spacesbefore, spacesafter[1 : 116], buffer[1 : linelimit]; integer tabstop, symbol, i, symbolcount, level; Boolean newline; integer procedure val(s); string s; begin comment The value of this procedure is the integer corresponding to the position in the string “characterset” of the symbol in the string “s”. The body of the procedure must be expressed in code; end val; procedure get(symbol); integer symbol; begin insymbol(2, characterset, symbol); if symbol = -2 then go to eof end get; procedure send(symbol); integer symbol; begin comment “send” must not break identifiers across lines or insert spurious characters into strings; integer i, u, v; if symbol = -1 ∨ symbolcount ≥ linelimit then begin v := tabstop; if newline then go to E; if level ≠ 0 then begin comment Inside a string; for i:= 1 step 1 until symbolcount do outsymbol(1, characterset, buffer[i]); outsymbol(1, characterset, -1) ; v := 0 end else begin u := symbolcount; newline := true; if symbol = -1 then go to D; comment Find a convenient place to break the line; for u := symbolcount - 1 step -1 until tabstop do if buffer[u + 1] = val(‘ ’) ∨ buffer[u] = val(rsq) then go to D; u := symbolcount; comment Send the line; D: for i := 1 step 1 until u do outsymbol(1, characterset, buffer[i]); outsymbol(1, characterset, -1); comment Find a non-blank character to start the next line; for i := u + 1 step 1 until symbolcount do if buffer[i] ≠ val(‘ ’) then go to F; go to G; comment Move a new line to the head of the buffer area; F: for i := i step 1 until symbolcount do begin v := v + 1; newline := false; buffer[v] := buffer[i] end; comment Insert blanks for tab stops; G: for i := 1 step 1 until tabstop do buffer[i] := val(‘ ’) end; E: symbolcount := v end; comment Now we can put the new symbol in the buffer array; if symbol ≠ -1 ∧ ¬ (newline ∧ symbol = val(‘ ’)) then begin symbolcount := symbolcount + 1; newline := false; buffer[symbolcount] := symbol end end send; for symbol := 1 step 1 until 116 do spacesbefore[symbol] := spacesafter[symbol] := 0; for symbol := val(‘+’), val(‘-’), val(‘¬’), val(‘:’), val(‘:=’), val(‘<’), val(‘≤’), val(‘=’), val(‘≠’), val(‘≥’), val(‘>’) do spacesbefore[symbol] := spacesafter[symbol] := 1; for symbol := val(‘∧’), val(‘∨’), val(‘⊃’), val(‘≡’), val(‘then’), val(‘else’), val(‘step’), val(‘until’),val(‘while’), val(‘do’) do spacesbefore[symbol] := spacesafter[symbol] := 2; for symbol := val(‘go to’), val(‘begin’), val(‘if’), val(‘for’), val(‘procedure’), val(‘value’), val(‘own’), val(‘real’), val(‘Boolean’), val(‘integer’), val(‘array’), val(‘switch’), val(‘label’), val(‘string’), val(‘,’) do spacesafter[symbol] := 2; level := symbolcount := tabstop := 0; newline := true; nextsymbol: deblank: get(symbol); scanned: if symbol = val(‘ ’) ∨ symbol = -1 then go to deblank; if symbol = val(‘begin’) then send( -1) else if symbol = val(‘end’) then begin tabstop := tabstop - 5; send( -1) end; for i := 1 step 1 until spacesbefore[symbol] do send(val(‘ ’)); send(symbol); for i := 1 step 1 until spacesafter[symbol] do send(val(‘ ’)); if symbol = val(‘comment’) then begin comment Pass comments on unchanged; for i := 1 while symbol ≠ val(‘;’) do begin get(symbol); send(symbol) end end else if symbol = val(‘end’) then begin comment ‘end’ comments; for i := 1 while symbol ≠ val(‘;’) do begin get(symbol); if symbol = val(‘else’) ∨ symbol = val(‘end’) then go to scanned; send(symbol) end end else if symbol = val(lsq) then begin comment Pass strings on unchanged; level := 1; for i := 1 while level ≠ 0 do begin get(symbol); send(symbol); if symbol = val(lsq) then level := level + 1 else if symbol = val(rsq) then level := level - 1 end end; if symbol = val(‘begin’) then tabstop := tabstop + 5 else if symbol = val(‘;’) then send(-1); go to nextsymbol; eof: send( -1); outsymbol (1, characterset, -2) end Algoledit;