module AsciiTree::WordParser

Public Class Methods

parse(string) click to toggle source
# File lib/ascii_tree/word_parser.rb, line 4
def parse(string)
  chars = word_chars_with_coordinates(string)
  group_contiguous(chars).map do |word_with_coords|
    identity, value = identity_value(word_with_coords)

    Word.new(
      identity: identity.strip,
      value: value,
      start_coordinate: word_with_coords.first.last,
      end_coordinate: word_with_coords.last.last
    )
  end
end

Private Class Methods

contigous?(previous_coordinate, coordinate) click to toggle source
# File lib/ascii_tree/word_parser.rb, line 80
def contigous?(previous_coordinate, coordinate)
  previous_coordinate &&
    previous_coordinate.y == coordinate.y &&
    previous_coordinate.x == coordinate.x - 1
end
edge?(char) click to toggle source
# File lib/ascii_tree/word_parser.rb, line 29
def edge?(char)
  ["/", "|", "\\"].include?(char)
end
group_contiguous(chars) click to toggle source
# File lib/ascii_tree/word_parser.rb, line 62
def group_contiguous(chars)
  chars.each_with_object([]) do |(char, coord), array|
    prev = previous_coordinate(array)

    if contigous?(prev, coord)
      array.last << [char, coord]
    else
      array << [[char, coord]]
    end
  end
end
identity_value(word_with_coords) click to toggle source
# File lib/ascii_tree/word_parser.rb, line 37
def identity_value(word_with_coords)
  chars = word_with_coords.map(&:first)
  chars = remove_parentheses(chars)

  word = chars.join
  word.strip!

  if word.end_with?("}")
    identity, tail = word.split("{", 2)
    expression = tail[0..-2]
    value = eval(expression)
    [identity, value]
  else
    [word, nil]
  end
end
previous_coordinate(array) click to toggle source
# File lib/ascii_tree/word_parser.rb, line 74
def previous_coordinate(array)
  previous_array = array.last
  previous_tuple = previous_array.last if previous_array
  previous_tuple.last if previous_tuple
end
remove_parentheses(chars) click to toggle source
# File lib/ascii_tree/word_parser.rb, line 54
def remove_parentheses(chars)
  if chars.first == "(" && chars.last == ")"
    chars[1..-2]
  else
    chars
  end
end
whitespace?(char) click to toggle source
# File lib/ascii_tree/word_parser.rb, line 33
def whitespace?(char)
  char.match(/\s/)
end
word_chars_with_coordinates(string) click to toggle source
# File lib/ascii_tree/word_parser.rb, line 20
def word_chars_with_coordinates(string)
  toggle = ParenthesisToggle.new

  Scanner.scan(string).reject do |char, _coordinate|
    toggle.read(char)
    toggle.off? && (edge?(char) || whitespace?(char))
  end
end