class Giter8::Parsers::PairsParser

PairsParser implements an FSM for parsing a key-value string containing property pairs for rendering.

Constants

ALPHA_REGEXP
CHR_CARRIAGE_RETURN
CHR_EQUAL
CHR_HASH
CHR_NEWLINE
CHR_SPACE
CHR_TAB
STATE_COMMENT
STATE_KEY
STATE_VALUE
WHITE_CHARS

Public Class Methods

new(opts = {}) click to toggle source

Initialises a new PairsParser instance. See also: PairsParser.parse

# File lib/giter8/parsers/pairs_parser.rb, line 33
def initialize(opts = {})
  @pairs = []
  @state = STATE_KEY
  @tmp_key = []
  @tmp_val = []
  @source = opts[:source] || "unknown"
  @column = 0
  @line = 1
end
parse(input, opts = {}) click to toggle source

Parses a given key-value pair list within a string with provided options. Options is a hash that currently only supports the :source key, which must be the name of the file being parsed. This key is used to identify any errors whilst parsing the contents and will be provided on any raised errors. Returns an Pairs object with the read properties.

# File lib/giter8/parsers/pairs_parser.rb, line 27
def self.parse(input, opts = {})
  new(opts).parse(input)
end

Public Instance Methods

parse(input) click to toggle source

Parses a given input string into key-value Pair objects. Returns an Pairs object of identified keys and values.

# File lib/giter8/parsers/pairs_parser.rb, line 45
def parse(input)
  input.chars.each do |chr|
    chr = chr.chr
    case @state
    when STATE_KEY
      parse_key(chr)

    when STATE_COMMENT
      @state = STATE_KEY if chr == CHR_NEWLINE

    when STATE_VALUE
      parse_value(chr)
    end

    @column += 1
    if chr == CHR_NEWLINE
      @line += 1
      @column = 0
    end
  end

  finish_parse
end

Private Instance Methods

finish_parse() click to toggle source
# File lib/giter8/parsers/pairs_parser.rb, line 115
def finish_parse
  raise Giter8::Error, "unexpected end of input at #{location}" if @state == STATE_KEY && !@tmp_key.empty?

  push_result if @state == STATE_VALUE

  result = Pairs.new(@pairs)
  reset_tmp
  @state = STATE_KEY
  @pairs = []
  result
end
location() click to toggle source

Returns the current FSM's location as a string representation in the format SOURCE_FILE_NAME:LINE:COLUMN

# File lib/giter8/parsers/pairs_parser.rb, line 73
def location
  "#{@source}:#{line}:#{column}"
end
parse_key(chr) click to toggle source

Parses a given character into the current key's key property. Raises an error in case the character is not accepted as a valid candidate for a key identifier.

# File lib/giter8/parsers/pairs_parser.rb, line 80
def parse_key(chr)
  if @tmp_key.empty? && WHITE_CHARS.include?(chr)
    nil
  elsif @tmp_key.empty? && chr == CHR_HASH
    @state = STATE_COMMENT
  elsif @tmp_key.empty? && !ALPHA_REGEXP.match?(chr)
    raise Giter8::Error, "unexpected char #{chr} at #{location}"
  elsif chr == CHR_EQUAL
    @state = STATE_VALUE
  else
    @tmp_key << chr
  end
end
parse_value(chr) click to toggle source

Consumes provided characters until a newline is reached.

# File lib/giter8/parsers/pairs_parser.rb, line 95
def parse_value(chr)
  if chr != CHR_NEWLINE
    @tmp_val << chr
    return
  end

  push_result
  @state = STATE_KEY
end
push_result() click to toggle source
# File lib/giter8/parsers/pairs_parser.rb, line 110
def push_result
  @pairs << Pair.new(@tmp_key.join.strip, @tmp_val.join.strip)
  reset_tmp
end
reset_tmp() click to toggle source
# File lib/giter8/parsers/pairs_parser.rb, line 105
def reset_tmp
  @tmp_key = []
  @tmp_val = []
end