Введение

Принцип наибольшего совпадения при разборе
В компьютерном программировании и информатике принцип "максимального захвата" или "наибольшего совпадения" заключается в том, что при создании какой-либо конструкции следует потреблять как можно большую часть доступного ввода. Первое известное использование этого термина встречается в докторской диссертации Р. Г. Г. Кэттелла, посвященной автоматическому построению генераторов кода для компиляторов.

Применение

Например, лексический синтаксис многих языков программирования требует, чтобы токены формировались из максимально возможного числа символов из входного потока. Это делается для разрешения проблемы внутренней неоднозначности в часто используемых регулярных выражениях, таких как [a-z]+ (одна или более строчных букв). Этот термин также используется в компиляторах на этапе выбора инструкций для описания метода "разбиения на блоки" – определения того, как структурированное дерево, представляющее программу на промежуточном языке, должно быть преобразовано в линейный машинный код. Целое поддерево может быть преобразовано всего в одну машинную инструкцию, и задача состоит в том, чтобы разделить дерево на неперекрывающиеся "блоки", каждый из которых представляет одну машинную инструкцию. Эффективная стратегия заключается в создании блока из максимально возможного поддерева в любой данной точке, что называется "жадным разбивлением" (или "максимальным захватом").

Недостатки

В некоторых ситуациях принцип "максимального захвата" приводит к нежелательным или неинтуитивным результатам. Например, в языке программирования C, выражение x=y/*z; (без пробелов) скорее всего вызовет синтаксическую ошибку, поскольку последовательность /* (непреднамеренно) инициирует комментарий, который либо не завершается, либо завершается конечным токеном */ некоторого последующего, не связанного комментария (комментарии в C не могут быть вложенными). Фактически, в этом выражении предполагалось присвоить переменной x результат деления значения y на значение, полученное при разыменовании указателя z; это был бы допустимый код. Это можно выразить, используя пробелы или x=y/(*z);. Другой пример, в C++, использует символы угловых скобок < и > в синтаксисе специализации шаблонов, но два последовательных символа > интерпретируются как оператор побитового сдвига вправо >>. До C++11 следующий код приводил бы к ошибке разбора, поскольку вместо двух токенов угловых скобок обнаруживался бы токен оператора сдвига вправо:

std::vector<std::vector<int>> my mat 11; //Неверно в C++03, верно в C++11. std::vector<std::vector<int> > my mat 03; //Верно как в C++03, так и в C++11. Стандарт C++11, принятый в августе 2011 года, изменил грамматику таким образом, что токен сдвига вправо был признан синонимом пары угловых скобок (как в Java), что усложняет грамматику, но позволяет продолжать использовать принцип максимального захвата. Исключение из правила максимального захвата в любом случае пришлось добавить для обработки последовательности <::, которая может встречаться в шаблонах. В этом случае, если за последовательностью не следует : или >, символ < интерпретируется как отдельный токен, а не как часть токена <:.

Альтернативы

Исследователи языков программирования также отреагировали, заменив или дополнив принцип максимального захвата другими тактиками лексической дезагигиации. Один из подходов — использовать "ограничения следования", которые вместо прямого выбора самого длинного соответствия накладывают ограничения на то, какие символы могут следовать за допустимым соответствием. Например, требование, чтобы строки, соответствующие [a-z]+, не могли быть за которыми следуют алфавитные символы, достигает того же эффекта, что и принцип максимального захвата с этим регулярным выражением. (В контексте регулярных выражений принцип максимального захвата называют жадностью и противопоставляют ему нежадность.) Другой подход заключается в сохранении принципа максимального захвата, но подчинении его другому принципу, например, контексту (например, токен сдвига вправо в Java не будет распознан в контексте обобщенного выражения, где он синтаксически недопустим).