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