Permalink
Browse files

Support octal and hex escape sequences in strings.

  • Loading branch information...
1 parent c55a224 commit 68cfaebfad7c72318bd57922185c5d6370637553 @kr committed Apr 1, 2009
Showing with 34 additions and 6 deletions.
  1. +34 −6 reader.py
View
40 reader.py
@@ -200,7 +200,7 @@ def __atom(self, *extra):
if type == T.NAME:
return lx.S(lexeme)
if type == T.STR:
- return lx.String(unescape(lexeme[1:-1])).setpos(pos)
+ return lx.String(unescape(lexeme[1:-1], pos)).setpos(pos)
if type == T.DECF:
return lx.Decimal(lexeme)
if type == T.HEREDOC:
@@ -213,18 +213,46 @@ def match_loop(self, parse, *sentinels):
first = parse()
return cons(first, self.match_loop(parse, *sentinels))
-def unescape(s):
+def report_bad_escape(pos, s, i):
+ ex = ReadError('bad escape sequence %s' % s[i:i + 4])
+ report_compile_error(ex, file=pos[0], line=pos[1], char=pos[2] + 1 + i)
+
+def unescape(s, pos):
i = 0
l = len(s)
r = [ ]
while i < l:
c = s[i]
+ i += 1
if c == '\\':
- i += 1
- c = tab[s[i]]
- # TODO octal and hex escape sequnces
+ if s[i] in '01234567':
+ n = int(s[i])
+ i += 1
+ if i < l and s[i] in '01234567':
+ n = (n << 3) | int(s[i])
+ i += 1
+ if i < l and s[i] in '01234567':
+ n = (n << 3) | int(s[i])
+ i += 1
+
+ c = chr(n)
+ elif s[i] == 'x':
+ i += 1
+ if i >= l: report_bad_escape(pos, s, i - 2)
+ if s[i] not in '0123456789abcdef':
+ report_bad_escape(pos, s, i - 2)
+
+ n = int(s[i], 16)
+ i += 1
+ if i < l and s[i] in '0123456789abcdef':
+ n = (n << 4) | int(s[i], 16)
+ i += 1
+
+ c = chr(n)
+ else:
+ c = tab[s[i]]
+ i += 1
r.append(c)
- i += 1
return ''.join(r)
tab = {

0 comments on commit 68cfaeb

Please sign in to comment.