Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions json5/json5.g
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,13 @@ string = squote sqchar*:cs squote -> join('', cs)
sqchar = bslash esc_char:c -> c
| bslash eol -> ''
| ~bslash ~squote ~eol anything:c -> c
| '\u2028' | '\u2029'
| ~?(_strict) '\x00'..'\x1f'

dqchar = bslash esc_char:c -> c
| bslash eol -> ''
| ~bslash ~dquote ~eol anything:c -> c
| '\u2028' | '\u2029'
| ~?( _strict ) '\x00'..'\x1f'

bslash = '\u005C'
Expand Down
24 changes: 20 additions & 4 deletions json5/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,8 @@ def _sqchar_(self):
self._sqchar__c1_,
self._sqchar__c2_,
self._sqchar__c3_,
self._sqchar__c4_,
self._sqchar__c5_,
]
)

Expand Down Expand Up @@ -511,14 +513,20 @@ def _sqchar__c2_(self):
self._pop('sqchar__c2')

def _sqchar__c3_(self):
self._ch('\u2028')

def _sqchar__c4_(self):
self._ch('\u2029')

def _sqchar__c5_(self):
self._seq(
[
lambda: self._not(self._sqchar__c3__s0_n_),
lambda: self._not(self._sqchar__c5__s0_n_),
lambda: self._range('\x00', '\x1f'),
]
)

def _sqchar__c3__s0_n_(self):
def _sqchar__c5__s0_n_(self):
v = self._get('_strict')
if v:
self._succeed(v)
Expand All @@ -532,6 +540,8 @@ def _dqchar_(self):
self._dqchar__c1_,
self._dqchar__c2_,
self._dqchar__c3_,
self._dqchar__c4_,
self._dqchar__c5_,
]
)

Expand Down Expand Up @@ -563,14 +573,20 @@ def _dqchar__c2_(self):
self._pop('dqchar__c2')

def _dqchar__c3_(self):
self._ch('\u2028')

def _dqchar__c4_(self):
self._ch('\u2029')

def _dqchar__c5_(self):
self._seq(
[
lambda: self._not(self._dqchar__c3__s0_n_),
lambda: self._not(self._dqchar__c5__s0_n_),
lambda: self._range('\x00', '\x1f'),
]
)

def _dqchar__c3__s0_n_(self):
def _dqchar__c5__s0_n_(self):
v = self._get('_strict')
if v:
self._succeed(v)
Expand Down
6 changes: 6 additions & 0 deletions tests/lib_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,9 +325,15 @@ def test_strings(self):
self.check('"foo\\\nbar"', 'foobar')
self.check("'foo\\\nbar'", 'foobar')

# U+2028 and U+2029 are allowed unescaped, as in JSON.
self.check('"foo
bar
"', 'foo
bar
')
self.check("'foo
bar
'", 'foo
bar
')
self.check('"foo\\
bar"', 'foobar')

# unterminated string literals.
self.check_fail('"\n')
self.check_fail("'\n")
self.check_fail('"\r"')

# bad hex literals
self.check_fail("'\\x0'")
Expand Down
Loading