class Tap::ParserError < Exception end class Tap::Entry enum Status Ok NotOk def self.new(s : String) if s == "ok" Ok elsif s == "not ok" NotOk else raise ParserError.new "Invalid TAP status: '#{s}'" end end end getter id : Int32 getter status : Status getter title : String getter comment : String? def initialize(@status, @id, @title, @comment = nil) end end class Tap::Suite < Array(Tap::Entry) end module Tap def self.parse(text : String) tap : Tap::Suite? = nil text.lines.each do |line| md = line.match(/^([0-9]+)\.\.([0-9]+)$/) if md unless tap tap = Tap::Suite.new md[2].to_i else if (tap.size+1) != md[2].to_i raise ParserError.new "Number of tests parsed does not match number of tests written in suite." end end next end md = line.match(/^(not ok|ok) ([0-9]+) *- *([^#]*)(#.*)?$/) if md unless tap tap = Tap::Suite.new end tap << Tap::Entry.new Entry::Status.new(md[1]), md[2].to_i, md[3], md[4]?.try(&.gsub /^# */, "") next end raise "oh no" end tap end end