zig 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/README.md +15 -10
- data/bin/zig +48 -0
- data/lib/zig.rb +7 -5
- data/lib/zig/formatter.rb +17 -17
- data/lib/zig/lines.rb +10 -12
- data/lib/zig/parser.rb +16 -9
- data/lib/zig/syntax_error.rb +2 -0
- data/lib/zig/version.rb +1 -1
- data/test/zig_test.rb +27 -4
- metadata +6 -5
- data/bin/format +0 -12
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,24 +1,29 @@
|
|
1
1
|
# ZIG
|
2
2
|
|
3
|
-
|
3
|
+
Zig is a simple data format. It is designed to be edited by hand.
|
4
4
|
It is also pretty easy to parse and generate, though.
|
5
|
+
You can think of Zig as an alternate, indentation-based
|
6
|
+
syntax for JSON.
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
Here is a short example:
|
8
|
+
Here is a short example that shows all data structures:
|
9
9
|
|
10
10
|
```
|
11
11
|
{
|
12
12
|
type: 'error'
|
13
|
+
subtype: nil
|
14
|
+
description: "
|
15
|
+
Check your Internet connection. Restart any router, modem,
|
16
|
+
or other network devices you may be using.
|
13
17
|
color: {
|
14
18
|
r: 255
|
15
19
|
g: 192
|
16
20
|
b: 0
|
17
|
-
description: "
|
18
|
-
Check your Internet connection. Restart any router, modem,
|
19
|
-
or other network devices you may be using.
|
20
21
|
# TODO: do we need these any more?
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
flags: [
|
23
|
+
true
|
24
|
+
false
|
25
|
+
true
|
24
26
|
```
|
27
|
+
|
28
|
+
In order of appearance: hash, string, nil, multiline string, number,
|
29
|
+
comment, list, boolean.
|
data/bin/zig
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "zig"
|
3
|
+
require "optparse"
|
4
|
+
|
5
|
+
def fail_with(message)
|
6
|
+
$stderr.puts message
|
7
|
+
exit 1
|
8
|
+
end
|
9
|
+
|
10
|
+
def parse_zig(file)
|
11
|
+
ZIG::Parser.parse_document(ZIG::Lines.new(File.open(file)))
|
12
|
+
rescue ZIG::SyntaxError => e
|
13
|
+
fail_with(e.message)
|
14
|
+
end
|
15
|
+
|
16
|
+
def parse_json(file)
|
17
|
+
require "json"
|
18
|
+
JSON.parse(File.read(file))
|
19
|
+
rescue JSON::ParserError => e
|
20
|
+
fail_with(e.message)
|
21
|
+
end
|
22
|
+
|
23
|
+
output = nil
|
24
|
+
OptionParser.new do |opts|
|
25
|
+
opts.on("-o", "--output [format]", "convert to output format") do |format|
|
26
|
+
output = format
|
27
|
+
end
|
28
|
+
end.parse!
|
29
|
+
|
30
|
+
_, ending = ARGV[0].split(".")
|
31
|
+
data = case ending
|
32
|
+
when "zig"
|
33
|
+
parse_zig(ARGV[0])
|
34
|
+
when "json"
|
35
|
+
parse_json(ARGV[0])
|
36
|
+
end
|
37
|
+
|
38
|
+
case output
|
39
|
+
when nil
|
40
|
+
# no output
|
41
|
+
when "zig"
|
42
|
+
puts ZIG.generate(data)
|
43
|
+
when "json"
|
44
|
+
require "json"
|
45
|
+
puts JSON.pretty_generate(data)
|
46
|
+
else
|
47
|
+
fail_with("unknown format: #{output}")
|
48
|
+
end
|
data/lib/zig.rb
CHANGED
@@ -2,6 +2,7 @@ require "zig/version"
|
|
2
2
|
require "zig/lines"
|
3
3
|
require "zig/parser"
|
4
4
|
require "zig/formatter"
|
5
|
+
require "zig/syntax_error"
|
5
6
|
|
6
7
|
require "stringio"
|
7
8
|
|
@@ -9,13 +10,14 @@ module ZIG
|
|
9
10
|
|
10
11
|
def self.parse(string)
|
11
12
|
lines = Lines.new(StringIO.new(string))
|
12
|
-
|
13
|
-
lines.next
|
14
|
-
Parser.parse_value(0, lines, start)
|
13
|
+
Parser.parse_document(lines)
|
15
14
|
end
|
16
15
|
|
17
|
-
def self.
|
18
|
-
|
16
|
+
def self.generate(data)
|
17
|
+
out = StringIO.new
|
18
|
+
Formatter.print_value(out, "", data)
|
19
|
+
out.rewind
|
20
|
+
out.read
|
19
21
|
end
|
20
22
|
|
21
23
|
end
|
data/lib/zig/formatter.rb
CHANGED
@@ -2,43 +2,43 @@ class ZIG::Formatter
|
|
2
2
|
|
3
3
|
INDENT = " " * 2
|
4
4
|
|
5
|
-
def self.print_hash(indent, hash)
|
6
|
-
|
5
|
+
def self.print_hash(out, indent, hash)
|
6
|
+
out.write("{\n")
|
7
7
|
indent = indent + INDENT
|
8
8
|
hash.each do |key, value|
|
9
|
-
|
10
|
-
print_value(indent, value)
|
9
|
+
out.write(indent + key.to_s + ": ")
|
10
|
+
print_value(out, indent, value)
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
def self.print_array(indent, array)
|
15
|
-
|
14
|
+
def self.print_array(out, indent, array)
|
15
|
+
out.write("[\n")
|
16
16
|
indent = indent + INDENT
|
17
17
|
array.each do |v|
|
18
|
-
|
19
|
-
print_value(indent, v)
|
18
|
+
out.write(indent)
|
19
|
+
print_value(out, indent, v)
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
def self.print_multiline_string(indent, string)
|
24
|
-
|
23
|
+
def self.print_multiline_string(out, indent, string)
|
24
|
+
out.write("\"\n")
|
25
25
|
indent = indent + INDENT
|
26
26
|
string.split("\n").each do |line|
|
27
|
-
|
27
|
+
out.write(indent + line.lstrip + "\n")
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
def self.print_value(indent, value)
|
31
|
+
def self.print_value(out, indent, value)
|
32
32
|
case value
|
33
|
-
when Hash then print_hash(indent, value)
|
34
|
-
when Array then print_array(indent, value)
|
33
|
+
when Hash then print_hash(out, indent, value)
|
34
|
+
when Array then print_array(out, indent, value)
|
35
35
|
when String
|
36
36
|
if value.include?("\n")
|
37
|
-
print_multiline_string(indent, value)
|
37
|
+
print_multiline_string(out, indent, value)
|
38
38
|
else
|
39
|
-
|
39
|
+
out.write("'#{value}'\n")
|
40
40
|
end
|
41
|
-
else
|
41
|
+
else out.write(value.inspect + "\n")
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
data/lib/zig/lines.rb
CHANGED
@@ -1,17 +1,15 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
attr_reader :current, :num
|
1
|
+
class ZIG::Lines
|
2
|
+
attr_reader :current, :num
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
def initialize(file)
|
5
|
+
@file, @current, @num = file, file.gets, 1
|
6
|
+
end
|
8
7
|
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
def empty?
|
9
|
+
@current.nil?
|
10
|
+
end
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
end
|
12
|
+
def next
|
13
|
+
@current, @num = @file.gets, @num + 1
|
16
14
|
end
|
17
15
|
end
|
data/lib/zig/parser.rb
CHANGED
@@ -13,20 +13,19 @@ class ZIG::Parser
|
|
13
13
|
return object if lines.empty?
|
14
14
|
spaces, value = lines.current.scan(FULL_LINE).flatten
|
15
15
|
return object if spaces.size < indent
|
16
|
-
raise "[line #{lines.num}] illegal indent" if spaces.size > indent
|
16
|
+
raise ZIG::SyntaxError, "[line #{lines.num}] illegal indent" if spaces.size > indent
|
17
17
|
lines.next
|
18
18
|
if object.is_a?(String)
|
19
19
|
object << "\n" unless object.empty?
|
20
20
|
object << value
|
21
|
+
elsif object.is_a?(Array)
|
22
|
+
next if value[0] == '#'
|
23
|
+
object << parse_value(indent, lines, value)
|
21
24
|
else
|
22
25
|
next if value[0] == '#'
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
object[key.strip.to_sym] = parse_value(indent, lines, value)
|
27
|
-
else
|
28
|
-
object << parse_value(indent, lines, value)
|
29
|
-
end
|
26
|
+
key, value = value.scan(KEY_VALUE).flatten
|
27
|
+
raise ZIG::SyntaxError, "[line #{lines.num - 1}] missing key" if key.nil?
|
28
|
+
object[key.strip.to_sym] = parse_value(indent, lines, value)
|
30
29
|
end
|
31
30
|
end
|
32
31
|
end
|
@@ -44,8 +43,16 @@ class ZIG::Parser
|
|
44
43
|
when INTEGER then text.to_i
|
45
44
|
when FLOAT then text.to_f
|
46
45
|
else
|
47
|
-
raise "[line #{lines.num}] illegal value: #{text}"
|
46
|
+
raise ZIG::SyntaxError, "[line #{lines.num}] illegal value: #{text}"
|
48
47
|
end
|
49
48
|
end
|
50
49
|
|
50
|
+
def self.parse_document(lines)
|
51
|
+
raise ZIG::SyntaxError, "cannot parse empty document" if lines.empty?
|
52
|
+
lines.next while lines.current[0] == '#'
|
53
|
+
start = lines.current
|
54
|
+
lines.next
|
55
|
+
return parse_value(0, lines, start)
|
56
|
+
end
|
57
|
+
|
51
58
|
end
|
data/lib/zig/version.rb
CHANGED
data/test/zig_test.rb
CHANGED
@@ -6,7 +6,7 @@ describe ZIG do
|
|
6
6
|
|
7
7
|
describe "empty" do
|
8
8
|
it "should reject an empty document" do
|
9
|
-
assert_raises(
|
9
|
+
assert_raises(ZIG::SyntaxError) { ZIG.parse("") }
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
@@ -24,7 +24,7 @@ describe ZIG do
|
|
24
24
|
end
|
25
25
|
|
26
26
|
it "should reject other literals" do
|
27
|
-
assert_raises(
|
27
|
+
assert_raises(ZIG::SyntaxError) { ZIG.parse("foo") }
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
@@ -107,6 +107,15 @@ describe ZIG do
|
|
107
107
|
assert_equal [1, 2, 3], ZIG.parse(doc)
|
108
108
|
end
|
109
109
|
|
110
|
+
it "should parse nested empty lists" do
|
111
|
+
doc =
|
112
|
+
"[
|
113
|
+
[
|
114
|
+
[
|
115
|
+
["
|
116
|
+
assert_equal [[], [], []], ZIG.parse(doc)
|
117
|
+
end
|
118
|
+
|
110
119
|
it "should parse a list of complex values" do
|
111
120
|
doc =
|
112
121
|
"[
|
@@ -154,16 +163,29 @@ describe ZIG do
|
|
154
163
|
a: 1
|
155
164
|
: 2
|
156
165
|
c: 3"
|
157
|
-
assert_raises(
|
166
|
+
assert_raises(ZIG::SyntaxError) { ZIG.parse(doc) }
|
158
167
|
end
|
159
168
|
end
|
160
169
|
|
161
170
|
describe "comments" do
|
171
|
+
it "should skip comment lines at the start of a document" do
|
172
|
+
doc =
|
173
|
+
"# IMPORTANT
|
174
|
+
{
|
175
|
+
a: 1
|
176
|
+
b: 2
|
177
|
+
c: 3"
|
178
|
+
assert_equal Hash[a: 1, b: 2, c: 3], ZIG.parse(doc)
|
179
|
+
end
|
180
|
+
|
181
|
+
|
182
|
+
|
162
183
|
it "should skip comment lines inside hashes" do
|
163
184
|
doc =
|
164
185
|
"{
|
165
186
|
a: 1
|
166
187
|
#b: 2
|
188
|
+
#b: 2
|
167
189
|
c: 3"
|
168
190
|
assert_equal Hash[a: 1, c: 3], ZIG.parse(doc)
|
169
191
|
end
|
@@ -173,6 +195,7 @@ describe ZIG do
|
|
173
195
|
"[
|
174
196
|
'one'
|
175
197
|
#'two'
|
198
|
+
#'two'
|
176
199
|
'three'"
|
177
200
|
assert_equal %w[one three], ZIG.parse(doc)
|
178
201
|
end
|
@@ -191,7 +214,7 @@ describe ZIG do
|
|
191
214
|
a: 1
|
192
215
|
# TODO: check c
|
193
216
|
c: 3"
|
194
|
-
assert_raises(
|
217
|
+
assert_raises(ZIG::SyntaxError) { ZIG.parse(doc) }
|
195
218
|
end
|
196
219
|
|
197
220
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zig
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,13 +9,13 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-11-
|
12
|
+
date: 2012-11-11 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: A parser for the ZIG data format.
|
15
15
|
email:
|
16
16
|
- tim@lossen.de
|
17
17
|
executables:
|
18
|
-
-
|
18
|
+
- zig
|
19
19
|
extensions: []
|
20
20
|
extra_rdoc_files: []
|
21
21
|
files:
|
@@ -24,13 +24,14 @@ files:
|
|
24
24
|
- LICENSE.txt
|
25
25
|
- README.md
|
26
26
|
- Rakefile
|
27
|
-
- bin/
|
27
|
+
- bin/zig
|
28
28
|
- data/example.json
|
29
29
|
- data/example.zig
|
30
30
|
- lib/zig.rb
|
31
31
|
- lib/zig/formatter.rb
|
32
32
|
- lib/zig/lines.rb
|
33
33
|
- lib/zig/parser.rb
|
34
|
+
- lib/zig/syntax_error.rb
|
34
35
|
- lib/zig/version.rb
|
35
36
|
- test/zig_test.rb
|
36
37
|
- zig.gemspec
|
@@ -54,7 +55,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
54
55
|
version: '0'
|
55
56
|
requirements: []
|
56
57
|
rubyforge_project:
|
57
|
-
rubygems_version: 1.8.
|
58
|
+
rubygems_version: 1.8.24
|
58
59
|
signing_key:
|
59
60
|
specification_version: 3
|
60
61
|
summary: A parser for the ZIG data format.
|