From cd9f3bc3f3ecb04eaee42c65880711bd35c7e71b Mon Sep 17 00:00:00 2001 From: Matthew Hall Date: Sat, 3 Sep 2022 16:07:58 +1200 Subject: Able to parse Thue code --- src/thue/parser.cr | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/thue/parser.cr (limited to 'src/thue/parser.cr') 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 + -- cgit v1.2.1