Execute Brain****/COBOL
This is a simple Brainf*** interpreter written in COBOL, which receives its program from standard input.
<lang cobol> IDENTIFICATION DIVISION.
PROGRAM-ID. Brainfuck-Interpreter.
DATA DIVISION. LOCAL-STORAGE SECTION.
01 Nesting-Level PIC 999.
01 Array. 03 Array-Table USAGE BINARY-CHAR OCCURS 30000 TIMES INDEXED BY Table-Index.
01 Input-Char PIC X.
- *>> Note: This limit is mostly arbitrary.
01 Max-Program-Size CONSTANT 2048. 01 Input-Program PIC X(Max-Program-Size). 01 Program-Index USAGE UNSIGNED-INT.
PROCEDURE DIVISION. Main. DISPLAY "Enter program: " WITH NO ADVANCING ACCEPT Input-Program
PERFORM Process-Statement VARYING Program-Index FROM 1 BY 1 UNTIL Max-Program-Size < Program-Index
GOBACK .
Process-Statement. EVALUATE Input-Program (Program-Index:1) WHEN ">" SET Table-Index UP BY 1
WHEN "<" SET Table-Index DOWN BY 1
WHEN "+" ADD 1 TO Array-Table (Table-Index)
WHEN "-" SUBTRACT 1 FROM Array-Table (Table-Index)
WHEN "." DISPLAY FUNCTION CHAR(FUNCTION SUM( Array-Table (Table-Index), 1)) WITH NO ADVANCING
WHEN "," ACCEPT Input-Char
- *> See below.
CALL "Ascii-Char-To-Num" USING Input-Char Array-Table (Table-Index)
WHEN "[" IF Array-Table (Table-Index) = ZERO PERFORM Jump-To-Block-End END-IF
WHEN "]" IF Array-Table (Table-Index) NOT = ZERO PERFORM Jump-To-Block-Start END-IF END-EVALUATE .
- *>> Move Program-Index back to position of matching '['
Jump-To-Block-Start. SUBTRACT 1 FROM Program-Index PERFORM VARYING Program-Index FROM Program-Index BY -1 UNTIL ((Input-Program (Program-Index:1) = "[") AND (Nesting-Level = 0)) OR (Program-Index = 0) EVALUATE Input-Program (Program-Index:1) WHEN "[" SUBTRACT 1 FROM Nesting-Level
WHEN "]" ADD 1 TO Nesting-Level END-EVALUATE END-PERFORM
PERFORM Check-Mismatched-Brackets .
- *>> Move Program-Index forward to position of matching ']'
Jump-To-Block-End. ADD 1 TO Program-Index PERFORM VARYING Program-Index FROM Program-Index BY 1 UNTIL ((Input-Program (Program-Index:1) = "]") AND (Nesting-Level = 0)) OR (Input-Program (Program-Index:1) = SPACE)
EVALUATE Input-Program (Program-Index:1) WHEN "[" ADD 1 TO Nesting-Level
WHEN "]" SUBTRACT 1 FROM Nesting-Level END-EVALUATE END-PERFORM
PERFORM Check-Mismatched-Brackets .
Check-Mismatched-Brackets. IF (Program-Index = 0) OR (Input-Program (Program-Index:1) = SPACE) DISPLAY "Mismatched squre brackets. Aborting..." GOBACK END-IF .
END PROGRAM Brainfuck-Interpreter.</lang>
When accepting input from the user, the character entered must be converted by the function below because moving it straight into a numeric data item would cause the character to be parsed as a number, causing non-numeric characters to be converted to zero. <lang cobol> IDENTIFICATION DIVISION.
PROGRAM-ID. Ascii-Char-To-Num.
DATA DIVISION. WORKING-STORAGE SECTION. 01 Ascii PIC X(128) VALUE X"0102030405060708090A0B0C0D0E0F" & X"101112131415161718191A1B1C1D1E1F" & " !" & QUOTE & "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[" & "\]^_`abcdefghijklmnopqrstuvwxyz{|}~" & X"7F".
LOCAL-STORAGE SECTION. 01 I PIC 999.
LINKAGE SECTION. 01 Input-Char PIC X. 01 Ascii-Num USAGE BINARY-CHAR.
*>> Converts an ASCII character to its corresponding numerical value, *>> placing the result in Ascii-Num. PROCEDURE DIVISION USING Input-Char Ascii-Num. IF Input-Char = X"00" MOVE ZERO TO Ascii-Num GOBACK END-IF
PERFORM VARYING I FROM 1 BY 1 UNTIL 128 < I IF Ascii (I:1) = Input-Char MOVE I TO Ascii-Num GOBACK END-IF END-PERFORM
DISPLAY "The character could not be matched." MOVE -1 TO Ascii-Num GOBACK .
END PROGRAM Ascii-Char-To-Num.</lang>