jsonerino 0.1.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.
- checksums.yaml +7 -0
- data/.github/workflows/linters.yml +19 -0
- data/.gitignore +4 -0
- data/.rspec +1 -0
- data/.rubocop.yml +99 -0
- data/Gemfile +3 -0
- data/README.md +2 -0
- data/Rakefile +1 -0
- data/jsonerino.gemspec +25 -0
- data/lib/jsonerino/ast.rb +86 -0
- data/lib/jsonerino/helpers.rb +15 -0
- data/lib/jsonerino/lexer.rb +150 -0
- data/lib/jsonerino/parse_error.rb +3 -0
- data/lib/jsonerino/parser.rb +106 -0
- data/lib/jsonerino/token.rb +23 -0
- data/lib/jsonerino/version.rb +3 -0
- data/lib/jsonerino.rb +10 -0
- data/spec/spec_helper.rb +10 -0
- metadata +117 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f7de1a3c85b62c80b26f5099f936d426b18cff799a158b58b6e946fb1267db3d
|
4
|
+
data.tar.gz: 8a7823ff56d374751196550adecf7fd994eff8dc41f0b76c3ddc7523ee1b3ef5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ecfd85b22b2667b39f76c7d105f9ade3bf439fb675a3bd1c92646a501055444500a684b6d6669ef1958658704f45a8ab302c5dbd432a9eea2c96e6e881e73245
|
7
|
+
data.tar.gz: 4c1777f865965078e57820d6c58545dc11fd3fd9d8711797f3da7d26eaa04d1a61ec89732e56e253b85b53aa65202d84fd03bfab55d7192a099a35132f237c97
|
@@ -0,0 +1,19 @@
|
|
1
|
+
name: Linters
|
2
|
+
|
3
|
+
on: pull_request
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
rubocop:
|
7
|
+
name: Rubocop
|
8
|
+
runs-on: ubuntu-18.04
|
9
|
+
steps:
|
10
|
+
- uses: actions/checkout@v2
|
11
|
+
- uses: actions/setup-ruby@v1
|
12
|
+
with:
|
13
|
+
ruby-version: 2.6.x
|
14
|
+
- name: Setup Rubocop
|
15
|
+
run: |
|
16
|
+
gem install --no-document rubocop:'~>0.81.0' # https://docs.rubocop.org/en/stable/installation/
|
17
|
+
[ -f .rubocop.yml ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/ruby/.rubocop.yml
|
18
|
+
- name: Rubocop Report
|
19
|
+
run: rubocop --color
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--require spec_helper
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
AllCops:
|
2
|
+
|
3
|
+
Exclude:
|
4
|
+
|
5
|
+
- "Guardfile"
|
6
|
+
|
7
|
+
- "Rakefile"
|
8
|
+
|
9
|
+
|
10
|
+
|
11
|
+
DisplayCopNames: true
|
12
|
+
|
13
|
+
|
14
|
+
|
15
|
+
Layout/LineLength:
|
16
|
+
|
17
|
+
Max: 120
|
18
|
+
|
19
|
+
Metrics/MethodLength:
|
20
|
+
|
21
|
+
Max: 20
|
22
|
+
|
23
|
+
Metrics/AbcSize:
|
24
|
+
|
25
|
+
Max: 50
|
26
|
+
|
27
|
+
Metrics/ClassLength:
|
28
|
+
|
29
|
+
Max: 150
|
30
|
+
|
31
|
+
Metrics/BlockLength:
|
32
|
+
|
33
|
+
ExcludedMethods: ['describe']
|
34
|
+
|
35
|
+
Max: 30
|
36
|
+
|
37
|
+
|
38
|
+
|
39
|
+
|
40
|
+
|
41
|
+
Style/Documentation:
|
42
|
+
|
43
|
+
Enabled: false
|
44
|
+
|
45
|
+
Style/ClassAndModuleChildren:
|
46
|
+
|
47
|
+
Enabled: false
|
48
|
+
|
49
|
+
Style/EachForSimpleLoop:
|
50
|
+
|
51
|
+
Enabled: false
|
52
|
+
|
53
|
+
Style/AndOr:
|
54
|
+
|
55
|
+
Enabled: false
|
56
|
+
|
57
|
+
Style/DefWithParentheses:
|
58
|
+
|
59
|
+
Enabled: false
|
60
|
+
|
61
|
+
Style/FrozenStringLiteralComment:
|
62
|
+
|
63
|
+
EnforcedStyle: never
|
64
|
+
|
65
|
+
|
66
|
+
|
67
|
+
Layout/HashAlignment:
|
68
|
+
|
69
|
+
EnforcedColonStyle: key
|
70
|
+
|
71
|
+
Layout/ExtraSpacing:
|
72
|
+
|
73
|
+
AllowForAlignment: false
|
74
|
+
|
75
|
+
Layout/MultilineMethodCallIndentation:
|
76
|
+
|
77
|
+
Enabled: true
|
78
|
+
|
79
|
+
EnforcedStyle: indented
|
80
|
+
|
81
|
+
Lint/RaiseException:
|
82
|
+
|
83
|
+
Enabled: false
|
84
|
+
|
85
|
+
Lint/StructNewOverride:
|
86
|
+
|
87
|
+
Enabled: false
|
88
|
+
|
89
|
+
Style/HashEachMethods:
|
90
|
+
|
91
|
+
Enabled: false
|
92
|
+
|
93
|
+
Style/HashTransformKeys:
|
94
|
+
|
95
|
+
Enabled: false
|
96
|
+
|
97
|
+
Style/HashTransformValues:
|
98
|
+
|
99
|
+
Enabled: false
|
data/Gemfile
ADDED
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/jsonerino.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'jsonerino/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "jsonerino"
|
8
|
+
spec.version = Jsonerino::VERSION
|
9
|
+
spec.authors = ["WinterCore"]
|
10
|
+
spec.email = ["hogobbl@gmail.com"]
|
11
|
+
spec.summary = %q{JSON parser/linter}
|
12
|
+
spec.description = %q{JSON parser/linter}
|
13
|
+
spec.homepage = "https://github.com/WinterCore/microverse-ruby-capstone-json-parser"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
22
|
+
spec.add_development_dependency "rubocop", "~> 0.81.0"
|
23
|
+
spec.add_development_dependency "rake"
|
24
|
+
spec.add_development_dependency "rspec"
|
25
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module Jsonerino
|
2
|
+
class JsonValue
|
3
|
+
attr_accessor :start, :finish
|
4
|
+
end
|
5
|
+
|
6
|
+
class JsonNull < JsonValue
|
7
|
+
def resolve
|
8
|
+
nil
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class JsonBool < JsonValue
|
13
|
+
attr_reader :value
|
14
|
+
|
15
|
+
def initialize(value)
|
16
|
+
@value = value
|
17
|
+
end
|
18
|
+
|
19
|
+
def resolve
|
20
|
+
@value
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class JsonNumber < JsonValue
|
25
|
+
attr_reader :value
|
26
|
+
|
27
|
+
def initialize(value)
|
28
|
+
@value = value
|
29
|
+
end
|
30
|
+
|
31
|
+
def resolve
|
32
|
+
@value
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class JsonString < JsonValue
|
37
|
+
attr_reader :value
|
38
|
+
|
39
|
+
def initialize(value)
|
40
|
+
@value = value
|
41
|
+
end
|
42
|
+
|
43
|
+
def resolve
|
44
|
+
@value
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class JsonArray < JsonValue
|
49
|
+
attr_reader :value
|
50
|
+
|
51
|
+
def initialize()
|
52
|
+
@value = []
|
53
|
+
end
|
54
|
+
|
55
|
+
def push(value)
|
56
|
+
raise 'Value is not instnace of JsonValue' unless value.is_a? JsonValue
|
57
|
+
|
58
|
+
@value.push(value)
|
59
|
+
end
|
60
|
+
|
61
|
+
def resolve
|
62
|
+
@value.map(&:resolve)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class JsonObject < JsonValue
|
67
|
+
attr_reader :value
|
68
|
+
|
69
|
+
def initialize()
|
70
|
+
@value = {}
|
71
|
+
end
|
72
|
+
|
73
|
+
def push(key, value)
|
74
|
+
raise 'Value is not instnace of JsonValue' unless value.is_a? JsonValue
|
75
|
+
|
76
|
+
@value[key] = value
|
77
|
+
end
|
78
|
+
|
79
|
+
def resolve
|
80
|
+
@value.keys.each do |key|
|
81
|
+
@value[key] = @value[key].resolve
|
82
|
+
end
|
83
|
+
@value
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require_relative './token'
|
2
|
+
require_relative './helpers'
|
3
|
+
|
4
|
+
module Jsonerino
|
5
|
+
class Lexer
|
6
|
+
SIMPLE_TOKENS_MATCHER = [
|
7
|
+
['{', Token::TOKEN_LCURLY],
|
8
|
+
['}', Token::TOKEN_RCURLY],
|
9
|
+
['[', Token::TOKEN_LBRACKET],
|
10
|
+
[']', Token::TOKEN_RBRACKET],
|
11
|
+
[':', Token::TOKEN_COLON],
|
12
|
+
[',', Token::TOKEN_COMMA]
|
13
|
+
].freeze
|
14
|
+
|
15
|
+
SIMPLE_ESCAPE_SEQUENCES_MATCHER = [
|
16
|
+
['"', '"'],
|
17
|
+
['b', "\b"],
|
18
|
+
['f', "\f"],
|
19
|
+
['r', "\r"],
|
20
|
+
%W[n \n],
|
21
|
+
%W[t \t]
|
22
|
+
].freeze
|
23
|
+
|
24
|
+
attr_reader :i
|
25
|
+
|
26
|
+
def initialize(contents)
|
27
|
+
@contents = contents
|
28
|
+
@i = 0
|
29
|
+
@l = 1 # Line number (row)
|
30
|
+
@li = 1 # Character in current line (column)
|
31
|
+
@c = contents[@i]
|
32
|
+
end
|
33
|
+
|
34
|
+
def next_token
|
35
|
+
skip_whitespace
|
36
|
+
|
37
|
+
while more_content?
|
38
|
+
|
39
|
+
v = collect_simple_token
|
40
|
+
return v if v
|
41
|
+
|
42
|
+
# Numbers in JSON are only allowed to start with a minus sign
|
43
|
+
return collect_number if number?
|
44
|
+
|
45
|
+
return collect_string if @c == '"'
|
46
|
+
|
47
|
+
return collect_id if Helpers.alphanumeric?(@c)
|
48
|
+
|
49
|
+
raise "Unexpected character '#{@c}'"
|
50
|
+
end
|
51
|
+
nil
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def number?
|
57
|
+
Helpers.numeric?(@c) || @c == '-'
|
58
|
+
end
|
59
|
+
|
60
|
+
def skip_whitespace
|
61
|
+
while [' ', "\n", "\t"].include?(@c)
|
62
|
+
c = advance
|
63
|
+
if c == "\n"
|
64
|
+
@li = 1
|
65
|
+
@l += 1
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def advance
|
71
|
+
return unless more_content?
|
72
|
+
|
73
|
+
@i += 1
|
74
|
+
@li += 1
|
75
|
+
c = @c
|
76
|
+
@c = @contents[@i]
|
77
|
+
c
|
78
|
+
end
|
79
|
+
|
80
|
+
def collect_id
|
81
|
+
start_i = @li
|
82
|
+
str = ''
|
83
|
+
while @c && Helpers.alphanumeric?(@c)
|
84
|
+
str += @c
|
85
|
+
advance
|
86
|
+
end
|
87
|
+
Token.new Token::TOKEN_ID, str, start_i, @li, @l
|
88
|
+
end
|
89
|
+
|
90
|
+
def collect_simple_token
|
91
|
+
start_i = @li
|
92
|
+
token = Lexer::SIMPLE_TOKENS_MATCHER.find { |x| x[0] == @c }
|
93
|
+
return nil unless token
|
94
|
+
|
95
|
+
Token.new token[1], advance, start_i, @li, @l
|
96
|
+
end
|
97
|
+
|
98
|
+
def collect_string
|
99
|
+
start_i = @li
|
100
|
+
advance
|
101
|
+
str = ''
|
102
|
+
|
103
|
+
while @c && @c != '"'
|
104
|
+
str += @c == '\\' ? collect_escape_sequence : @c
|
105
|
+
advance
|
106
|
+
end
|
107
|
+
advance
|
108
|
+
|
109
|
+
Token.new Token::TOKEN_STRING, str, start_i, @li, @l
|
110
|
+
end
|
111
|
+
|
112
|
+
def collect_escape_sequence
|
113
|
+
advance
|
114
|
+
|
115
|
+
if (escape = Lexer::SIMPLE_ESCAPE_SEQUENCES_MATCHER.find { |x| x[0] == @c })
|
116
|
+
escape[1]
|
117
|
+
elsif @c == 'u'
|
118
|
+
collect_unicode_escape
|
119
|
+
else
|
120
|
+
@c
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def collect_unicode_escape
|
125
|
+
str_number = 4.times.inject('0x') do |str|
|
126
|
+
advance
|
127
|
+
raise "Invalid unicode escape sequence #{@c}" unless Helpers.hex?(@c)
|
128
|
+
|
129
|
+
str + @c
|
130
|
+
end
|
131
|
+
str_number.to_i.chr
|
132
|
+
end
|
133
|
+
|
134
|
+
def collect_number
|
135
|
+
start_i = @li
|
136
|
+
str_number = ''
|
137
|
+
loop do
|
138
|
+
str_number += @c
|
139
|
+
advance
|
140
|
+
break unless @c && (Helpers.numeric?(@c) || ['.', '-', '+', 'e', 'E'].include?(@c))
|
141
|
+
end
|
142
|
+
number = str_number.match?(/[\.e]/i) ? str_number.to_f : str_number.to_i
|
143
|
+
Token.new Token::TOKEN_NUMBER, number, start_i, @li, @l
|
144
|
+
end
|
145
|
+
|
146
|
+
def more_content?
|
147
|
+
@i < @contents.length
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require_relative './token'
|
2
|
+
require_relative './ast'
|
3
|
+
require_relative './helpers'
|
4
|
+
require_relative './parse_error'
|
5
|
+
|
6
|
+
module Jsonerino
|
7
|
+
class Parser
|
8
|
+
def initialize(lexer)
|
9
|
+
@lexer = lexer
|
10
|
+
@current_token = lexer.next_token
|
11
|
+
end
|
12
|
+
|
13
|
+
def parse
|
14
|
+
raise_end_of_data unless @current_token
|
15
|
+
|
16
|
+
v = parse_json_value
|
17
|
+
raise_unexpected_token unless v
|
18
|
+
v
|
19
|
+
end
|
20
|
+
|
21
|
+
def parse_json_value
|
22
|
+
case @current_token.token
|
23
|
+
when Token::TOKEN_LBRACKET
|
24
|
+
parse_array
|
25
|
+
when Token::TOKEN_LCURLY
|
26
|
+
parse_object
|
27
|
+
when Token::TOKEN_STRING
|
28
|
+
JsonString.new consume(Token::TOKEN_STRING)
|
29
|
+
when Token::TOKEN_NUMBER
|
30
|
+
JsonNumber.new consume(Token::TOKEN_NUMBER)
|
31
|
+
when Token::TOKEN_ID
|
32
|
+
parse_id
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def consume(token)
|
39
|
+
if @current_token.nil?
|
40
|
+
raise_end_of_data
|
41
|
+
elsif token != @current_token.token
|
42
|
+
raise_unexpected_token
|
43
|
+
end
|
44
|
+
|
45
|
+
value = @current_token.value
|
46
|
+
@current_token = @lexer.next_token
|
47
|
+
value
|
48
|
+
end
|
49
|
+
|
50
|
+
def raise_unexpected_token
|
51
|
+
message = "Unexpected token '#{@current_token.value}'"\
|
52
|
+
" at line #{@current_token.line} column #{@current_token.start} of the JSON data"
|
53
|
+
raise JsonParseError.new, message
|
54
|
+
end
|
55
|
+
|
56
|
+
def raise_end_of_data
|
57
|
+
raise JsonParseError.new, 'End of data while reading object contents of the JSON data'
|
58
|
+
end
|
59
|
+
|
60
|
+
def parse_object
|
61
|
+
consume Token::TOKEN_LCURLY
|
62
|
+
obj = JsonObject.new
|
63
|
+
if @current_token && @current_token.token != Token::TOKEN_RCURLY
|
64
|
+
loop do
|
65
|
+
key = consume(Token::TOKEN_STRING)
|
66
|
+
consume(Token::TOKEN_COLON)
|
67
|
+
value = parse
|
68
|
+
obj.push key, value
|
69
|
+
break if @current_token && @current_token.token != Token::TOKEN_COMMA
|
70
|
+
|
71
|
+
consume(Token::TOKEN_COMMA)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
consume Token::TOKEN_RCURLY
|
75
|
+
obj
|
76
|
+
end
|
77
|
+
|
78
|
+
def parse_array
|
79
|
+
consume Token::TOKEN_LBRACKET
|
80
|
+
arr = JsonArray.new
|
81
|
+
if @current_token && @current_token.token != Token::TOKEN_RBRACKET
|
82
|
+
loop do
|
83
|
+
arr.push parse
|
84
|
+
break if @current_token && @current_token.token != Token::TOKEN_COMMA
|
85
|
+
|
86
|
+
consume(Token::TOKEN_COMMA)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
consume Token::TOKEN_RBRACKET
|
90
|
+
arr
|
91
|
+
end
|
92
|
+
|
93
|
+
def parse_id
|
94
|
+
case consume(Token::TOKEN_ID)
|
95
|
+
when 'true'
|
96
|
+
JsonBool.new true
|
97
|
+
when 'false'
|
98
|
+
JsonBool.new false
|
99
|
+
when 'null'
|
100
|
+
JsonNull.new
|
101
|
+
else
|
102
|
+
raise_unexpected_token
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Jsonerino
|
2
|
+
class Token
|
3
|
+
TOKEN_ID = :token_id
|
4
|
+
TOKEN_STRING = :token_string
|
5
|
+
TOKEN_NUMBER = :token_number
|
6
|
+
TOKEN_LCURLY = :token_lcurly
|
7
|
+
TOKEN_RCURLY = :token_rcurly
|
8
|
+
TOKEN_LBRACKET = :token_lbracket
|
9
|
+
TOKEN_RBRACKET = :token_rbracket
|
10
|
+
TOKEN_COMMA = :token_comma
|
11
|
+
TOKEN_COLON = :token_colon
|
12
|
+
|
13
|
+
attr_reader :token, :value, :start, :finish, :line
|
14
|
+
|
15
|
+
def initialize(token, value, start, finish, line)
|
16
|
+
@token = token
|
17
|
+
@value = value
|
18
|
+
@start = start
|
19
|
+
@finish = finish
|
20
|
+
@line = line
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/jsonerino.rb
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
RSpec.configure do |config|
|
2
|
+
config.expect_with :rspec do |expectations|
|
3
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
4
|
+
end
|
5
|
+
|
6
|
+
config.mock_with :rspec do |mocks|
|
7
|
+
mocks.verify_partial_doubles = true
|
8
|
+
end
|
9
|
+
config.shared_context_metadata_behavior = :apply_to_host_groups
|
10
|
+
end
|
metadata
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jsonerino
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- WinterCore
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-06-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rubocop
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.81.0
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.81.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: JSON parser/linter
|
70
|
+
email:
|
71
|
+
- hogobbl@gmail.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".github/workflows/linters.yml"
|
77
|
+
- ".gitignore"
|
78
|
+
- ".rspec"
|
79
|
+
- ".rubocop.yml"
|
80
|
+
- Gemfile
|
81
|
+
- README.md
|
82
|
+
- Rakefile
|
83
|
+
- jsonerino.gemspec
|
84
|
+
- lib/jsonerino.rb
|
85
|
+
- lib/jsonerino/ast.rb
|
86
|
+
- lib/jsonerino/helpers.rb
|
87
|
+
- lib/jsonerino/lexer.rb
|
88
|
+
- lib/jsonerino/parse_error.rb
|
89
|
+
- lib/jsonerino/parser.rb
|
90
|
+
- lib/jsonerino/token.rb
|
91
|
+
- lib/jsonerino/version.rb
|
92
|
+
- spec/spec_helper.rb
|
93
|
+
homepage: https://github.com/WinterCore/microverse-ruby-capstone-json-parser
|
94
|
+
licenses:
|
95
|
+
- MIT
|
96
|
+
metadata: {}
|
97
|
+
post_install_message:
|
98
|
+
rdoc_options: []
|
99
|
+
require_paths:
|
100
|
+
- lib
|
101
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
requirements: []
|
112
|
+
rubygems_version: 3.0.3
|
113
|
+
signing_key:
|
114
|
+
specification_version: 4
|
115
|
+
summary: JSON parser/linter
|
116
|
+
test_files:
|
117
|
+
- spec/spec_helper.rb
|