Контекстная чувствительность против неоднозначности

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

Я считаю правильным:

Двусмысленность:

Неоднозначная грамматика приводит к построению более одного дерева синтаксического анализа с использованием либо левого, либо правого вывода. Язык, в котором все возможные грамматики неоднозначны, является неоднозначным языком.

Например, C ++ - неоднозначный язык, потому что x * y всегда может означать две разные вещи, как обсуждается в: Почему нельзя проанализировать C ++ с помощью парсера LR (1)?.

Контекстная чувствительность:

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


Теперь меня беспокоят утверждения, которые более или менее говорят о том, что контекстно-зависимые парсеры могут анализировать неоднозначности, такие как x * y. Например, в вышеупомянутом связанном вопросе утверждается, что «... синтаксический анализатор, который [украшает синтаксическое дерево при его создании] не является контекстно-зависимым, а LR-анализаторы (чистые) контекстно-свободными». На мой взгляд, это означает, что контекстно-зависимые парсеры (в отличие от контекстно-свободных парсеров?) Могут это делать. Другой пример: Является ли какая-либо часть синтаксиса C ++ зависимой от контекста? где на этот вопрос ответят «Да ...». То же самое и здесь: что такое неоднозначная контекстно-свободная грамматика?

Я не понимаю, какое отношение эта неоднозначность C ++ имеет к контекстной чувствительности. Я не думаю, что существует контекстно-зависимая грамматика, способная справиться с этой двусмысленностью. Например, если вы возьмете вымышленное правило типа Typedef, ‹other› *, PointerDeclaration -> Ident "*" Ident

тогда вы все равно не сможете определить (с помощью чистого синтаксического анализа), использовался ли конкретный первый Ident (например, "x") во время Typedef (например, typedef double x;).


Возможно ли, что термин «контекстная чувствительность» используется в связанных вопросах, хотя означает что-то простое, например зависимость от контекста (например, требуется больше информации, чем предоставляется простым синтаксическим анализатором). Или есть какая-то связь между "реальной" контекстной зависимостью "и двусмысленностями.

Изменить. Более конкретный вопрос: есть ли какие-либо двусмысленности в контекстно-свободных грамматиках, с которыми можно справиться с помощью контекстно-зависимых грамматик. Этот вопрос возникает у меня, потому что в связанных вопросах это звучит так, как будто двусмысленность C ++ иногда упоминается как проблема контекстной чувствительности.

Edit2 Дополнительная информация: книга Компьютерные системы утверждает на странице 346, что такие требования, как наличие одинакового количества фактических и формальных параметров, могут быть выражены контекстно-зависимыми грамматиками. Но это очень громоздко, потому что вам понадобится множество сложных правил. Но, возможно, это могло также относиться к неоднозначности C ++, упомянутой ранее. Так что у нас есть такие правила, как

«Typedef double x», ‹other› *, PointerDeclaration -> «x» «*» Идентификатор

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


person user764754    schedule 22.05.2011    source источник
comment
Мне нравится этот вопрос, но я жду, когда придет какой-нибудь ТАК неудачник и закричит на вас за то, что это не связано с программированием.   -  person San Jacinto    schedule 22.05.2011
comment
@San: Это связано с программированием. Хотя, вероятно, это не связано с процессом разработки. И называть людей неудачниками из-за того, что они придерживаются политики веб-сайта, немного натянуто; пожалуйста, не используйте на этом сайте личные эпитеты.   -  person Lightness Races in Orbit    schedule 22.05.2011
comment
@tomalak Позвольте мне быть честным с вами; Моя первая склонность - сбить вас с толку, но вы правы. Однако моя жалоба или личный эпитет в большей степени касается все более разочаровывающего состояния, в которое впадает SO, когда вопросы, относящиеся к повседневным задачам программирования, часто передаются программистам или суперпользователю просто потому, что толпа здесь не видит такой же полезности в вопрос.   -  person San Jacinto    schedule 23.05.2011
comment
@SanJacinto: Тогда было бы более уместно использовать meta. :)   -  person Lightness Races in Orbit    schedule 24.05.2011


Ответы (3)


Контекстная чувствительность и неоднозначность полностью ортогональны. Существуют неоднозначные контекстно-свободные языки и однозначные контекстно-зависимые языки.

