diff options
author | Jed Barber <jjbarber@y7mail.com> | 2015-03-14 23:37:44 +1100 |
---|---|---|
committer | Jed Barber <jjbarber@y7mail.com> | 2015-03-14 23:37:44 +1100 |
commit | aac4cacb47ba22edf8cc722ff2a8fb9e19072a4b (patch) | |
tree | 1548c1b1ba66814387a2d16112c8fd95c2928e13 | |
parent | 8e492d005cbc090c6253f9fe20a57088b025eeba (diff) |
Brainfuck interpreter in Ada
-rw-r--r-- | src/Brainfuck/brainfuck.adb | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/src/Brainfuck/brainfuck.adb b/src/Brainfuck/brainfuck.adb new file mode 100644 index 0000000..26de72c --- /dev/null +++ b/src/Brainfuck/brainfuck.adb @@ -0,0 +1,124 @@ + + +with Ada.Text_IO; +with Ada.Direct_IO; +with Ada.Command_Line; + + +procedure Brainfuck is + + + package CL renames Ada.Command_Line; + package Text_IO renames Ada.Text_IO; + + + package Direct_IO is new Ada.Direct_IO(Character); + use type Direct_IO.Count; + + + type Cell is mod 256; + type Tape_Position is mod 5000; + type Program_Tape is array (Tape_Position'Range) of Cell; + pragma Pack (Program_Tape); + + + Input_File : Direct_IO.File_Type; + File_Position : Direct_IO.Positive_Count; + Counter : Integer; + Current_Char : Character; + Tape : Program_Tape; + Current_Cell : Tape_Position; + + +begin + + + if CL.Argument_Count /= 1 then + Text_IO.Put_Line(Text_IO.Standard_Error, "Please supply the filename of a brainfuck program"); + CL.Set_Exit_Status(CL.Failure); + return; + end if; + + + begin + Direct_IO.Open( File => Input_File, + Mode => Direct_IO.In_File, + Name => CL.Argument(1) ); + exception + when others => + Text_IO.Put_Line(Text_IO.Standard_Error, "Can not open the file '" & CL.Argument(1) & "'. Does it exist?"); + CL.Set_Exit_Status(CL.Failure); + return; + end; + + + Tape := (others => 0); + Current_Cell := Tape_Position'First; + + while not Direct_IO.End_Of_File(Input_File) loop + Direct_IO.Read(Input_File, Current_Char); + + case Current_Char is + + when '>' => + Current_Cell := Current_Cell + 1; + + when '<' => + Current_Cell := Current_Cell - 1; + + when '+' => + Tape(Current_Cell) := Tape(Current_Cell) + 1; + + when '-' => + Tape(Current_Cell) := Tape(Current_Cell) - 1; + + when '.' => + Text_IO.Put(Character'Val(Tape(Current_Cell))); + + when ',' => + Text_IO.Get(Current_Char); + Tape(Current_Cell) := Character'Pos(Current_Char); + + when '[' => + if Tape(Current_Cell) = 0 then + Counter := 1; + while Counter > 0 and not Direct_IO.End_Of_File(Input_File) loop + Direct_IO.Read(Input_File, Current_Char); + if Current_Char = '[' then + Counter := Counter + 1; + elsif Current_Char = ']' then + Counter := Counter - 1; + end if; + end loop; + end if; + + when ']' => + if Tape(Current_Cell) /= 0 then + Counter := 0; + File_Position := Direct_IO.Index(Input_File) - 1; + loop + Direct_IO.Set_Index(Input_File, File_Position); + Direct_IO.Read(Input_File, Current_Char); + if Current_Char = ']' then + Counter := Counter + 1; + elsif Current_Char = '[' then + Counter := Counter - 1; + end if; + File_Position := File_Position - 1; + exit when Counter < 1; + end loop; + end if; + + when others => + null; + + end case; + + end loop; + + + Direct_IO.Close(Input_File); + + +end Brainfuck; + |