summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/flint.cr31
-rw-r--r--src/thue/parser.cr50
-rw-r--r--src/thue/program.cr13
-rw-r--r--src/thue/rule.cr43
-rw-r--r--src/thue/thue.cr7
5 files changed, 132 insertions, 12 deletions
diff --git a/src/flint.cr b/src/flint.cr
index f2323a2..8f11223 100644
--- a/src/flint.cr
+++ b/src/flint.cr
@@ -4,10 +4,10 @@ require "option_parser"
require "./util.cr"
require "./brainfuck/*"
-require "./brainfuck/parser.cr"
+require "./thue/*"
module Flint
- VERSION = "0.1.0"
+ VERSION = "0.1.1"
def self.main
execution_mode = :interpret
@@ -23,12 +23,19 @@ module Flint
chosen_language = :brainfuck
memory_size = Brainfuck::DEFAULT_TAPE_SIZE
- parser.banner = "Useage: flint brainfuck [OPTIONS] [FILE]"
+ parser.banner = "Usage: flint brainfuck [OPTIONS] [FILE]"
parser.on("-t CELLS", "--tape-size=CELLS", "specify the number of memory cells in the tape, defaults to 30,000") do |_cells|
memory_size = _cells.to_i
end
end
+ parser.on("thue", "select Thue as the language") do
+ chosen_language = :thue
+
+ parser.banner = "Usage: flint thue [OPTIONS] [FILE]"
+ # no thue-specific options yet
+ end
+
parser.on("-h", "--help", "show this help and exit") do
puts parser
exit(0)
@@ -48,12 +55,6 @@ module Flint
parser.parse
- if chosen_language.nil?
- puts "ERROR: No language chosen"
- puts parser
- exit(1)
- end
-
if read_stdin
source_io = STDIN
elsif source_file
@@ -62,14 +63,20 @@ module Flint
else
puts "ERROR: No source file chosen"
puts parser
- puts source_file.nil?
- puts (!read_stdin)
exit(1)
end
- if chosen_language == :brainfuck
+ case chosen_language
+ when :brainfuck
bf_parser = Brainfuck::Parser.new(source_io)
program = Brainfuck::Program.new(bf_parser, memory_size)
+ when :thue
+ thue_parser = Thue::Parser.new(source_io)
+ program = Thue::Program.new(thue_parser)
+ else
+ puts "ERROR: No language chosen"
+ puts parser
+ exit(1)
end
begin
diff --git a/src/thue/parser.cr b/src/thue/parser.cr
new file mode 100644
index 0000000..6b3907b
--- /dev/null
+++ b/src/thue/parser.cr
@@ -0,0 +1,50 @@
+require "../util.cr"
+require "./thue.cr"
+require "./rule.cr"
+
+class Thue::Parser
+ def initialize(code_io : IO)
+ @raw_code = code_io.gets_to_end
+ code_io.close # just in case
+ end
+
+ def parse
+ rules = [] of Rule
+ line_iterator = @raw_code.lines.each
+
+ line_iterator.each do |line|
+ case line
+ when "", "::="
+ # stops iteration of lines to be picked up by string builder
+ break
+
+ # returned match objects are provably not_nil, safe
+ when .matches?(R_INPUT_RULE)
+ m = line.match(R_INPUT_RULE).not_nil!
+ rules << InputRule.new(m[1])
+
+ when .matches?(R_OUTPUT_RULE)
+ m = line.match(R_OUTPUT_RULE).not_nil!
+ rules << OutputRule.new(m[1], m[2])
+
+ when .matches?(R_NORMAL_RULE)
+ m = line.match(R_NORMAL_RULE).not_nil!
+ rules << NormalRule.new(m[1], m[2])
+
+ else
+ raise Util::ParserError.new("No separator between code and initial state near '#{line}'")
+ end
+ end
+
+ state = String.build do |str|
+ # resumes from where rule parser left off
+ line_iterator.each do |line|
+ str << line
+ str << '\n'
+ end
+ end
+
+ {rules, state}
+ end
+end
+
diff --git a/src/thue/program.cr b/src/thue/program.cr
new file mode 100644
index 0000000..c59780b
--- /dev/null
+++ b/src/thue/program.cr
@@ -0,0 +1,13 @@
+require "./thue.cr"
+require "./parser.cr"
+
+class Thue::Program
+ def initialize(@parser : Parser)
+ end
+
+ def interpret
+ something = @parser.parse
+ puts something
+ end
+end
+
diff --git a/src/thue/rule.cr b/src/thue/rule.cr
new file mode 100644
index 0000000..34c2396
--- /dev/null
+++ b/src/thue/rule.cr
@@ -0,0 +1,43 @@
+require "./thue.cr"
+
+abstract struct Thue::Rule
+ @pattern : Regex
+
+ def initialize(pattern : String)
+ @pattern = Regex.new(pattern)
+ end
+
+ def matches?(str : String) : Bool
+ str.matches?(@pattern)
+ end
+
+ abstract def replacement : String
+end
+
+struct Thue::NormalRule < Thue::Rule
+ def initialize(pattern : String, @replacement : String)
+ super(pattern)
+ end
+
+ def replacement : String
+ @replacement
+ end
+end
+
+struct Thue::InputRule < Thue::Rule
+ def replacement : String
+ gets
+ end
+end
+
+struct Thue::OutputRule < Thue::Rule
+ def initialize(pattern : String, @output : String)
+ super(pattern)
+ end
+
+ def replacement : String
+ print @output
+ return ""
+ end
+end
+
diff --git a/src/thue/thue.cr b/src/thue/thue.cr
new file mode 100644
index 0000000..9c22b96
--- /dev/null
+++ b/src/thue/thue.cr
@@ -0,0 +1,7 @@
+module Thue
+ # Allow matching empty patterns, handle during parsing
+ R_NORMAL_RULE = /^(.*)::=(.*)$/
+ R_INPUT_RULE = /^(.*)::=:::$/
+ R_OUTPUT_RULE = /^(.*)::=~(.*)$/
+end
+