Контекстно-зависимый язык - это формальный язык, который можно анализировать с помощью контекстно-зависимой грамматики (CSG). Каждый контекстно-свободный язык также является контекстно-зависимым языком, поскольку контекстно-зависимые грамматики - это упрощенные контекстно-зависимые языки. Однако не каждый формальный язык зависит от контекста; есть языки, которые не может описать даже CSG.

person Fred Foo    schedule 22.05.2011
comment
Этот ответ можно улучшить с помощью примеров (даже ссылок на примеры). В его нынешнем виде он просто подтверждает утверждения OP. - person OJFord; 26.01.2015
comment
Утверждать, что они даже не коррелируют, сомнительно после того, как мы заметили, что двусмысленность разрешается контекстом, я думаю, что вам нужно предоставить больше оснований для своего утверждения. Сказать they are orthogonal - это слишком слабо. Более того, мы наблюдаем все наши неоднозначности в контекстно-свободных языках и думаем о контекстно-зависимых языках как о менее двусмысленных. Утверждать, что существуют неоднозначные контекстно-свободные языки, вообще не имеет смысла. Итак, все противоречит вашему утверждению об ортогональности. - person Valentin Tihomirov; 26.12.2015
comment
Основные факты из теории синтаксического анализа о том, что контекстно-свободный - частный случай контекстно-зависимого, когда вы тратите 2/3 своего ответа, ничего не дает. Я знаю это уже 2 десятилетия. Как это помогло мне избежать обмана, в который попадает OP? Я считаю, что точно так же, как OP, этот контекст избавляет вас от многих неясностей, которые у вас есть в контекстно-свободных грамматиках. В чем заключается тот факт, что контекстно-свободная информация - это подмножество контекстно-зависимых изменений в этом обмане? - person Valentin Tihomirov; 26.12.2015

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

Пример первый: XML-подобный язык, допускающий любое имя тега. Поскольку контекстно-свободная грамматика не может анализировать предложение ww, состоящее из двух повторяющихся слов w = {a, b} +, она не может анализировать <ID></ID>, где идентификаторы также равны. Таким образом, определяется неконтекстная грамматика, которая принимает надмножество:

start -> elem
elem  -> open elem* close
open  -> '<' ID '>'
close -> '</' ID '>'
ID    -> ('a' / 'b')+

Это, очевидно, анализирует даже те предложения, которые вам не нужны, поэтому необходимо выполнить дополнительную проверку эквивалентных идентификаторов в open и close.

Пример второй: C-подобный Typedef на очень простом языке. Представьте себе язык, который содержит только typedef, указатели и умножения. У него всего два идентификатора: a и b. Пример такого языка:

typedef a;
b * a;                    // multiplication
a * b;                    // b is pointer to type a 

Грамматика, не зависящая от контекста, будет выглядеть так:

start                     -> typedef multiplication-or-pointer+
typedef                   -> 'typedef' ID ';'
multiplication-or-pointer -> ID '*' ID ';'
ID                        -> 'a'
ID                        -> 'b'

Грамматика не принимает надмножество, но не знает, видит ли он умножение или указатель, поэтому это неоднозначно. И поэтому нужно просмотреть результат и решить, умножение это или указатель, в зависимости от того, какой тип определен в typedef.

С контекстно-зависимой грамматикой можно сделать гораздо больше. Очень приблизительно (и неточно):

start                                     -> typedef multiplication-or-pointer+
typedef                                   -> 'typedef' ID ';'
multiplication-or-pointer                 -> pointer / multiplication
'typedef' 'a' ';' WHATEVER pointer        -> 'a' '*' ID   
'typedef' 'b' ';' WHATEVER pointer        -> 'b' '*' ID   
'typedef' 'b' ';' WHATEVER multiplication -> 'a' '*' ID
'typedef' 'a' ';' WHATEVER multiplication -> 'b' '*' ID
ID                                        -> 'a'
ID                                        -> 'b'

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

Что касается вашего Edit 1: я надеюсь, что предыдущий пример отвечает на это.

Относительно вашего Edit 2: Есть еще одна уловка, как выразить это, чтобы правила не были так ограничены, но они обычно умопомрачительны, и IMO это причина, по которой никто не использует формализм CSG.

NB: контекстно-зависимая грамматика эквивалентна линейному ограниченному автомату, контекстно-свободная грамматика эквивалентна автомату выталкивания вниз. Неверно утверждать, что контекстно-свободный синтаксический анализатор является противоположностью контекстно-зависимого синтаксического анализатора.

person jk_    schedule 10.06.2014

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

person Community    schedule 22.05.2011