Какие языки программирования являются контекстно-свободными?
или, если быть более точным: какие языки программирования определяются контекстно-свободной грамматикой?
из того, что я собираю, C++ не является контекстно-свободным из-за таких вещей, как макросы и шаблоны. Интуиция подсказывает мне, что функциональные языки могут быть свободны от контекста, но у меня нет никаких жестких данных для этого.
Extra rep для кратких примеров : -)
8 ответов
набор синтаксически корректных программ не содержит контекста практически для всех языков.
набор программ, которые компилируются не является контекстно-свободным для почти всех языков. Например, если набор всех программ компиляции C был контекстно свободным, то, пересекаясь с регулярным языком (также известным как регулярное выражение), набор всех программ компиляции C, которые соответствуют
^int main\(void\) { int a+; a+ = a+; return 0; }$
будет контекстно-свободным, но это явно изоморфно языку a^kba^kba^k, известная не быть контекстно-свободной.
какие языки программирования контекстно-свободной? [...]
моя интуиция говорит мне, что функциональные языки могут быть контекстно-свободными [...]
краткая версия: вряд ли есть какие-либо реальные языки программирования, которые свободны от контекста в любом значении этого слова. Является ли язык контекстно-свободным или нет, не имеет ничего общего с его функциональностью. Дело просто в том, насколько сложны языковые правила и особенности для разбора.
вот CFG для важно язык Brainfuck:
Program → Instr Program | ε
Instr → '+' | '-' | '>' | '<' | ',' | '.' | '[' Program ']'
и вот CFG для функциональное Лыжное комбинаторное исчисление:
Program → E
E → 'S' E E E
E → 'K' E E
E → 'I'
E → '(' E ')'
эти CFGs распознают все действительные программы двух языков, потому что они настолько просты.
больше вариант: обычно используются только контекстно-свободные грамматики (CFGs) к примерно укажите синтаксис языка. Нужно различать синтаксически корректных программ и программы, которые компилируются. Чаще всего компиляторы разделяют анализ языка на анализ синтаксис который строит и проверяет общую структуру фрагмента кода и семантический анализ проверки смысл программы.
если под "контекстно-свободным языком" вы подразумеваете "... для которых компилируются все программы", то ответ: вряд ли. Языки, которые соответствуют этому законопроекту, вряд ли имеют какие-либо правила или сложные функции, такие как существование переменных, чувствительность к пробелам, система типов или любая другая контекст: информация определяется в одном месте и полагается в другом.
если, с другой стороны, "контекстно-свободный язык" единственным средством "... для которых все программы проходят синтаксический анализ", ответ a вопрос в том, насколько сложен сам синтаксис. Есть много синтаксических функций, которые трудно или невозможно описать только с помощью CFG. Некоторые из них преодолеваются путем добавления дополнительного состояния к синтаксическим анализаторам для отслеживания счетчиков, таблиц поиска и т. д.
примеры синтаксических функций, которые невозможно выразить с помощью CFG:
-
отступы и пробелы-чувствительные языки, такие как Python и Haskell. Отслеживание произвольно вложенных уровни отступов в основном зависят от контекста и требуют отдельных счетчиков для уровня отступов; как количество пробелов, используемых для каждого уровня, так и количество уровней.
разрешение только фиксированного уровня отступа с использованием фиксированного количества пробелов будет работать путем дублирования грамматики для каждого уровня отступа, но на практике это неудобно.
-
на Проблема Синтаксического Анализа C Typedef говорит, что программы C неоднозначно во время лексического анализа, потому что он не может знать из одной грамматики, является ли что-то регулярным идентификатором или псевдонимом typedef для существующего типа.
пример:
typedef int my_int; my_int x;
в точке с запятой среда типов должна быть обновлена записью для my_int. Но если лексер уже посмотрел вперед на my_int, он будет использовать его как идентификатор, а не имя типа.
макро - и языки на основе шаблонов, такие как Lisp, C++, Template Haskell, Nim и так далее. Поскольку синтаксис изменяется по мере его анализа, одним из решений является превращение синтаксического анализатора в самомодифицирующуюся программу. См. также "с контекстно-свободной++ или контекстная?"
-
часто приоритет оператора и ассоциативность не выражаются непосредственно в CFGs, даже если это *возможно. Например, CFG для небольшой грамматики выражений, где ^ связывается плотнее, чем×, и × связывается туже, чем+, может выглядеть так:
E → E ^ E E → E × E E → E + E E → (E) E → num
это CFG неоднозначные, однако, и часто сопровождается приоритет / ассоциативность таблице говоря, например, что ^ связывается теснее, × связывается теснее, чем+, что ^ является правоассоциативным, а × и + являются левоассоциативными.
приоритет и ассоциативность могут быть закодированы в CFG механическим способом таким образом, что он однозначен и создает только синтаксические деревья, где операторы вести себя корректно. Пример этого для грамматики выше:
E₀ → EA E₁ EA → E₁ + EA EA → ε E₁ → EM E₂ EM → E₂ × EM EM → ε E₂ → E₃ EP EP → ^ E₃ EP E₃ → num E₃ → (E₀)
но неоднозначные CFGs + таблицы приоритета / ассоциативности распространены, потому что они более читабельны и потому что различные типы парсер LR библиотеки генератора могут производить более эффективные Парсеры исключения сдвига/уменьшения конфликтов вместо того, чтобы иметь дело с однозначной, преобразованной грамматикой большего размера.
в теории, все конечные множества строки являются регулярными языками, и поэтому все юридические программы ограниченного размера являются регулярными. Поскольку обычные языки являются подмножеством контекстно-свободных языков, все программы ограниченного размера контекстно-свободны. Спор продолжается:--7-->
хотя можно утверждать, что было бы приемлемым ограничением для языка разрешать только программы менее миллиона строк, нецелесообразно описывать язык программирования как обычный язык: описание было бы слишком большой.
- Торбен Morgensen это Основы проектирования компиляторов, гл. 2.10.2
то же самое касается CFGs. Чтобы ответить на ваш под-вопрос немного по-другому,
какие языки программирования определена контекстно-свободной грамматикой?
большинство реальных языков программирования определяются их реализациями, и большинство синтаксических анализаторов для реальных языков программирования либо написаны от руки или использует генератор синтаксического анализатора, который расширяет контекстный анализ. К сожалению, не так часто можно найти точный CFG для вашего любимого языка. Когда вы это делаете, это обычно в форма Backus-Naur (BNF) или спецификация синтаксического анализатора, которая, скорее всего, не является чисто контекстной.
примеры грамматических спецификаций из дикой природы:
в зависимости от того, как вы понимаете вопрос, ответ меняется. Но IMNSHO, правильный ответ заключается в том, что все современные языки программирования на самом деле чувствительны к контексту. Например, нет контекстной свободной грамматики,которая принимает только синтаксически правильные программы C. Люди, которые указывают на контекстные грамматики yacc / bison для C, упускают точку.
чтобы пойти на самый драматический пример грамматики без контекста, грамматика перла, как я понимаю,turing-complete.
Если я понимаю ваш вопрос, вы ищете языки программирования, которые могут быть описаны контекстными свободными грамматиками (cfg), так что cfg генерирует все допустимые программы и только допустимые программы.
Я считаю, что большинство (если не все) современных языков программирования поэтому не контекстно свободны. Например, если у вас есть определенные пользователем типы (очень распространенные в современных языках), Вы автоматически учитываете контекст.
есть разница между проверкой синтаксис и проверка семантической корректности программы. Проверка синтаксиса свободна от контекста, тогда как проверка семантической корректности-нет (опять же, в большинстве языков).
Это, однако, не означает, что такой язык не может существовать. Нетипизированный лямбда-исчисление, например, можно описать с помощью контекстной свободной грамматики и, конечно же, Тьюринга.
большинство современных языков программирования не являются контекстно-свободными языками. В качестве доказательства, если я углубляюсь в корень CFL, его соответствующая машина PDA не может обрабатывать сопоставления строк, такие как {ww | w is a string}
. Так что большинство языков программирования требуют этого.
пример:
int fa; // w
fa=1; // ww as parser treat it like this