В информатике, неоднозначная грамматика - это контекстно-свободная грамматика, для которой существует строка, которая может иметь больше чем одно крайнее левое производное или дерево синтаксического анализа, а однозначная грамматика - это контекстно-свободная грамматика, для которой каждая допустимая строка имеет уникальное самое левое дерево производного или синтаксического анализа. Многие языки допускают как неоднозначные, так и однозначные грамматики, в то время как некоторые языки допускают только неоднозначные грамматики. Любой непустой язык допускает неоднозначную грамматику, беря однозначную грамматику и вводя повторяющееся правило или синоним (единственный язык без неоднозначных грамматик - это пустой язык). Язык, допускающий только неоднозначные грамматики, называется неоднозначным по своей сути языком, и существуют по своей сути неоднозначные контекстно-свободные языки. Детерминированные контекстно-свободные грамматики всегда однозначны и являются важным подклассом однозначных грамматик; однако существуют недетерминированные однозначные грамматики.
Для компьютерных языков программирования справочная грамматика часто бывает неоднозначной из-за таких проблем, как проблема dangling else. Если они присутствуют, эти неоднозначности обычно разрешаются путем добавления правил приоритета или других контекстно-зависимых правил синтаксического анализа, поэтому общая грамматика фраз является однозначной. Некоторые алгоритмы синтаксического анализа (например, (Earley или GLR parsers) могут генерировать наборы синтаксических деревьев (или "синтаксических лесов") из строк, которые синтаксически неоднозначны.
Самый простой пример: неоднозначная грамматика для тривиального языка, которая состоит только из пустой строки:
… означает, что продукция может быть либо самим собой, либо пустой строкой. Таким образом, пустая строка имеет самые левые производные от длина 1, 2, 3 и даже любой длины, в зависимости от того, сколько раз используется правило A → A.
Этот язык также имеет однозначную грамматику, состоящую из одного элемента Правило действия :
… означает, что уникальная продукция может создавать только пустую строку, которая является уникальной строкой в языке.
Таким же образом любую грамматику непустого языка можно сделать неоднозначной, добавив дубликаты.
регулярный язык унарных строк заданного символа, например 'a'
(регулярное выражение a *
), имеет однозначную грамматику:
… но также имеет неоднозначную грамматику:
Они соответствуют созданию правоассоциативного дерева (для однозначной грамматики) или разрешению как левой, так и правой ассоциации. Это подробно описано ниже.
контекстно-свободная грамматика
неоднозначно, поскольку есть два крайних левых вывода для строки a + a + a:
A | → A + A | A | → A + A | ||
→ a + A | → A + A + A (Первый A заменяется на A + A. Замена второго A приведет к аналогичному выводу) | ||||
→ a + A + A | → a + A + A | ||||
→ a + a + A | → a + a + A | ||||
→ a + a + a | → a + a + a |
В качестве другого примера грамматика неоднозначна, поскольку существует два дерева синтаксического анализа для строка a + a - a:
Язык, который она генерирует, однако, не является неоднозначным по своей сути; следующая однозначная грамматика порождает тот же язык:
Распространенным примером неоднозначности в языках программирования является проблема dangling else. Во многих языках else
в операторе If – then (–else) является необязательным, что приводит к появлению нескольких способов распознавания с точки зрения контекстно-свободной грамматики.
Конкретно, на многих языках можно писать условные выражения в двух допустимых формах: форма if-then и форма if-then-else - фактически, делая предложение else необязательным:
В грамматике, содержащей правила
оператор → if Condition then Statement | if Condition then Statement else Statement |... Условие →...
могут возникать неоднозначные структуры фраз. Выражение
ifa, затем ifb, затем s else s2
может быть проанализировано как
ifa, затемbegin ifb затем s endelse s2
или как
ifa затемbegin ifb затем s else s2 end
в зависимости от того, связан ли else
с первым if
или вторым if
.
. Это разрешается по-разному на разных языках. Иногда грамматика модифицируется, чтобы сделать ее недвусмысленной, например, требуя выражение endif
или делая else
обязательным. В других случаях грамматика остается неоднозначной, но неоднозначность разрешается путем создания общей грамматики фразы контекстно-зависимой, например, путем связывания else
с ближайшим if
. В последнем случае грамматика недвусмысленна, но контекстно-свободная грамматика неоднозначна.
Существование нескольких производных одной и той же строки недостаточно, чтобы указать что грамматика неоднозначна; только несколько крайних левых производных (или, что то же самое, несколько деревьев синтаксического анализа) указывают на неоднозначность.
Например, простая грамматика
S → A + A A → 0 | 1
- однозначная грамматика для языка {0 + 0, 0 + 1, 1 + 0, 1 + 1}. В то время как каждая из этих четырех строк имеет только одну самую левую производную, у нее есть два разных производных, например
S ⇒ A + A ⇒ 0 + A ⇒ 0 + 0
и
S ⇒ A + A ⇒ A + 0 ⇒ 0 + 0
Только первый вывод является крайним левым.
Проблема принятия решения о том, является ли произвольная грамматика неоднозначной, является неразрешимой, потому что можно показать, что она эквивалентна Проблема с почтовой корреспонденцией. По крайней мере, есть инструменты, реализующие некоторую процедуру полурешения для обнаружения неоднозначности контекстно-свободных грамматик.
Эффективность контекстно-свободного синтаксического анализа грамматик определяется автоматом, который его принимает. Детерминированные контекстно-свободные грамматики принимаются детерминированными выталкивающими автоматами и могут анализироваться за линейное время, например, парсером LR. Это подмножество контекстно-свободных грамматик, которые принимаются автоматом выталкивания и могут быть проанализированы за полиномиальное время, например, с помощью алгоритма CYK. Однозначные контекстно-свободные грамматики могут быть недетерминированными.
Например, язык четных длин палиндромов на алфавите 0 и 1 имеет однозначную контекстно-свободную грамматику S → 0S0 | 1S1 | ε. Произвольная строка этого языка не может быть проанализирована, не прочитав сначала все ее буквы, что означает, что выталкивающий автомат должен пробовать альтернативные переходы между состояниями, чтобы приспособиться к различной возможной длине частично проанализированной строки. Тем не менее, устранение грамматической двусмысленности может привести к детерминированной контекстно-свободной грамматике и, таким образом, обеспечить более эффективный синтаксический анализ. Генераторы компиляторов, такие как YACC включает функции для разрешения некоторых видов неоднозначности, например, с помощью ограничений приоритета и ассоциативности.
Существование по своей сути неоднозначных языков было доказано теоремой Париха в 1961 году Рохитом Парихом в исследовательском отчете MIT.
Хотя некоторые контекстно-свободные языки (набор строк, которые могут быть сгенерированы грамматикой) имеют как неоднозначную, так и однозначную грамматику, существуют контекстно-свободные языки, для которых не может существовать однозначная контекстно-свободная грамматика. Примером по своей сути неоднозначного языка является объединение с . Этот набор контекстно-свободный, так как объединение двух контекстно-свободных языков всегда контекстно-независимое. Но Hopcroft Ullman (1979) приводят доказательство того, что нет способа однозначно анализировать строки в (неконтекстно-независимом) общем подмножестве .