Это может быть проще с tokenize - адаптировать пример в документации,
import cStringIO
import tokenize
class Lookahead(object):
def __init__(self, s):
self._t = tokenize.generate_tokens(cStringIO.StringIO(s).readline)
self.lookahead = next(self._t, None)
def __iter__(self):
return self
def next(self):
result = self.lookahead
if result is None: raise StopIteration
self.lookahead = next(self._t, None)
return result
def doit(s):
toks = Lookahead(s)
result = []
for toktype, tokvalue, _, _, _ in toks:
if toktype == tokenize.STRING:
pk = toks.lookahead
if pk is not None and pk[0] == tokenize.OP and pk[1] == '%':
result.extend([
(tokenize.NAME, 'functioncall'),
(tokenize.OP, '('),
(tokenize.STRING, repr(tokvalue)),
(tokenize.OP, ')')
])
continue
result.append((toktype, tokvalue))
return tokenize.untokenize(result)
print doit('"some literal string %" % SOMETHING')
Печатается functioncall ('"some literal string %"')%SOMETHING
. Интервал довольно странный (требуется гораздо больше усилий, чтобы получить интервал в самый раз, но это еще хуже для восстановления источников из модифицированного AST), но это просто отлично, если все, что вы собираетесь делать, это импортировать/запустить (не так хорошо, если вы хотите получить хорошо читаемый и редактируемый код), но это довольно большая проблема, что я бы предложил отдельный Q ;-).
Возможно, вам удастся использовать инструмент 2to3, который предназначен для преобразования источника в источник. –