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