zig 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +6 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +22 -0
- data/README.md +21 -0
- data/Rakefile +8 -0
- data/bin/format +12 -0
- data/data/example.json +830 -0
- data/data/example.zig +676 -0
- data/lib/zig.rb +21 -0
- data/lib/zig/formatter.rb +45 -0
- data/lib/zig/lines.rb +17 -0
- data/lib/zig/parser.rb +48 -0
- data/lib/zig/version.rb +3 -0
- data/test/zig_test.rb +164 -0
- data/zig.gemspec +19 -0
- metadata +62 -0
data/lib/zig.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require "zig/version"
|
2
|
+
require "zig/lines"
|
3
|
+
require "zig/parser"
|
4
|
+
require "zig/formatter"
|
5
|
+
|
6
|
+
require "stringio"
|
7
|
+
|
8
|
+
module ZIG
|
9
|
+
|
10
|
+
def self.parse(string)
|
11
|
+
lines = Lines.new(StringIO.new(string))
|
12
|
+
start = lines.current || raise("cannot parse empty document")
|
13
|
+
lines.next
|
14
|
+
Parser.parse_value(0, lines, start)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.print(data)
|
18
|
+
Formatter.print_value("", data)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
class ZIG::Formatter
|
2
|
+
|
3
|
+
INDENT = " " * 2
|
4
|
+
|
5
|
+
def self.print_hash(indent, hash)
|
6
|
+
print "{\n"
|
7
|
+
indent = indent + INDENT
|
8
|
+
hash.each do |key, value|
|
9
|
+
print indent + key.to_s + ": "
|
10
|
+
print_value(indent, value)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.print_array(indent, array)
|
15
|
+
print "[\n"
|
16
|
+
indent = indent + INDENT
|
17
|
+
array.each do |v|
|
18
|
+
print indent
|
19
|
+
print_value(indent, v)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.print_multiline_string(indent, string)
|
24
|
+
print "\"\n"
|
25
|
+
indent = indent + INDENT
|
26
|
+
string.split("\n").each do |line|
|
27
|
+
print indent + line.lstrip + "\n"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.print_value(indent, value)
|
32
|
+
case value
|
33
|
+
when Hash then print_hash(indent, value)
|
34
|
+
when Array then print_array(indent, value)
|
35
|
+
when String
|
36
|
+
if value.include?("\n")
|
37
|
+
print_multiline_string(indent, value)
|
38
|
+
else
|
39
|
+
print "'#{value}'\n"
|
40
|
+
end
|
41
|
+
else print value.inspect + "\n"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
data/lib/zig/lines.rb
ADDED
data/lib/zig/parser.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
class ZIG::Parser
|
2
|
+
|
3
|
+
INDENT = 2
|
4
|
+
|
5
|
+
FULL_LINE = /^( *)(.*)$/
|
6
|
+
KEY_VALUE = /^([^:]+):(.*)$/
|
7
|
+
STRING = /^'(.*)'$/
|
8
|
+
INTEGER = /^-?\d+$/
|
9
|
+
FLOAT = /^-?\d+\.\d+([eE][+-]?\d+)?$/
|
10
|
+
|
11
|
+
def self.parse_object(indent, lines, object)
|
12
|
+
loop do
|
13
|
+
return object if lines.empty?
|
14
|
+
spaces, value = lines.current.scan(FULL_LINE).flatten
|
15
|
+
return object if spaces.size < indent
|
16
|
+
raise "[line #{lines.num}] illegal indent" if spaces.size > indent
|
17
|
+
lines.next
|
18
|
+
if object.is_a?(Hash)
|
19
|
+
key, value = value.scan(KEY_VALUE).flatten
|
20
|
+
raise "[line #{lines.num}] missing key" if key.nil?
|
21
|
+
object[key.strip.to_sym] = parse_value(indent, lines, value)
|
22
|
+
elsif object.is_a?(Array)
|
23
|
+
object << parse_value(indent, lines, value)
|
24
|
+
else
|
25
|
+
object << "\n" unless object.empty?
|
26
|
+
object << value
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.parse_value(indent, lines, text)
|
32
|
+
text = text.strip
|
33
|
+
case text
|
34
|
+
when 'nil' then nil
|
35
|
+
when 'true' then true
|
36
|
+
when 'false' then false
|
37
|
+
when '{' then parse_object(indent + INDENT, lines, {})
|
38
|
+
when '[' then parse_object(indent + INDENT, lines, [])
|
39
|
+
when '"' then parse_object(indent + INDENT, lines, "")
|
40
|
+
when STRING then $1
|
41
|
+
when INTEGER then text.to_i
|
42
|
+
when FLOAT then text.to_f
|
43
|
+
else
|
44
|
+
raise "[line #{lines.num}] illegal value: #{text}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
data/lib/zig/version.rb
ADDED
data/test/zig_test.rb
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require "minitest/autorun"
|
3
|
+
require "zig"
|
4
|
+
|
5
|
+
describe ZIG do
|
6
|
+
|
7
|
+
describe "empty" do
|
8
|
+
it "should reject an empty document" do
|
9
|
+
assert_raises(RuntimeError) { ZIG.parse("") }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "literals" do
|
14
|
+
it "should parse nil" do
|
15
|
+
assert_equal nil, ZIG.parse("nil")
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should parse true" do
|
19
|
+
assert_equal true, ZIG.parse("true")
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should parse false" do
|
23
|
+
assert_equal false, ZIG.parse("false")
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should reject other literals" do
|
27
|
+
assert_raises(RuntimeError) { ZIG.parse("foo") }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "integers" do
|
32
|
+
it "should parse zero" do
|
33
|
+
assert_equal 0, ZIG.parse("0")
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should parse positive integers" do
|
37
|
+
assert_equal 7, ZIG.parse("7")
|
38
|
+
assert_equal 23, ZIG.parse("23")
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should parse negative integers" do
|
42
|
+
assert_equal -7, ZIG.parse("-7")
|
43
|
+
assert_equal -23, ZIG.parse("-23")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "floats" do
|
48
|
+
it "should parse zero" do
|
49
|
+
assert_equal 0.0, ZIG.parse("0.0")
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should parse positive floats" do
|
53
|
+
assert_equal 0.07, ZIG.parse("0.07")
|
54
|
+
assert_equal 23.9, ZIG.parse("23.9")
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should parse negative floats" do
|
58
|
+
assert_equal -0.07, ZIG.parse("-0.07")
|
59
|
+
assert_equal -23.9, ZIG.parse("-23.9")
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should parse pi" do
|
63
|
+
assert_equal 3.14159265359, ZIG.parse("3.14159265359")
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should parse exponential notation" do
|
67
|
+
assert_equal 2.3e-10, ZIG.parse("2.3e-10")
|
68
|
+
assert_equal 2.3e10, ZIG.parse("2.3e+10")
|
69
|
+
assert_equal 2.3e10, ZIG.parse("2.3e10")
|
70
|
+
assert_equal 2.3e10, ZIG.parse("2.3E10")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "strings" do
|
75
|
+
it "should parse simple strings" do
|
76
|
+
assert_equal "foo bar", ZIG.parse("'foo bar'")
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should parse unicode strings" do
|
80
|
+
assert_equal "Übung macht den Meister", ZIG.parse("'Übung macht den Meister'")
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "multiline strings" do
|
85
|
+
it "should parse multiline strings" do
|
86
|
+
doc =
|
87
|
+
%{"
|
88
|
+
one house
|
89
|
+
two houses
|
90
|
+
three houses}
|
91
|
+
assert_equal "one house\ntwo houses\nthree houses", ZIG.parse(doc)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
describe "lists" do
|
97
|
+
it "should parse an empty list" do
|
98
|
+
assert_equal [], ZIG.parse("[")
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should parse a list of simple values" do
|
102
|
+
doc =
|
103
|
+
"[
|
104
|
+
1
|
105
|
+
2
|
106
|
+
3"
|
107
|
+
assert_equal [1, 2, 3], ZIG.parse(doc)
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should parse a list of complex values" do
|
111
|
+
doc =
|
112
|
+
"[
|
113
|
+
[
|
114
|
+
23
|
115
|
+
42
|
116
|
+
[
|
117
|
+
{
|
118
|
+
a: 1
|
119
|
+
b: 2"
|
120
|
+
assert_equal [[23, 42], [], {a: 1, b: 2}], ZIG.parse(doc)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe "hashes" do
|
125
|
+
it "should parse an empty hash" do
|
126
|
+
assert_equal Hash.new, ZIG.parse("{")
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should parse a hash with simple values" do
|
130
|
+
doc =
|
131
|
+
"{
|
132
|
+
a: 1
|
133
|
+
b: 2
|
134
|
+
c: 3"
|
135
|
+
assert_equal Hash[a: 1, b: 2, c: 3], ZIG.parse(doc)
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should parse a hash with complex values" do
|
139
|
+
doc =
|
140
|
+
"{
|
141
|
+
x: {
|
142
|
+
a: 1
|
143
|
+
b: 2
|
144
|
+
y: {
|
145
|
+
z: [
|
146
|
+
true
|
147
|
+
false"
|
148
|
+
assert_equal Hash[x: {a: 1, b: 2}, y: {}, z: [true, false]], ZIG.parse(doc)
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should reject empty keys" do
|
152
|
+
doc =
|
153
|
+
"{
|
154
|
+
a: 1
|
155
|
+
: 2
|
156
|
+
c: 3"
|
157
|
+
assert_raises(RuntimeError) { ZIG.parse(doc) }
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
describe "comments" do
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
data/zig.gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'zig/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "zig"
|
8
|
+
gem.version = ZIG::VERSION
|
9
|
+
gem.authors = ["Tim Lossen"]
|
10
|
+
gem.email = ["tim@lossen.de"]
|
11
|
+
gem.description = %q{A parser for the ZIG data format.}
|
12
|
+
gem.summary = %q{A parser for the ZIG data format.}
|
13
|
+
gem.homepage = "https://github.com/tlossen/zig"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^test/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: zig
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Tim Lossen
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-11-07 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: A parser for the ZIG data format.
|
15
|
+
email:
|
16
|
+
- tim@lossen.de
|
17
|
+
executables:
|
18
|
+
- format
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- .gitignore
|
23
|
+
- Gemfile
|
24
|
+
- LICENSE.txt
|
25
|
+
- README.md
|
26
|
+
- Rakefile
|
27
|
+
- bin/format
|
28
|
+
- data/example.json
|
29
|
+
- data/example.zig
|
30
|
+
- lib/zig.rb
|
31
|
+
- lib/zig/formatter.rb
|
32
|
+
- lib/zig/lines.rb
|
33
|
+
- lib/zig/parser.rb
|
34
|
+
- lib/zig/version.rb
|
35
|
+
- test/zig_test.rb
|
36
|
+
- zig.gemspec
|
37
|
+
homepage: https://github.com/tlossen/zig
|
38
|
+
licenses: []
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options: []
|
41
|
+
require_paths:
|
42
|
+
- lib
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
none: false
|
45
|
+
requirements:
|
46
|
+
- - ! '>='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
requirements: []
|
56
|
+
rubyforge_project:
|
57
|
+
rubygems_version: 1.8.24
|
58
|
+
signing_key:
|
59
|
+
specification_version: 3
|
60
|
+
summary: A parser for the ZIG data format.
|
61
|
+
test_files:
|
62
|
+
- test/zig_test.rb
|