регулярное выражение ply lexmatch имеет группы, отличные от обычных re

Я использую ply и заметил странное несоответствие между повторным соответствием токена, хранящимся в t.lex.lexmatch, по сравнению с sre_pattern, определенным обычным образом с помощью модуля re. Группа (x), кажется, отличается на 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, как я и ожидал.

Кто-нибудь знает, почему существует это несоответствие?


person murftown    schedule 17.09.2011    source источник


Ответы (2)


В версии 3.4 PLY причина этого связана с тем, как выражения преобразуются из строк документации в шаблоны.

Глядя на источник действительно помогает - строка 746 lex.py:

c = re.compile("(?P<%s>%s)" % (fname,f.__doc__), re.VERBOSE | self.reflags)

Я бы не рекомендовал полагаться на что-то подобное между версиями — это всего лишь часть волшебства того, как работает PLY.

person Andrew Walker    schedule 22.09.2011

мне кажется, что соответствующая группа зависит от положения функции токена в файле, например, если бы группы были фактически кумулятивными через все объявленные регулярные выражения токенов:

   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
person lolo    schedule 04.01.2018