Примеры языка без контекста на языке C?

Каковы примеры неконтекстно-свободных языков в языке C? Как следующий не-CFL существует на языке C?

а) L1 = {wcw|w равно {a,b}*}

b) L2 = {a^n b^m c^n d^m| n,m >=1}


person akshaykumar6    schedule 22.10.2012    source источник
comment
C на 99% состоит из CFG, но мне нужен пример из того 1%, который не является CFG.   -  person akshaykumar6    schedule 22.10.2012


Ответы (2)


Вопрос коряво сформулирован, поэтому читаю между строк, вот. Тем не менее, это распространенный вопрос о домашнем задании/учебе.

Различные двусмысленности [1] в грамматике C в обычном представлении не делают язык неконтекстно-свободным. (На самом деле, они даже не делают грамматики неконтекстно-свободными.) Общее правило «если это выглядит как объявление, то это объявление независимо от других возможных синтаксических анализов», вероятно, может быть кодифицировано в очень сложной контекстно-свободной грамматике. (хотя не на 100% очевидно, что это правда, поскольку CFG не замкнуты при пересечении или различии), но проще анализировать с помощью более простой CFG, а затем устранять неоднозначность в соответствии с правилом объявления.

Важным моментом в отношении C (и большинства языков программирования) является то, что синтаксис языка немного сложнее, чем BNF, используемый для пояснительных целей. Например, программа на C не будет корректной, если переменная используется без определения. Это синтаксическая ошибка, но анализатор CFG ее не обнаруживает. Грамматические конструкции, необходимые для определения этих случаев, довольно сложны из-за сложного синтаксиса языка, но они сводятся к требованию, чтобы идентификаторы появлялись дважды в допустимой программе. Следовательно, L1 = {wcw|w is {a,b}+} (здесь w — это идентификатор, а c слишком сложно, чтобы его можно было расшифровать). На практике проверка этого требования обычно выполняется с помощью таблицы символов, а правила формального языка, хотя и точны, не написаны в логическом формализме. Поскольку L1 не является контекстно-свободным языком, формализм не может быть контекстно-свободным, но контекстно-зависимая грамматика может распознавать L1, так что это не совсем невозможно. (См., например, Алгол 68.)

Таблица символов также используется для принятия решения о том, следует ли сократить конкретное identifier до typedef-name [2]. Это необходимо для устранения ряда неясностей в грамматике. (Это также дополнительно ограничивает набор строк в языке, потому что в некоторых случаях identifier должно быть разрешено как typedef-name, чтобы программа была корректной.)

Для другого типа контекстной зависимости вызовы функций должны совпадать с объявлениями функций по количеству аргументов; такого рода требования моделируются L2 = {a^n b^m c^n d^m| n,m >=1}, где a и c представляют определение и использование некоторой функции, а b и d представляют определение и использование другой функции. (Опять же, в очень упрощенной форме.)

Это второе требование, возможно, менее явно является синтаксическим требованием. Другие языки (например, Python) допускают вызовы функций с любым количеством аргументов и обнаруживают совпадение количества аргументов/параметров как семантическую ошибку, обнаруживаемую только во время выполнения. Однако в случае C несоответствие явно является синтаксической ошибкой.

Короче говоря, набор грамматически допустимых строк, составляющих язык C, является правильным подмножеством набора строк, распознаваемых CFG, представленным в определении языка C; набор допустимых синтаксических анализов является правильным подмножеством набора производных, сгенерированных CFG, а сам язык (а) однозначен и (б) не является контекстно-свободным.

Примечание 1: Большинство из них на самом деле не являются двусмысленностями, потому что они зависят от того, как разрешается данное identifier (имя typedef, идентификатор функции, объявленная переменная,...).

Примечание 2: Это не тот случай, когда identifier нужно разрешать как typedef-name, если это так; это происходит только в тех местах, где возможно сокращение. Использование одного и того же идентификатора как для типа, так и для переменной, даже в одной и той же области видимости, не является синтаксической ошибкой. (Это не очень хорошая идея, но допустимая.) В следующем примере, адаптированном из примера из раздела 6.7.8 стандарта, показано использование t как имени поля, так и определения типа:

typedef signed int t;
struct tag {
    unsigned t:4;  // field named 't' of type unsigned int
    const t:5;     // unnamed field of type 't' (signed int)
};
person rici    schedule 23.10.2012
comment
Поэтому было бы правильно сказать, что так называемая грамматика C, формально представленная в стандарте, является CFG (поскольку все продукты являются контекстно-свободными BNF), хотя и неоднозначными. Тогда это разделы ограничений (возможно, плюс различные другие правила), которые используют английский язык для определения подмножества, отличного от CFG, которое является фактическим языком C? - person Steve Jessop; 23.10.2012
comment
@SteveJessop: я бы согласился. Не все ограничения находятся в разделах ограничений; например, 6.5.1(2): Идентификатор является первичным выражением при условии, что он был объявлен как обозначающий объект (в этом случае это lvalue) или функцию (в этом случае это указатель функции) в раздел семантики, хотя в сопроводительном примечании 91 четко указано, что необъявленный идентификатор является нарушением синтаксиса. Препроцессор вносит некоторые дополнительные сложности. - person rici; 23.10.2012

Эти вещи не являются контекстно-свободными в C:

foo * bar; // foo multiplied by bar or declaration of bar pointing to foo?
foo(*bar); // foo called with *bar as param or declaration of bar pointing to foo?
foo bar[2] // is bar an array of foo or a pointer to foo?
foo (bar baz) // is foo a function or a pointer to a function?
person Alexey Frunze    schedule 22.10.2012
comment
Ok! Спасибо. Любой пример для данных языков? ? - person akshaykumar6; 22.10.2012
comment
Каковы данные языки? Я думаю, что, возможно, неправильно понял вопрос. Можете ли вы уточнить это? И какое это имеет отношение к Си? - person Alexey Frunze; 22.10.2012
comment
Я имею в виду примеры, которые относятся к не-CFL L1 или L2 в C? - person akshaykumar6; 22.10.2012
comment
Разве это не примеры двусмысленности, а не демонстрация того, что язык не является контекстно-свободным? - person Andy Hayden; 22.10.2012
comment
@developer Можете ли вы привести более наглядный пример того, что вы ищете? - person Alexey Frunze; 22.10.2012
comment
@hayden Это не неоднозначно в контексте C. Они неоднозначны вне контекста. Итак, похоже, это демонстрирует, что C не является контекстно-свободным. - person Alexey Frunze; 22.10.2012
comment
Мне нужны выражения, которые принадлежат этим языкам, не относящимся к CFL (L1 и L2). Одним из примеров, который я думаю о языке L1, является + = a, но я не уверен в этом. Нет представления о L2. - person akshaykumar6; 22.10.2012
comment
@AlexeyFrunze: грамматика является контекстно-свободной, даже если она неоднозначна, а язык является контекстно-свободным, если существует контекстно-свободная грамматика, которая точно выводит набор всех строк в языке. Контекстная чувствительность C демонстрируется не неоднозначностями, а непринятыми строками. Я пытаюсь объяснить это в своем ответе. - person rici; 23.10.2012