Class: VDF::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/vdf/parse.rb

Overview

The Parser class is responsible for parsing a VDF document into a Ruby Hash

See Also:

Class Method Summary collapse

Class Method Details

.parse(input) ⇒ Hash

Parses a VDF document into a Ruby Hash and returns it

For large files, it’s recommended to pass the File object to VDF.parse instead of reading the whole File contents into memory

Examples:

Parse the contents of a VDF String

contents = VDF.parse(string)

Parse the contents of a VDF File

File.open("filename.vdf", "r") do |file|
  contents = VDF.parse(file)
  puts contents.inspect
end

Parameters:

  • input (String, File, #to_str, #each_line)

    the input object

Returns:

  • (Hash)

    the contents of the VDF document, parsed into a Ruby Hash

Raises:



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/vdf/parse.rb', line 31

def parse(input)
  raise ArgumentError, "Input has to respond to :each_line or :to_str" unless input.respond_to?(:each_line) || input.respond_to?(:to_str)
  input = StringIO.new(input) unless input.respond_to? :pos

  result = {}
  stack = [result]
  expect = false
  i = 0

  enum = input.each_line
  enum.with_index do |line, _|
    i += 1
    line.encode!("UTF-8").strip!
    next if line.empty? || line[0] == -'/'

    if line.start_with?(-'{')
      expect = false
      next
    elsif expect
      raise ParserError, "Invalid syntax on line #{i+1} (Expected bracket)"
    end

    if line.start_with?(-'}')
      stack.pop
      next
    end

    loop do
      if (m = REGEX.match(line)).nil?
        raise ParserError, "Invalid syntax on line #{i+1} (Line didn't match regex)"
      end

      key = m[2] || m[3]
      val = m[6] || m[8]

      if val.nil?
        if stack[-1][key].nil?
          stack[-1][key] = {}
        end
        stack << stack[-1][key]
        expect = true
      else
        if m[7].nil? && m[8].nil?
          if (next_line = enum.next).nil?
            raise ParserError, "Invalid syntax on line #{i+1} (Unexpected EOF)"
          end

          i += 1
          line << -"\n" << next_line.to_s.encode("UTF-8").strip
          next
        end

        stack[-1][key] = begin
          begin
            Integer(val)
          rescue ArgumentError
            Float(val)
          end
        rescue ArgumentError
          case val.downcase
          when -"true"
            true
          when -"false"
            false
          when -"null"
            nil
          else
            val
          end
        end
      end

      break
    end
  end

  raise ParserError, "Open parentheses somewhere" unless stack.length == 1

  return result
end