Skip to content

Commit 0fc1b87

Browse files
author
Ben Weaver
committed
Make RFC grammar parser more lenient about quoted items.
1 parent 9bb3057 commit 0fc1b87

File tree

1 file changed

+42
-1
lines changed

1 file changed

+42
-1
lines changed

sasl/rfc.py

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,9 +216,14 @@ class item(Parameterized):
216216
((u'foo', u'baz@mumble.net'), 20)
217217
"""
218218

219+
QUOTES = True
220+
219221
def __init__(self, default='token_or_quoted_string', rules={}):
220222
self.default = default and production(default)
221-
self.grammar = dict((k, production(v)) for (k, v) in rules.iteritems())
223+
self.grammar = dict(
224+
(k, maybe_unquote(production(v)))
225+
for (k, v) in rules.iteritems()
226+
)
222227

223228
def production(self, name):
224229
"""Find the production for a value based on an item's name.
@@ -246,6 +251,7 @@ def write(self, data):
246251
))
247252

248253
class quote(Parameterized):
254+
QUOTES = True
249255

250256
def __init__(self, kind=None):
251257
self.kind = production(kind) if kind else element_list(token, min=1)
@@ -263,6 +269,39 @@ def write(self, data):
263269
dq = double_quote.write(None)
264270
return u'%s%s%s' % (dq, self.kind.write(data), dq)
265271

272+
class MaybeUnquote(Parameterized):
273+
def __init__(self, kind):
274+
self.kind = kind
275+
self.write = kind.write
276+
277+
def read(self, data, pos=0):
278+
if data[pos] != '"':
279+
return self.kind.read(data, pos)
280+
try:
281+
(quoted, new_pos) = require(quoted_string, data, pos)
282+
(value, val_pos) = require(self.kind, quoted, 0)
283+
if val_pos == len(quoted):
284+
return (value, new_pos)
285+
return (None, pos)
286+
except BadToken:
287+
return (None, pos)
288+
289+
def write(self, data):
290+
return self.kind.write(data)
291+
292+
def maybe_unquote(prod):
293+
"""
294+
>>> int = maybe_unquote(integer)
295+
>>> int.read('123')
296+
(123, 3)
297+
>>> int.read("123")
298+
(123, 3)
299+
>>> int.read("foo")
300+
(None, 0)
301+
"""
302+
prod = production(prod)
303+
return prod if getattr(prod, 'QUOTES', False) else MaybeUnquote(prod)
304+
266305

267306
### Simple Productions
268307

@@ -279,6 +318,7 @@ class token_or_quoted_string(Production):
279318
u'"frob@mumble.net"'
280319
"""
281320

321+
QUOTES = True
282322
SEPARATOR = re.compile(r'[\(\)<>@,;:\\"/\[\]\?={}\s]')
283323

284324
@classmethod
@@ -305,6 +345,7 @@ class quoted_string(Production):
305345
(None, 0)
306346
"""
307347

348+
QUOTES = True
308349
UNESCAPE = re.compile(r'\\(.)')
309350

310351
@regular(r'"((?:\\.|[^"])+)"')

0 commit comments

Comments
 (0)