summaryrefslogtreecommitdiff
path: root/src/thue
diff options
context:
space:
mode:
authorMatthew Hall <hallmatthew314@gmail.com>2022-09-03 16:07:58 +1200
committerMatthew Hall <hallmatthew314@gmail.com>2022-09-03 16:07:58 +1200
commitcd9f3bc3f3ecb04eaee42c65880711bd35c7e71b (patch)
tree48d76a9bfaaa7959de7a9689277b8e01e78286b1 /src/thue
parent95e20a4662c96372b62441a4c598df0f29851834 (diff)
Able to parse Thue code
Diffstat (limited to 'src/thue')
-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
4 files changed, 113 insertions, 0 deletions
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
+