diff options
| author | Joel Martin <github@martintribe.org> | 2014-04-10 20:34:29 -0500 |
|---|---|---|
| committer | Joel Martin <github@martintribe.org> | 2014-04-10 20:34:29 -0500 |
| commit | f705f0fce151863091ad77753105f0d15270edec (patch) | |
| tree | 788691596846567abec1606131c972d24211604c /ruby/reader.rb | |
| parent | 712af9efbe15a9a65c25ab92ee2a49c8e749ed3d (diff) | |
| download | mal-f705f0fce151863091ad77753105f0d15270edec.tar.gz mal-f705f0fce151863091ad77753105f0d15270edec.zip | |
Ruby: step0, step1
Diffstat (limited to 'ruby/reader.rb')
| -rw-r--r-- | ruby/reader.rb | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/ruby/reader.rb b/ruby/reader.rb new file mode 100644 index 0000000..d224e9c --- /dev/null +++ b/ruby/reader.rb @@ -0,0 +1,74 @@ +require "types" + +class Reader + def initialize(tokens) + @position = 0 + @tokens = tokens + end + def peek + return @tokens[@position] + end + def next + @position += 1 + return @tokens[@position-1] + end +end + + +def tokenize(str) + re = /[\s,]*(~@|[\[\]{}()'`~^@]|"(?:\\.|[^\\"])*"|;.*|[^\s\[\]{}('"`,;)]*)/ + return str.scan(re).map{|m| m[0]}.select{|m| m != ""} +end + +def parse_str(t) + return t[1..-2].gsub(/\\"/, "\"").gsub(/\\n/, "\n") +end + +def read_atom(rdr) + token = rdr.next + return case token + when /^-?[0-9]+$/ then token.to_i # integer + when /^-?[0-9][0-9.]*$/ then token.to_f # float + when /^"/ then parse_str(token) # string + when "nil" then nil + when "true" then true + when "false" then false + else token.to_sym # symbol + end +end + +def read_list(rdr, klass, start="(", last =")") + ast = klass.new + token = rdr.next() + if token != start + raise "expected '" + start + "'" + end + while (token = rdr.peek) != last + if not token + raise "expected '" + last + "', got EOF" + end + ast.push(read_form(rdr)) + end + rdr.next + return ast +end + +def read_form(rdr) + token = rdr.peek + return case rdr.peek + when ";" then nil + when "(" then read_list(rdr, List, "(", ")") + when ")" then raise "unexpected ')'" + when "[" then read_list(rdr, Vector, "[", "]") + when "]" then raise "unexpected ']'" + when "{" then raise "unexpected '{'" + when "}" then raise "unexpected '}'" + else read_atom(rdr) + end +end + +def read_str(str) + tokens = tokenize(str) + return read_form(Reader.new(tokens)) +end + |
