регулярное выражение ply lexmatch имеет группы, отличные от обычных - PullRequest
6 голосов
/ 17 сентября 2011

Я использую 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, как я ожидаю.

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

Ответы [ 2 ]

5 голосов
/ 22 сентября 2011

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

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

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

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

1 голос
/ 04 января 2018

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

   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
...