Ни один из примеров в вопросе не является контекстно-свободным, поэтому, строго говоря, их нельзя анализировать с помощью контекстно-свободных грамматик. Но с практической точки зрения их довольно легко разобрать.
Алгоритм Python хорошо описан в справочном руководстве Python (хотя вам нужно читать это в контексте.) То, что описано там, представляет собой этап предварительной обработки, на котором пробелы в начале строки систематически заменяются токенами INDENT
и DEDENT
.
Уточняю: на самом деле это не этап предварительной обработки, и важно отметить, что он происходит после неявного и явного соединения строк. (В справочном руководстве есть предыдущие разделы, в которых описываются эти процедуры.) В частности, строки неявно соединяются внутри круглых и фигурных скобок, поэтому процесс переплетается с разбором.
С практической точки зрения, и алгоритмы соединения строк, и алгоритмы отступов могут быть реализованы программно; как правило, это делается внутри пользовательского сканера (токенизатора), который поддерживает как стек скобок, так и уровни отступов. Затем поток токенов можно анализировать с помощью обычных контекстно-свободных алгоритмов, но токенизатору — хотя он может использовать регулярные выражения — нужна контекстно-зависимая логика (например, подсчет пробелов). [Примечание 1]
Точно так же форматы, которые содержат явные размеры (например, большинство форматов сериализации, включая файлы PNG, протобуфы Google и кодирование по частям HTTP), не являются контекстно-свободными, но, очевидно, легко токенизировать, поскольку токенизатор просто должен прочитать длину, а затем прочитать столько байтов.
Существует множество контекстно-зависимых формализмов, и они определенно имеют свое применение, но при практическом анализе наиболее распространенной стратегией является использование формализма, эквивалентного Тьюрингу (например, любого языка программирования, возможно, дополненного сканером-генератором, таким как flex
) для токенизатора и контекстно-свободный формализм для синтаксического анализатора. [Заметка 2]
Примечания:
Может быть не сразу очевидно, что отступы Python не являются контекстно-свободными, поскольку контекстно-свободные грамматики могут принимать некоторые категории соглашений. Например, {ωω-1 | ω∈Σ*}
(язык всех палиндромов четной длины) не зависит от контекста, как и {anbn}
.
Однако эти примеры не могут быть расширены, потому что единственно возможное соглашение о подсчете в контекстно-свободном языке — это заключение в скобки. Таким образом, в то время как палиндромы являются контекстно-свободными (вы можете реализовать проверку с помощью одного стека), внешне очень похожий {ωω | ω∈Σ*}
не является таковым, как и {anbncn}
.
Одним из таких формализмов являются обратные ссылки в «регулярных» выражениях, которые могут быть доступны в некоторых реализациях PEG. Обратные ссылки позволяют выражать множество контекстно-зависимых языков, но не позволяют выражать все контекстно-свободные языки. К сожалению, регулярные выражения с обратными ссылками на практике действительно отстой, потому что проблема определения того, соответствует ли строка регулярному выражению с обратными ссылками, является NP-полной. Вы можете найти этот вопрос на родственный сайт SE интересен. (И вы можете переформулировать свой вопрос так, чтобы его можно было задать на этом сайте http://cs.stackexchange.com. )
person
rici
schedule
18.09.2014