Регулярное выражение 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
Другие вопросы по тегам