Для того чтобы язык был программируемым, обязательно ли он основывался на контекстно-свободной грамматике

23

Практически, для языка, который в конечном итоге может быть скомпилирован / преобразован в инструкции системного уровня, необходимо ли, чтобы это была контекстно-свободная грамматика?

пример: все ли языки программирования / написания сценариев являются контекстно-свободными грамматиками? Java основана на CFG, но действительно ли это так, что все языки программирования основаны на CFG?

Это не кажется обязательным, но в моем понимании есть пробелы.

Некоторый контекст для вопроса: я смотрел на спецификацию языка Java, которая также предоставляет правила грамматики . Это заставило меня задуматься над этим вопросом.

sandeepkunkunuru
источник
1
В общем, я думаю, что вы просто хотите, чтобы проблема компиляции была вычислимой, а синтаксический анализ CFG - это легко и просто. Хотя я слышал некоторые утверждения, что, например, распознавание допустимых программ на Perl на самом деле является невычислимой проблемой.
Янне Х. Корхонен
2
на самом деле все, что вам действительно нужно, это синтаксис, разрешимый по Тьюрингу (который есть во всех CFG). Вы также можете сделать язык программирования, синтаксис которого не решаем по Тьюрингу, но когда вы делаете опечатку, компилятор может никогда не остановиться, пока он пытается решить, является ли это допустимым синтаксисом. это не очень полезно
чокнутый урод
@ratchet, вы предполагаете, что синтаксис должен быть рекурсивно перечислимым?
Дэвид Харрис
4
@JanneKorhonen: В частности, Perl не может быть проанализирован статически , то есть он не может быть проанализирован без выполнения; так как указанное выполнение может быть не прекращающимся, статический анализ Perl подразумевал бы решение проблемы остановки.
Джон Пурди
@janne Я имею в виду, что постпроцессинг, который может повлечь за собой проблемы, которые могут или не могут быть вычислимы, это, как правило, тот случай, когда окончательная грамматика, по которой проверяется программа, не зависит от контекста. Чтобы быть более конкретным, после предварительной обработки, для определения правила, которое соответствует последовательности токенов, нам нужно взглянуть на другие токены, окружающие последовательность. Я не знаю, есть ли у меня смысл, извините за это. Я немного смущен на самом деле.
sandeepkunkunuru

Ответы:

20

Два раза нет.

Во-первых, большинство HPL не являются контекстно-свободными. Хотя у них обычно есть синтаксис, основанный на CFG, у них также есть то, что люди называют статической семантикой (которая также часто включается в термин синтаксис). Это может включать имена и типы, которые должны проверить правильность программы. Например,

class A {
  String a = "a";
  int b = a + d;
}

является синтаксически правильной Java-программой, но не будет компилироваться, потому что dне определена и aне имеет подходящего типа.

Во-вторых, вы можете анализировать языки, которые не являются контекстно-свободными (что очевидно доказано существованием компиляторов). Только в том, что CFG могут быть эффективно проанализированы, в то время как CSG не может, в целом. Однако вы можете добавить некоторые неконтекстные функции, оставаясь при этом эффективными.

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

Рафаэль
источник
3
Не забывайте public class Program { public static void main(String[] args) { ... } }... Java не позволит вам так легко уйти. :-)
Рой Тинкер
Технически, этого class A { ... }вполне достаточно, так как javacкомпилирует то, что вы на самом деле не можете выполнить (из-за отсутствия точки входа). Но да.
Рафаэль
20

Разбор perl не решаем.

http://www.jeffreykegler.com/Home/perl-and-undecidability/perl-and-undecidability-files/TPR3.pdf?attredirects=0

http://www.perlmonks.org/?node_id=663393

Найл Мерфи
источник
6
Я чувствую, что это должно быть изюминкой шутки Perl :)
Suresh Venkat
5
Суреш: Я уже сделал эту шутку, хотя она оказалась не очень хорошей шуткой в ​​статье «О негибких языках программирования» в SIGBOVIK 2011 ( sigbovik.org/2011/proceedings.pdf - стр. 79-). 82).
Роб Симмонс
1
Примечание: интерпретатор Perl еще не является недетерминированным, если это кому-то утешительно :)
Рой Тинкер
15

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

Точнее, кажется, что существует гомоморфизм из языка блоков Python вида

если условие:
     линия 1
     line2
     line3
еще:
     строка4

0N10N10N

Дэвид Эппштейн
источник
4
Строго говоря, вы правы, но в контексте языков программирования мы пытаемся освободить контекст от языка, получающегося после этапа предварительной обработки, называемого токенизацией . Я думаю, что отступ проверяется до этого.
Диего де Эстрада
7
Да, у лексера Python (токенизатор) есть стек глубины отступа; поток токенов имеет символ INDENT в начале каждого блока и символ DEDENT в конце, который может быть проанализирован без контекста (INDENT и DEDENT действуют так же, как фигурные скобки в C). C имеет проблему «не могу сказать, если объявление или выражение»: является foo * bar;ли объявление fooуказателем barили умножением fooвремени bar?
Макс
8
Хорошо, конечно, но тогда вы просто прячете ту же сложность в лексере, а не превращаете его в датчик конечного состояния, как это часто бывает.
Дэвид Эппштейн
1
@DavidEppstein: Честно говоря, сложность не очень велика.
Джон Пурди
1
Помимо обработки INDENT / DEDENT в лексере, Python имеет очень простую грамматику LL (1).
rmmh
13

