Skip to content

Commit

Permalink
Fixed an array parsing bug
Browse files Browse the repository at this point in the history
  • Loading branch information
Shannarra committed Jul 15, 2024
1 parent c4e678a commit 986973d
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 6 deletions.
28 changes: 27 additions & 1 deletion main.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,33 @@ def self.parse!(text)
end

def main
value = JRB.parse! '{"items":[1,6.9,-1200000,"Hello World!",[1,2,3],{"name":"John Doe", "false": true, "true": false, "value": null}]}'
value = JRB.parse! '
{
"hello": "world",
"items": [
1,
6.9,
-1200000,
"Hello World!",
[
1,
2,
3
],
{
"name": "John Doe",
"false": true,
"true": false,
"value": null
}
],
"foo": {
"data": {
"weirdnum": null
},
"asd": "ASD"
}
}'
puts value
puts value.dig('foo', 'data', 'weirdnum')

Expand Down
101 changes: 100 additions & 1 deletion spec/parser_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def parse!(text)
end

it 'mixed bag' do
text = '{"items":[1,6.9,-12e5,"Hello World!",{"name":"John Doe"}, [2,3,4,5,6]}'
text = '{"items":[1,6.9,-12e5,"Hello World!",{"name":"John Doe"}, [2,3,4,5,6]}}'

result = parse! text

Expand Down Expand Up @@ -190,6 +190,105 @@ def parse!(text)
expect(drug['strength']).to eq '"500 mg"'
end
end

context 'for tricky before-and-after array values' do
let(:text) do
'{
"hello": "world",
"items": [
1,
6.9,
-1.2e6,
"Hello World!",
null,
false,
true,
[
1,
2,
3
],
{
"name": "John Doe",
"false": true,
"true": false,
"value": null
}
],
"foo": {
"data": {
"weirdnum": -4.20e69
},
"asd": "ASD"
}
}'
end

before(:each) do
@result = parse! text

@items_result = [
1,
6.9,
-1_200_000,
'"Hello World!"',
nil,
false,
true,
[
1,
2,
3
],
{
'name' => '"John Doe"',
'false' => true,
'true' => false,
'value' => nil
}
]
end

it 'handles values before array' do
expect(@result['hello']).to eq '"world"'
end

context 'handles the array correctly' do
before(:each) do
@arr = @result['items']
end

it 'and has correct length' do
expect(@arr.length).to eq @items_result.length
end

it 'and has matching values for simple values' do
expect(@arr[..-2]).to match_array @items_result[..-2]
end

it 'and has matching values for nested arrays' do
expect(@arr[-3..-2]).to match_array @items_result[-3..-2]
end

it 'and has matching values for nested objects' do
expect(@arr[-1]).to match @items_result[-1]
end
end

context 'handles values after array' do
before(:each) do
@obj = @result['foo']
end

it 'and nested objects correctly' do
expect(@obj.dig('data', 'weirdnum')).to eq(-4.20e69) # nice
end

it 'and object\'s values correctly' do
expect(@obj['asd']).to eq '"ASD"'
end
end
end
end
end
# rubocop:enable Metrics/BlockLength
7 changes: 3 additions & 4 deletions src/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ def parse_object
elsif current != JSON[:SYMBOLS][:COMMA]
return object unless current

next if current.string_token?

error! "Expected a comma after a key-value pair in object, got an \"#{unwrap! current}\""
end

Expand All @@ -80,10 +82,7 @@ def parse_object
def parse_array
array = []

if current == JSON[:SYMBOLS][:RIGHTBRACKET]
advance
return array
end
return array if current == JSON[:SYMBOLS][:RIGHTBRACKET]

while current
item = parse(offset: @ip)
Expand Down
4 changes: 4 additions & 0 deletions src/token.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,8 @@ def ==(other)

type == other.type && value == other.value
end

TokenType.constants.map { |type| type.to_s.downcase }.each do |type|
define_method("#{type}_token?") { is_a?(Token) && self.type == type.capitalize }
end
end

0 comments on commit 986973d

Please sign in to comment.