diff --git a/json5/json5.g b/json5/json5.g index 7cafff3..2e00636 100644 --- a/json5/json5.g +++ b/json5/json5.g @@ -118,7 +118,7 @@ id_esc_continue = id_esc_start | ~~('u' ('200C' | '200c' | '200D' | '200d')) unicode_esc num_literal = '-' unsigned_lit:n -> '-' + n - | '+' unsigned_lit:n -> n + | '+' unsigned_lit:n -> '+' + n | unsigned_lit:n -> n unsigned_lit = dec_literal:d ~id_start -> d diff --git a/json5/lib.py b/json5/lib.py index 91c2b46..9c76355 100644 --- a/json5/lib.py +++ b/json5/lib.py @@ -372,7 +372,7 @@ def _fp_constant_parser(s): return float(s.replace('Infinity', 'inf').replace('NaN', 'nan')) def _parse_int(s): - if s.lstrip('-').startswith(('0x', '0X')): + if s.lstrip('+-').startswith(('0x', '0X')): return int(s, 16) return int(s) @@ -414,7 +414,7 @@ def _walk_ast( return False ty, v = el if ty == 'number': - unsigned = v[1:] if v.startswith('-') else v + unsigned = v[1:] if v[:1] in ('-', '+') else v if unsigned.startswith(('0x', '0X')): return parse_int(v) if '.' in v or 'e' in v or 'E' in v: diff --git a/json5/parser.py b/json5/parser.py index ab5deb7..dd6275f 100644 --- a/json5/parser.py +++ b/json5/parser.py @@ -1423,7 +1423,7 @@ def _num_literal__c1_(self): [ lambda: self._ch('+'), lambda: self._bind(self._unsigned_lit_, 'n'), - lambda: self._succeed(self._get('n')), + lambda: self._succeed('+' + self._get('n')), ] ) self._pop('num_literal__c1') diff --git a/tests/lib_test.py b/tests/lib_test.py index 161928a..6379510 100644 --- a/tests/lib_test.py +++ b/tests/lib_test.py @@ -324,12 +324,17 @@ def hook(x): json5.loads('-Infinity', parse_constant=hook), '-Infinity' ) self.assertEqual(json5.loads('NaN', parse_constant=hook), 'NaN') + self.assertEqual( + json5.loads('+Infinity', parse_constant=hook), '+Infinity' + ) + self.assertEqual(json5.loads('+NaN', parse_constant=hook), '+NaN') def test_parse_float(self): def hook(x): return x self.assertEqual(json5.loads('1.0', parse_float=hook), '1.0') + self.assertEqual(json5.loads('+1.5', parse_float=hook), '+1.5') for text in ('1E5', '1E+5', '2.5E-3', '1e5', '1e-5'): with self.subTest(text=text): self.assertEqual(json5.loads(text, parse_float=hook), text) @@ -341,8 +346,11 @@ def hook(x): self.assertEqual(json5.loads('1', parse_int=hook), '1') self.assertEqual(json5.loads('0x10', parse_int=hook), '0x10') self.assertEqual(json5.loads('-0xff', parse_int=hook), '-0xff') + self.assertEqual(json5.loads('+5', parse_int=hook), '+5') + self.assertEqual(json5.loads('+0xff', parse_int=hook), '+0xff') self.assertEqual(json5.loads('0x10'), 16) self.assertEqual(json5.loads('-0xff'), -255) + self.assertEqual(json5.loads('+0xff'), 255) self.assertEqual(json5.loads('0X2a'), 42) def test_sample_file(self):