zig 0.0.2 → 0.0.3

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 CHANGED
@@ -2,5 +2,6 @@
2
2
  .bundle
3
3
  .config
4
4
  .yardoc
5
+ .rvmrc
5
6
  Gemfile.lock
6
7
  pkg
data/README.md CHANGED
@@ -1,24 +1,29 @@
1
1
  # ZIG
2
2
 
3
- ZIG is a simple data format. It is designed to be easily edited by hand.
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
- ZIG is indentation-based, like Python or Coffeescript.
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
- codes: [
22
- 118
23
- 192
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
- start = lines.current || raise("cannot parse empty document")
13
- lines.next
14
- Parser.parse_value(0, lines, start)
13
+ Parser.parse_document(lines)
15
14
  end
16
15
 
17
- def self.print(data)
18
- Formatter.print_value("", data)
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
@@ -2,43 +2,43 @@ class ZIG::Formatter
2
2
 
3
3
  INDENT = " " * 2
4
4
 
5
- def self.print_hash(indent, hash)
6
- print "{\n"
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
- print indent + key.to_s + ": "
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
- print "[\n"
14
+ def self.print_array(out, indent, array)
15
+ out.write("[\n")
16
16
  indent = indent + INDENT
17
17
  array.each do |v|
18
- print indent
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
- print "\"\n"
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
- print indent + line.lstrip + "\n"
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
- print "'#{value}'\n"
39
+ out.write("'#{value}'\n")
40
40
  end
41
- else print value.inspect + "\n"
41
+ else out.write(value.inspect + "\n")
42
42
  end
43
43
  end
44
44
 
@@ -1,17 +1,15 @@
1
- module ZIG
2
- class Lines
3
- attr_reader :current, :num
1
+ class ZIG::Lines
2
+ attr_reader :current, :num
4
3
 
5
- def initialize(file)
6
- @file, @current, @num = file, file.gets, 1
7
- end
4
+ def initialize(file)
5
+ @file, @current, @num = file, file.gets, 1
6
+ end
8
7
 
9
- def empty?
10
- @current.nil?
11
- end
8
+ def empty?
9
+ @current.nil?
10
+ end
12
11
 
13
- def next
14
- @current, @num = @file.gets, @num + 1
15
- end
12
+ def next
13
+ @current, @num = @file.gets, @num + 1
16
14
  end
17
15
  end
@@ -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
- if object.is_a?(Hash)
24
- key, value = value.scan(KEY_VALUE).flatten
25
- raise "[line #{lines.num}] missing key" if key.nil?
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
@@ -0,0 +1,2 @@
1
+ class ZIG::SyntaxError < StandardError
2
+ end
@@ -1,3 +1,3 @@
1
1
  module ZIG
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -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(RuntimeError) { ZIG.parse("") }
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(RuntimeError) { ZIG.parse("foo") }
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(RuntimeError) { ZIG.parse(doc) }
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(RuntimeError) { ZIG.parse(doc) }
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.2
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-08 00:00:00.000000000 Z
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
- - format
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/format
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.10
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.
data/bin/format DELETED
@@ -1,12 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require "json"
3
-
4
- begin
5
- require "zig"
6
- rescue LoadError
7
- $:.unshift File.expand_path('../lib', File.dirname(__FILE__))
8
- require "zig"
9
- end
10
-
11
- data = JSON.parse(File.read(ARGV[0]))
12
- ZIG.print(data)