нужен ли более декларативный способ выражения регулярных выражений?:) - PullRequest
13 голосов
/ 09 августа 2010

Я пытаюсь создать функцию Python, которая может взять простое английское описание регулярного выражения и вернуть регулярное выражение вызывающей стороне.

В настоящее время я думаю об описании в формате YAML.Таким образом, мы можем сохранить описание как необработанную строковую переменную, которая передается этой другой функции, а выходные данные этой функции затем передаются в модуль 're'.Ниже приведен довольно упрощенный пример:

# a(b|c)d+e*
re1 = """
- literal: 'a'
- one_of: 'b,c'
- one_or_more_of: 'd'
- zero_or_more_of: 'e'
"""
myre = re.compile(getRegex(re1))
myre.search(...)

и т. Д.

Кто-нибудь думает, что что-то подобное можно было бы использовать более широко?Знаете ли вы уже существующие пакеты, которые могут это сделать?Какие ограничения вы видите для этого подхода?Кто-нибудь думает, что наличие декларативной строки в коде сделает ее более понятной?

Ответы [ 4 ]

6 голосов
/ 09 августа 2010

Пожалуйста, посмотрите на pyparsing . Многие из проблем, которые вы описываете с помощью RE, вдохновили меня на написание этого пакета.

Вот некоторые особенности pyparsing из главы электронной книги O'Reilly «Что такого особенного в pyparsing?» .

6 голосов
/ 09 августа 2010

Это на самом деле очень похоже (идентично?) На то, как работает лексер / парсер. Если бы у вас была определенная грамматика, то вы могли бы написать парсер без особых проблем. Например, вы можете написать что-то вроде этого:

<expression> :: == <rule> | <rule> <expression> | <rule> " followed by " <expression>
<rule>       :: == <val> | <qty> <val>
<qty>        :: == "literal" | "one" | "one of" | "one or more of" | "zero or more of"
<val>        :: == "a" | "b" | "c" | "d" | ... | "Z" | 

Это далеко не идеальное описание. Для получения дополнительной информации взгляните на этот BNF языка регулярных выражений . Затем вы можете посмотреть на lexing и синтаксический анализ выражения.

Если бы вы сделали это таким образом, вы, вероятно, могли бы немного приблизиться к Естественный язык / Английские версии регулярных выражений.


Я вижу, что подобный инструмент полезен, но, как было сказано ранее, в основном для начинающих. Основное ограничение этого подхода заключается в количестве кода, который вы должны написать, чтобы перевести язык в регулярные выражения (и / или наоборот). С другой стороны, я думаю, что инструмент двустороннего перевода был бы более идеальным и имел бы большую пользу. Возможность найти регулярное выражение и перевести его на английский может быть гораздо полезнее для выявления ошибок.

Конечно, это не займет много времени, чтобы подобрать регулярное выражение, так как синтаксис обычно краткий, и большинство значений довольно понятны, по крайней мере, если вы используете | или || как OR на вашем языке, и вы считаете * умножением на 0-N, + добавлением 0-N.

Хотя иногда я не возражал бы печатать «найди одну или несколько« a », за которыми следуют три цифры или« b », затем« c »»

2 голосов
/ 09 августа 2010

Для разработчиков, пытающихся написать регулярные выражения, которые легко найти и поддерживать, мне интересно, предложит ли такой подход что-то, что re.VERBOSE уже не предоставляет.

Для начинающих ваша идея может иметькакое-то обращение.Однако, прежде чем идти по этому пути, вы можете попытаться смоделировать, как будет выглядеть ваш декларативный синтаксис для более сложных регулярных выражений, с использованием групп захвата, якорей, предварительных утверждений и так далее.Одна из проблем заключается в том, что вы можете получить декларативный синтаксис, который так же сложно запомнить, как и сам язык регулярных выражений.

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

from refunc import *

pattern = Compile(
    'a',
    Capture(
        Choices('b', 'c'),
        N_of( 'd', 1, Infin() ),
        N_of( 'e', 0, Infin() ),
    ),
    Look_ahead('foo'),
)

Но когда я вижу это в действии, это кажется мне болью.Существует много аспектов регулярного выражения, которые достаточно интуитивны - например, + означает «один или несколько».Одним из вариантов был бы гибридный подход, позволяющий вашему пользователю смешивать те части регулярного выражения, которые уже просты, с функциями для более эзотерических битов.

pattern = Compile(
    'a',
    Capture(
        '[bc]',
        'd+',
        'e*',
    ),
    Look_ahead('foo'),
)

Я бы добавил, что по моему опыту регулярные выраженияизучение мыслительного процесса.Освоение синтаксиса - самая простая часть.

2 голосов
/ 09 августа 2010

может быть не совсем то, что вы просите, но есть способ, как написать регулярные выражения более читабельным способом (VERBOSE, коротко X флаг):

rex_name = re.compile("""
    [A-Za-z]    # first letter
    [a-z]+      # the rest
""", re.X)

rex_name.match('Joe')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...