class RubyLisp::Reader
Constants
- TOKEN_REGEX
from kanaka/mal
Attributes
position[RW]
tokens[RW]
Public Class Methods
read_str(str)
click to toggle source
# File lib/rubylisp/reader.rb, line 197 def Reader.read_str str reader = Reader.new reader.tokenize(str) forms = [] while reader.position < reader.tokens.count forms << reader.read_form end forms end
Public Instance Methods
next_token()
click to toggle source
# File lib/rubylisp/reader.rb, line 36 def next_token token = peek @position += 1 token end
peek()
click to toggle source
# File lib/rubylisp/reader.rb, line 32 def peek @tokens[@position] end
read_atom()
click to toggle source
# File lib/rubylisp/reader.rb, line 67 def read_atom token = next_token case token when nil nil when /^\-?\d+$/ Value.new(token.to_i) when /^\-?\d+\.\d+$/ Value.new(token.to_f) when /^".*"$/ # it's safe to use eval here because the tokenizer ensures that # the token is an escaped string representation Value.new(eval(token)) # it's a little weird that an unfinished string (e.g. "abc) gets # tokenized as "", but at least the behavior is consistent ¯\_(ツ)_/¯ when "" raise ParseError, "Unexpected EOF while parsing string." when /^:/ Value.new(token[1..-1].to_sym) when 'nil' Value.new(nil) when 'true' Value.new(true) when 'false' Value.new(false) else Symbol.new(token) end end
read_deref_form()
click to toggle source
# File lib/rubylisp/reader.rb, line 121 def read_deref_form read_special_form 'deref' end
read_form()
click to toggle source
# File lib/rubylisp/reader.rb, line 148 def read_form case peek when /^;/ # ignore comments next_token read_form when '(' next_token read_list when '[' next_token read_vector when '{' next_token read_hashmap when ')' raise ParseError, "Unexpected ')'." when ']' raise ParseError, "Unexpected ']'." when '}' raise ParseError, "Unexpected '}'." when "'" next_token read_quoted_form when '`' next_token read_quasiquoted_form when '~' next_token read_unquoted_form when '~@' next_token read_splice_unquoted_form when '@' next_token read_deref_form when '^' next_token read_form_with_metadata else read_atom end end
read_form_with_metadata()
click to toggle source
# File lib/rubylisp/reader.rb, line 125 def read_form_with_metadata token = peek case token when nil raise ParseError, "Unexpected EOF while parsing metadata." when '{' next_token metadata = read_hashmap when /^:/ kw = read_form metadata = hash_map [kw, Value.new(true)] else raise ParseError, "Invalid metadata: '#{token}'" end form = read_form unless form raise ParseError, "Unexpected EOF after metadata." end list [Symbol.new("with-meta"), form, metadata] end
read_hashmap()
click to toggle source
# File lib/rubylisp/reader.rb, line 63 def read_hashmap read_seq 'hash-map', RubyLisp.method(:hash_map), '}' end
read_list()
click to toggle source
# File lib/rubylisp/reader.rb, line 55 def read_list read_seq 'list', RubyLisp.method(:list), ')' end
read_quasiquoted_form()
click to toggle source
# File lib/rubylisp/reader.rb, line 109 def read_quasiquoted_form read_special_form 'quasiquote' end
read_quoted_form()
click to toggle source
# File lib/rubylisp/reader.rb, line 105 def read_quoted_form read_special_form 'quote' end
read_seq(type_name, constructor, end_token, seq=[])
click to toggle source
# File lib/rubylisp/reader.rb, line 42 def read_seq(type_name, constructor, end_token, seq=[]) case peek when nil raise ParseError, "Unexpected EOF while parsing #{type_name}." when end_token next_token constructor.call(seq) else seq << read_form read_seq(type_name, constructor, end_token, seq) end end
read_special_form(special)
click to toggle source
# File lib/rubylisp/reader.rb, line 97 def read_special_form(special) form = read_form unless form raise ParseError, "Unexpected EOF while parsing #{special} form." end list [Symbol.new(special), form] end
read_splice_unquoted_form()
click to toggle source
# File lib/rubylisp/reader.rb, line 117 def read_splice_unquoted_form read_special_form 'splice-unquote' end
read_unquoted_form()
click to toggle source
# File lib/rubylisp/reader.rb, line 113 def read_unquoted_form read_special_form 'unquote' end
read_vector()
click to toggle source
# File lib/rubylisp/reader.rb, line 59 def read_vector read_seq 'vector', RubyLisp.method(:vec), ']' end
tokenize(str)
click to toggle source
# File lib/rubylisp/reader.rb, line 192 def tokenize str @tokens = str.strip.scan(TOKEN_REGEX).flatten[0...-1] @position = 0 end