class Ruspea::Interpreter::Reader

Constants

ARRAY_CLOSE
ARRAY_OPEN
DELIMITERS
DIGIT
ENDER
HIFEN
LIST_CLOSE
LIST_OPEN
NUMERIC
QUOTE
SEPARATOR
STRING

Public Instance Methods

call(source, forms = []) click to toggle source
# File lib/ruspea/interpreter/reader.rb, line 6
def call(source, forms = [])
  return [source, forms] if source.empty?

  code = to_list(source)

  rest, new_form =
    case code.head
    when HIFEN
      if DIGIT.match?(code.tail.head)
        numberify(code.tail, code.head)
      else
        symbolize(code)
      end
    when DELIMITERS
      # Closing lists, arrays, etc...
      return [code, forms]
    when SEPARATOR
      # ignore separators
      [code.tail, nil]
    when STRING
      stringfy(code.tail)
    when DIGIT
      numberify(code.tail, code.head)
    when LIST_OPEN
      listify(code.tail)
    when ARRAY_OPEN
      arraify(code.tail)
    when QUOTE
      quotify(code.tail)
    else
      symbolize(code)
    end

  new_forms = new_form.nil? ? forms : forms + [new_form]
  call(rest, new_forms)
end

Private Instance Methods

arraify(code) click to toggle source
# File lib/ruspea/interpreter/reader.rb, line 95
def arraify(code)
  more_code, forms = call(code)
  form = Form.new(forms, closed: ARRAY_CLOSE.match?(more_code.head))

  [more_code.tail, form]
end
floatfy(code, number) click to toggle source
# File lib/ruspea/interpreter/reader.rb, line 80
def floatfy(code, number)
  finished = code.empty? || !NUMERIC.match?(code.head)
  return [code.tail, Form.new(Float(number))] if finished

  floatfy(code.tail, number + code.head)
end
listify(code) click to toggle source
# File lib/ruspea/interpreter/reader.rb, line 87
def listify(code)
  more_code, forms = call(code)
  closed = LIST_CLOSE.match?(more_code.head)
  form = Form.new(List.create(*forms), closed: closed)

  [more_code.tail, form]
end
numberify(code, number = "") click to toggle source
# File lib/ruspea/interpreter/reader.rb, line 71
def numberify(code, number = "")
  return floatfy(code.tail, number + code.head) if code.head == "."

  finished = code.empty? || !NUMERIC.match?(code.head)
  return [code, Form.new(Integer(number))] if finished

  numberify(code.tail, number + code.head)
end
quotify(code) click to toggle source
# File lib/ruspea/interpreter/reader.rb, line 102
def quotify(code)
  more_code, content = call(code)

  invocation = List.create(
    Form.new(Sym.new("quote")),
    *content
  )

  [more_code, Form.new(invocation)]
end
read_word(word) click to toggle source
# File lib/ruspea/interpreter/reader.rb, line 120
def read_word(word)
  return word == "true" if word == "true" || word == "false"
  return nil if word == "nil"

  Sym.new(word)
end
stringfy(code, string = "") click to toggle source
# File lib/ruspea/interpreter/reader.rb, line 64
def stringfy(code, string = "")
  finished = code.head == "\"" || code.empty?
  return [code.tail, Form.new(string, closed: !code.empty?)] if finished

  stringfy(code.tail, string + code.head)
end
symbolize(code, word = "") click to toggle source
# File lib/ruspea/interpreter/reader.rb, line 113
def symbolize(code, word = "")
  finished = code.empty? || ENDER.match?(code.head)
  return [code, Form.new(read_word(word))] if finished

  symbolize(code.tail, word + code.head)
end
to_list(source) click to toggle source
# File lib/ruspea/interpreter/reader.rb, line 58
def to_list(source)
  return source if source.is_a?(Ruspea::Runtime::List)

  Ruspea::Runtime::List.create(*source.chars)
end