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 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)