diff options
| author | Matthew Hall <hallmatthew314@gmail.com> | 2022-09-02 21:03:42 +1200 |
|---|---|---|
| committer | Matthew Hall <hallmatthew314@gmail.com> | 2022-09-02 21:03:42 +1200 |
| commit | 4dd4e596ae6e5da84f2ce4296cbf9c030efe69bb (patch) | |
| tree | 401bf737a26c3cac4a32cf4862180d6288f9c010 | |
| parent | dd2bcbdadf2068723bdd88729d295171b0291cd2 (diff) | |
Can read code from STDIN, can parse brainfuck
| -rw-r--r-- | src/brainfuck/brainfuck.cr | 14 | ||||
| -rw-r--r-- | src/brainfuck/parser.cr | 30 | ||||
| -rw-r--r-- | src/brainfuck/program.cr | 14 | ||||
| -rw-r--r-- | src/flint.cr | 31 | ||||
| -rw-r--r-- | src/util.cr | 5 |
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 + |
