Skip to content

Instantly share code, notes, and snippets.

@dgalling
Last active August 29, 2015 13:56
Show Gist options
  • Save dgalling/8830533 to your computer and use it in GitHub Desktop.
Save dgalling/8830533 to your computer and use it in GitHub Desktop.
module RParse
class Parser
def initialize(&block)
@block = block
end
def char(c)
case @buffer[0]
when c
@buffer.slice!(0)
else
raise "Parse Error"
end
end
def decimal
chars = @buffer.chars.take_while { |c| ('0'..'9').include? c }
@buffer.slice!(0...chars.length)
chars.join.to_i
end
def digit
case @buffer[0]
when '0'..'9'
@buffer.slice!(0)
else
raise "Parse Error"
end
end
def repeat(n, name, *args)
n.times.map { method(name).call(*args) }.join
end
def parse(data)
@buffer = data
instance_eval(&@block)
end
end
end
require 'rparse/parser'
describe RParse::Parser do
it "can parse IP addresses" do
IP = Struct.new(:a, :b, :c, :d)
ip_parser = RParse::Parser.new do
d1 = decimal
char '.'
d2 = decimal
char '.'
d3 = decimal
char '.'
d4 = decimal
IP.new(d1, d2, d3, d4)
end
expect(ip_parser.parse("192.168.1.1")).to eq(IP.new(192, 168, 1, 1))
end
it "can parse years" do
year_parser = RParse::Parser.new do
year = repeat 4, :digit
end
expect(year_parser.parse "1999").to eq("1999")
end
it "can parse dates" do
date_parser = RParse::Parser.new do
year = repeat 4, :digit
char '-'
mm = repeat 2, :digit
char '-'
d = repeat 2, :digit
char ' '
h = repeat 2, :digit
char ':'
m = repeat 2, :digit
char ':'
s = repeat 2, :digit
DateTime.new(year.to_i, mm.to_i, d.to_i, h.to_i, m.to_i, s.to_i)
end
expect(date_parser.parse "1999-12-31 23:59:59").to eq(DateTime.new(1999, 12, 31, 23, 59, 59))
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment