Skip to content

Instantly share code, notes, and snippets.

@aarongough
Created October 14, 2010 19:11
Show Gist options
  • Save aarongough/626825 to your computer and use it in GitHub Desktop.
Save aarongough/626825 to your computer and use it in GitHub Desktop.
require 'benchmark'
require 'sexpistol'
require 'sxp'
class Lexer
def initialize(str)
@str = str
@p = 0
end
def next_token
while true
case c
when nil
return @token = nil
when ' ', "\n", "\r", "\t"
@p += 1
next
when '('
@p += 1
return @token = :'('
when ')'
@p += 1
return @token = :')'
when '"'
start = @p
while c! != '"' && c != nil
end
@p += 1
return @token = @str[start + 1 ... @p - 1]
when /[0-9\+\-]/
start = @p
@p += 1
while true
case c
when /[0-9]/
@p += 1
else
break
end
end
return @token = @str[start ... @p].to_i
when /[a-zA-Z\_]/
start = @p
while true
case c
when /[a-zA-Z0-9\_]/
@p += 1
else
break
end
end
return @token = @str[start ... @p].to_sym
else
raise 'Invalid character'
end
end
end
def c
x = @str[@p]
end
def c!
@p += 1
c
end
end
class Parser < Lexer
def self.parse(str)
Parser.new(str).parse
end
def parse
exp = []
while true
case next_token
when :'('
exp << parse
raise 'Missing closing parenthesis' if @token != :')'
when :')'
break
when String, Fixnum, Symbol
exp << @token
when nil
break
end
end
exp
end
end
example_sexp = <<-EOD
((display "This is a test string!")
(define test (lambda () (begin
(display (+ 1 1))
(display (+ true true))
(display (+ false false))
(display (+ nil nil))
(display (+ 2 1))
(display (+ 26 212))
))))
EOD
Benchmark.bmbm do |b|
b.report("Sexpistol") do
5000.times do
parser = Sexpistol.new
test = parser.parse_string(example_sexp)
end
end
b.report("SXP") do
5000.times do
test = SXP.read(example_sexp)
end
end
b.report("Ary") do
5000.times do
test = Parser.parse(example_sexp)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment