RosettaCodeData/Task/Execute-Brain-/ALGOL-68/execute-brain--1.alg
2024-11-04 21:53:44 -08:00

95 lines
3.6 KiB
Text

BEGIN # Brain**** -> Algol 68 transpiler #
# a single line of Brain**** code is prompted for and read from #
# standard input, the generated code is written to standard output #
# the original code is included in the output as a comment #
# transpiles the Brain**** code in code list to Algol 68 #
PROC generate = ( STRING code list )VOID:
BEGIN
PROC emit = ( STRING code )VOID: print( ( code, newline ) );
PROC emit1 = ( STRING code )VOID:
print( ( IF need semicolon THEN ";" ELSE "" FI
, newline, indent, code
)
);
PROC next = CHAR: IF c pos > c max
THEN "$"
ELSE CHAR result = code list[ c pos ];
c pos +:= 1;
result
FI;
# address and data modes and the data space #
emit( "BEGIN" );
emit( " MODE DADDR = INT; # data address #" );
emit( " MODE DATA = INT;" );
emit( " DATA zero = 0;" );
emit( " [-255:255]DATA data; # finite data space #" );
emit( " FOR i FROM LWB data TO UPB data DO data[i] := zero OD;" );
emit( " DADDR addr := ( UPB data + LWB data ) OVER 2;" );
# actual code #
STRING indent := " ";
BOOL need semicolon := FALSE;
INT c pos := LWB code list;
INT c max = UPB code list;
CHAR c := next;
WHILE c /= "$" DO
IF c = "?"
THEN emit1( "SKIP" );
need semicolon := TRUE;
WHILE ( c := next ) = "?" DO SKIP OD
ELIF c = "<" OR c = ">"
THEN CHAR op code = c;
CHAR assign op = IF c = ">" THEN "+" ELSE "-" FI;
INT incr := 1;
WHILE ( c := next ) = op code DO incr +:= 1 OD;
emit1( "addr " + assign op + ":= " + whole( incr, 0 ) );
need semicolon := TRUE
ELIF c = "+" OR c = "-"
THEN CHAR op code = c;
INT incr := 1;
WHILE ( c := next ) = op code DO incr +:= 1 OD;
emit1( "data[ addr ] " + op code + ":= " + whole( incr, 0 ) );
need semicolon := TRUE
ELIF c = "."
THEN emit1( "print( ( REPR data[ addr ] ) )" );
need semicolon := TRUE;
c := next
ELIF c = ","
THEN emit1( "data[ addr ] := ABS read char" );
need semicolon := TRUE;
c := next
ELIF c = "["
THEN emit1( "WHILE data[ addr ] /= zero DO" );
indent +:= " ";
need semicolon := FALSE;
c := next
ELIF c = "]"
THEN need semicolon := FALSE;
indent := indent[ LWB indent + 2 : ];
emit1( "OD" );
need semicolon := TRUE;
c := next
ELSE
print( ( "Invalid op code: """, c, """", newline ) );
c := next
FI
OD;
emit( "" );
emit( "END" )
END # gen # ;
# get the code to transpile and output it as a comment at the start #
# of the code #
print( ( "CO BF> " ) );
STRING bf code;
read( ( bf code, newline ) );
print( ( newline, bf code, newline, "CO", newline ) );
# transpile the code #
generate( bf code )
END