summaryrefslogtreecommitdiff
path: root/src/thue/parser.cr
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/parser.cr
parent95e20a4662c96372b62441a4c598df0f29851834 (diff)
Able to parse Thue code
Diffstat (limited to 'src/thue/parser.cr')
-rw-r--r--src/thue/parser.cr50
1 files changed, 50 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
+