Регулярное выражение ply lexmatch имеет группы, отличные от обычных
Я использую ply и заметил странное несоответствие между соответствием токена, хранящимся в t.lex.lexmatch, по сравнению с sre_pattern, определенным обычным способом с модулем re. Группа (х), кажется, отключена на 1.
Я определил простой лексер, чтобы проиллюстрировать поведение, которое я вижу:
import ply.lex as lex
tokens = ('CHAR',)
def t_CHAR(t):
r'.'
t.value = t.lexer.lexmatch
return t
l = lex.lex()
(Я получаю предупреждение о t_error, но пока игнорирую его.) Теперь я передаю некоторые данные в лексер и получаю токен:
l.input('hello')
l.token()
Я получаю LexToken(CHAR,<_sre.SRE_Match object at 0x100fb1eb8>,1,0)
, Я хочу посмотреть объект соответствия:
m = _.value
Итак, теперь я смотрю на группы:
m.group()
=> 'h'
как я и ожидал.
m.group(0)
=> 'h'
как я и ожидал.
m.group(1)
=> 'h'
, но я бы ожидал, что такой группы не будет.
Сравните это с созданием такого регулярного выражения вручную:
import re
p = re.compile(r'.')
m2 = p.match('hello')
Это дает разные группы:
m2.group()
знак равно 'h'
как я и ожидал.
m2.group(0)
знак равно 'h'
как я и ожидал.
m2.group(1)
дает IndexError: no such group
как я и ожидал.
Кто-нибудь знает, почему существует это несоответствие?
2 ответа
В версии 3.4 PLY причина, по которой это происходит, связана с тем, как выражения преобразуются из строк документации в шаблоны.
Поиск источника действительно помогает - строка 746 файла lex.py:
c = re.compile("(?P<%s>%s)" % (fname,f.__doc__), re.VERBOSE | self.reflags)
Я не рекомендовал бы полагаться на что-то подобное между версиями - это лишь часть волшебства того, как работает PLY.
Мне кажется, что совпадающая группа зависит от положения функции токена в файле, например, если группы фактически накапливались через все объявленные регулярные выражения токенов:
t_MYTOKEN1(t):
r'matchit(\w+)'
t.value = lexer.lexmatch.group(1)
return t
t_MYTOKEN2(t):
r'matchit(\w+)'
t.value = lexer.lexmatch.group(2)
return t