diff options
Diffstat (limited to 'src/thue')
| -rw-r--r-- | src/thue/parser.cr | 50 | ||||
| -rw-r--r-- | src/thue/program.cr | 13 | ||||
| -rw-r--r-- | src/thue/rule.cr | 43 | ||||
| -rw-r--r-- | src/thue/thue.cr | 7 |
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 + |
