class Savage::Parser

Constants

DIRECTIONS

Public Class Methods

parse(parsable) click to toggle source
# File lib/savage/parser.rb, line 25
def parse(parsable)
  raise TypeError if parsable.class != String
  subpaths = extract_subpaths parsable
  raise TypeError if (subpaths.empty?)
  path = Path.new
  path.subpaths = []
  subpaths.each_with_index do |subpath, i|
    path.subpaths << parse_subpath(subpath, i == 0)
  end
  path
end

Private Class Methods

build_direction(parsable, force_absolute=false) click to toggle source
# File lib/savage/parser.rb, line 72
def build_direction(parsable, force_absolute=false)
  directions = []
  @coordinates = extract_coordinates parsable
  recurse_code = parsable[0,1]
  first_absolute = force_absolute
  
  # we need to handle this separately, since ClosePath doesn't take any coordinates
  if @coordinates.empty? && recurse_code =~ /[Zz]/
    directions << Directions::ClosePath.new(parsable[0,1] == parsable[0,1].upcase)
  end
  
  until @coordinates.empty?
    absolute = (first_absolute || parsable[0,1] == parsable[0,1].upcase)
    directions << construct_direction(recurse_code.strip[0].downcase.intern, absolute)
    recurse_code = 'L' if recurse_code.downcase =~ /m/
    first_absolute = false
  end
  
  directions
end
construct_direction(recurse_code, absolute) click to toggle source
# File lib/savage/parser.rb, line 93
def construct_direction(recurse_code, absolute)
  args = @coordinates.shift DIRECTIONS[recurse_code][:args]
  raise TypeError if args.any?(&:nil?)
  DIRECTIONS[recurse_code][:class].new(*args, absolute)
end
extract_coordinates(command_string) click to toggle source
# File lib/savage/parser.rb, line 99
def extract_coordinates(command_string)
  coordinates = []
  command_string.scan(/-?\d+(\.\d+)?([eE][+-]?\d+)?/) do |match_group|
    coordinates << $&.to_f
  end
  coordinates
end
extract_directions(parsable, force_absolute=false) click to toggle source
# File lib/savage/parser.rb, line 57
def extract_directions(parsable, force_absolute=false)
  directions = []
  i = 0
  parsable.scan(/[MmLlHhVvQqCcTtSsAaZz](?:\d|[eE.,+-]|\W)*/m) do |match_group|
    direction = build_direction $&, force_absolute && i == 0
    if direction.kind_of?(Array)
      directions.concat direction
    else
      directions << direction
    end
    i += 1
  end
  directions
end
extract_subpaths(parsable) click to toggle source
# File lib/savage/parser.rb, line 38
def extract_subpaths(parsable)
  subpaths = []
  if move_index = parsable.index(/[Mm]/)
    subpaths << parsable[0...move_index] if move_index > 0
    parsable.scan(/[Mm](?:\d|[eE.,+-]|[LlHhVvQqCcTtSsAaZz]|\W)+/m) do |match_group|
      subpaths << $&
    end
  else
    subpaths << parsable
  end
  subpaths
end
parse_subpath(parsable, force_absolute=false) click to toggle source
# File lib/savage/parser.rb, line 51
def parse_subpath(parsable, force_absolute=false)
  subpath = SubPath.new
  subpath.directions = extract_directions parsable, force_absolute
  subpath
end