summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/brainfuck/brainfuck.cr14
-rw-r--r--src/brainfuck/parser.cr30
-rw-r--r--src/brainfuck/program.cr14
-rw-r--r--src/flint.cr31
-rw-r--r--src/util.cr5
5 files changed, 87 insertions, 7 deletions
diff --git a/src/brainfuck/brainfuck.cr b/src/brainfuck/brainfuck.cr
index 78c504c..b75ad1c 100644
--- a/src/brainfuck/brainfuck.cr
+++ b/src/brainfuck/brainfuck.cr
@@ -13,5 +13,19 @@ module Brainfuck
LoopStart
LoopEnd
end
+
+ def self.opcode_from_char(c : Char) : Opcode?
+ case c
+ when '>' then Opcode::PtrRight
+ when '<' then Opcode::PtrLeft
+ when '+' then Opcode::Inc
+ when '-' then Opcode::Dec
+ when '.' then Opcode::Out
+ when ',' then Opcode::In
+ when '[' then Opcode::LoopStart
+ when ']' then Opcode::LoopEnd
+ else nil
+ end
+ end
end
diff --git a/src/brainfuck/parser.cr b/src/brainfuck/parser.cr
index b937f73..df381e3 100644
--- a/src/brainfuck/parser.cr
+++ b/src/brainfuck/parser.cr
@@ -1,5 +1,33 @@
+require "./brainfuck.cr"
+require "../util.cr"
+
class Brainfuck::Parser
- def initialize()
+ def initialize(code_io : IO)
+ @raw_code = code_io.gets_to_end
+ code_io.close # just in case
+ end
+
+ def parse
+ loop_depth = 0
+ code = [] of Opcode
+ @raw_code.chars.each do |c|
+ op = Brainfuck.opcode_from_char(c)
+ unless op.nil?
+ if loop_depth == 0 && op == Opcode::LoopEnd
+ raise Util::ParserError.new("Missing loop entrance(s)")
+ end
+
+ loop_depth -= 1 if op == Opcode::LoopEnd
+ loop_depth += 1 if op == Opcode::LoopStart
+ code << op
+ end
+ end
+
+ unless loop_depth == 0
+ raise Util::ParserError.new("Missing loop exit(s)")
+ end
+
+ return code
end
end
diff --git a/src/brainfuck/program.cr b/src/brainfuck/program.cr
new file mode 100644
index 0000000..cf4a097
--- /dev/null
+++ b/src/brainfuck/program.cr
@@ -0,0 +1,14 @@
+require "./parser.cr"
+
+class Brainfuck::Program
+ def initialize(@parser : Brainfuck::Parser)
+ end
+
+ def interpret
+ puts @parser.parse
+ end
+
+ def compile
+ end
+end
+
diff --git a/src/flint.cr b/src/flint.cr
index 39d8363..1c67cc9 100644
--- a/src/flint.cr
+++ b/src/flint.cr
@@ -2,6 +2,7 @@
require "option_parser"
+require "./util.cr"
require "./brainfuck/*"
require "./brainfuck/parser.cr"
@@ -13,6 +14,7 @@ module Flint
chosen_language = nil
memory_size = nil
source_file = nil
+ read_stdin = false
parser = OptionParser.new do |parser|
parser.banner = "Basic usage: flint [LANGUAGE] [OPTIONS] [FILE]"
@@ -33,6 +35,9 @@ module Flint
parser.on("-c", "--compile", "produce a binary or different source code file instead of interpeting the code, overrides an explicit '-i' or '--intepret' flag") do
execution_mode = :compile
end
+ parser.on("--stdin", "read source code from STDIN instead of a file") do
+ read_stdin = true
+ end
parser.unknown_args do |_args|
source_file = _args[0] unless _args.empty?
@@ -47,17 +52,31 @@ module Flint
exit(1)
end
- if source_file.nil?
+ if read_stdin
+ source_io = STDIN
+ elsif source_file
+ # compilier complains without the not_nil!
+ source_io = File.new(source_file.not_nil!)
+ else
puts "ERROR: No source file chosen"
puts parser
+ puts source_file.nil?
+ puts (!read_stdin)
exit(1)
end
- # temporary
- puts execution_mode
- puts chosen_language
- puts memory_size
- puts source_file
+ if chosen_language == :brainfuck
+ bf_parser = Brainfuck::Parser.new(source_io)
+ program = Brainfuck::Program.new(bf_parser)
+ end
+
+ begin
+ program.not_nil!.interpret
+ rescue ex : Util::ParserError
+ puts "Caught ParserError"
+ puts ex.message
+ exit(1)
+ end
end
end
diff --git a/src/util.cr b/src/util.cr
new file mode 100644
index 0000000..841a2b2
--- /dev/null
+++ b/src/util.cr
@@ -0,0 +1,5 @@
+module Util
+ class ParserError < Exception
+ end
+end
+