Бодо Манти и Мартин Беме показывают, что каждый компилятор C ++ обязательно завершен по Тьюрингу, то есть он может вычислять любую частично рекурсивную функцию во время компиляции . Так что это намного хуже, чем просто контекстно-зависимый.

http://wwwhome.math.utwente.nl/~mantheyb/journals/BotEATCS_BoehmeManthey_CompilingCPP.pdf

Маркус Блезер
источник
Да, но компилятор никогда не бывает просто контекстно-свободной грамматикой. Вы должны обсудить саму грамматику, а не компилятор.
Джефф Берджес
@Jeff: «Время компиляции» в моем ответе означает «проверка правильности заданного исходного кода C +». Из небольшого изменения конструкции в статье следует, что вы можете свести каждый разрешимый язык к набору всех правильных программ на C ++.
Маркус Блезер
7

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

int myfun(int a) { ... }
int myfun(int a, int b) { ... }
int myfun(int a, int b, int c, ...) { ... }
...
int I_m_I_cfg = myfun(1,2);
...

Я сделал небольшой поиск в Google и обнаружил эту статью: « Булева грамматика для простого булева языка » А. Охотина (2004); по его словам, реальная проблема заключается в том, чтобы найти язык программирования, который полностью описывается формальной грамматикой:

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

Раздел «Введение» статьи является коротким, но очень понятным.

Марцио де Биаси
источник
6

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

Языки, основанные на отступах, не являются, естественно, свободными от контекста, как сказал Дэвид, но они становятся контекстно-свободными по отношению к параметризованному токену отступа.

Haskell позволяет изменять приоритет операторов с помощью infix и infixl. Модуль строгой прагмы в Perl реализован с использованием лексических настроек $ ^ H и% ^ H, которые делают его неконтекстным, возможно, и другие настройки.

Существуют языки расширения макросов, такие как TeX, в которых синтаксический анализ afaik не имеет смысла без выполнения.

Вероятно, есть даже две контекстно-свободные грамматики, пересечение которых не является контекстно-свободным, но все же описывает машину Тьюринга.

Ява и ассемблер, вероятно, оба не зависят от контекста.

Джефф Берджес
источник
2
Разве двусмысленность (a)-bСи не делает контекстно-зависимой? ( aможет быть переменной или typedef - некоторые другие языки по этой причине не позволяют
приводить
Я прошу прощения за очень задержанный комментарий, но устройство Даффа не содержит никаких синтаксических отклонений. Брекеты сбалансированы правильно. Функция C чаще всего игнорируется в дискуссиях о том, является ли C контекстно-свободным препроцессором. Я скептически отношусь к тому, что существует какая-то неформальная интерпретация «не зависящей от контекста», которая позволяет использовать его для описания языка с макропроцессором, даже с хорошим поведением. И препроцессор C совсем не хорош.
Ричи
4

Нет, и многие практические языки не являются контекстно-свободными. Например, грамматики C ++ нет, потому что в некоторых контекстах разрешение грамматики зависит от ввода информации, которая не является контекстно-свободной.

antti.huima
источник
4

Сначала позвольте мне провести различие между синтаксисом языка программирования и самим языком.

Синтаксис многих языков (по крайней мере, основан на) контекстно-свободной грамматике (CFG), потому что они хорошо изучены, и есть алгоритмы, которые могут эффективно анализировать CFG, и крайний случай, который не может быть решен CFG, может быть обработан специально

Однако многие языки фактически не являются контекстно-свободными (когда используются символы объявления перед использованием, например, в Java, C (++), D).

Интересный факт: у D есть полная функция времени компиляции по Тьюрингу и расширение шаблона, что делает сам язык не-разрешимым по Тьюрингу. Однако создатель языка сделал все возможное, чтобы сделать синтаксис CFG.

чокнутый урод
источник
Анализ имен и типов обычно выполняет по своей сути неконтекстные задачи.
Рафаэль
Шаблонное метапрограммирование на C ++ завершено по Тьюрингу.
Джефф Берджес
3

Что касается "Все ли языки программирования / написания сценариев являются контекстно-свободными грамматиками?" часть обеспокоена, ответ однозначный

В отношении основного вопроса «для языка, который в конечном итоге может быть скомпилирован / преобразован в инструкции системного уровня», я не знаю, почему это обязательно должен быть CFG. Тем не менее, могут быть лучшие объяснения.

Kris
источник
1
Крис, не могли бы вы привести несколько примеров неконтекстных языков программирования, не основанных на грамматике. Я имею в виду, пост-предварительная обработка, которая может повлечь за собой проблемы, которые могут или не могут быть вычислимы, окончательная грамматика, по которой программа проверяется.
sandeepkunkunuru
3

Язык программирования должен основываться на некотором грамматическом формализме, примером которого является CFG. В то время как CFGs являются наиболее распространенными (и это обычно преподается на курсах по компиляции в университетах), существуют и другие формализмы, такие как грамматики синтаксического анализа, о которых вы можете прочитать больше здесь (pdf) или в Википедии для более читаемого размера.

evilcandybag
источник