aboutsummaryrefslogtreecommitdiff
path: root/ruby/reader.rb
diff options
context:
space:
mode:
authorJoel Martin <github@martintribe.org>2014-04-10 20:34:29 -0500
committerJoel Martin <github@martintribe.org>2014-04-10 20:34:29 -0500
commitf705f0fce151863091ad77753105f0d15270edec (patch)
tree788691596846567abec1606131c972d24211604c /ruby/reader.rb
parent712af9efbe15a9a65c25ab92ee2a49c8e749ed3d (diff)
downloadmal-f705f0fce151863091ad77753105f0d15270edec.tar.gz
mal-f705f0fce151863091ad77753105f0d15270edec.zip
Ruby: step0, step1
Diffstat (limited to 'ruby/reader.rb')
-rw-r--r--ruby/reader.rb74
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
+