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[l : 116], buffer[l : linelimit];
integer tabstop, symbol, i, symbolcount, level;
boolean newline;
integer procedure val(s);
string s;
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;
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(l, characterset, buffer[i]);
outsymbol(l, 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 := l 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 := l;
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