class Atom def initialize(content = nil) @content = content end attr_reader :content def to_s content end def self.from_token(token) new(token.content) end end class SExp def initialize(addr = nil, data = nil) @addr = addr @data = data end def car @addr end def car=(addr) @addr = addr end def cdr @data end def cdr=(data) @data = data end def to_s if car.nil? "()" elsif cdr.nil? "(#{car} . ())" else "(#{car} . #{cdr})" end end end def peek_token(tokens) tokens.first end def get_token(tokens) tokens.shift end def num_members(tokens) members = 0 level = 1 at = 1 until level == 0 case tokens.at(at) when T_LParen members += 1 if level == 1 level += 1 when T_RParen level -= 1 when T_Atom members += 1 if level == 1 end at += 1 end members end def members_to_tree(members) case members.length when 0 nil when 1 SExp.new(members[0], SExp.new) when 2 SExp.new(members[0], members[1]) else SExp.new(members[0], members_to_tree(members[1..-1])) end end def parse_sexp(tokens) need = num_members(tokens) get_token(tokens) members = [] need.times do case peek_token(tokens) when T_Atom members << Atom.from_token(get_token(tokens)) when T_LParen members << parse_sexp(tokens) end end get_token(tokens) members_to_tree(members) end def parse_sexps(tokens) sexps = [] until tokens.empty? sexps << parse_sexp(tokens) end sexps end