В дизайне компилятора, почему левая рекурсия должна быть исключена в грамматике? Я читаю, что это потому, что это может вызвать бесконечную рекурсию, но разве это не так и для правильной рекурсивной грамматики?
20
В дизайне компилятора, почему левая рекурсия должна быть исключена в грамматике? Я читаю, что это потому, что это может вызвать бесконечную рекурсию, но разве это не так и для правильной рекурсивной грамматики?
Ответы:
Левые рекурсивные грамматики не обязательно являются плохой вещью. Эти грамматики легко анализируются с использованием стека, чтобы отслеживать уже проанализированные фразы, как это имеет место в LR-анализаторе .
Напомним, что левое рекурсивное правило CF-грамматики имеет вид:G = ( V, Σ , R , S)
с элементом V и β элементом V ∪ Σ . (См. Полное формальное определение для кортежа ( V , Σ , R , S ) там ).α В β В∪ Е ( V, Σ , R , S)
Всякий раз, когда новый терминал принимается синтаксическим анализатором грамматики (от лексера), этот терминал помещается поверх стека: эта операция называется сдвигом .
Каждый раз, когда правая часть правила сопоставляется группой последовательных элементов в верхней части стека, эта группа заменяется одним элементом, представляющим вновь сопоставляемую фразу. Эта замена называется сокращением .
При правильных рекурсивных грамматиках стек может расти бесконечно, пока не произойдет сокращение, что значительно ограничивает возможности синтаксического анализа. Однако, оставленные рекурсивные позволят компилятору генерировать сокращения раньше (фактически, как можно скорее). Смотрите запись в Википедии для получения дополнительной информации.
источник
Рассмотрим это правило:
Теперь рассмотрим анализатор LL, пытающийся сопоставить несоответствующую строку, как
'b'
это правило. Так'a'
как не совпадает, он будет пытаться соответствоватьexample 'b'
. Но для того, чтобы это сделать, оно должно соответствоватьexample
... что именно оно и пыталось сделать в первую очередь. Он может застрять, пытаясь навсегда увидеть, может ли он соответствовать, потому что он всегда пытается сопоставить один и тот же поток токенов с одним и тем же правилом.Чтобы предотвратить это, вам нужно либо разобрать справа (что довольно редко встречается, насколько я видел, и вместо этого сделать правильную рекурсию), искусственно ограничить количество разрешенных вложений или сопоставить токен до начала рекурсии, так что всегда есть базовый случай (а именно, где все токены были использованы, и до сих пор нет полного совпадения). Поскольку праворекурсивное правило уже выполняет третье, у него нет такой же проблемы.
источник
(Я знаю, что этот вопрос довольно старый, но в случае, если у других людей тот же вопрос ...)
Вы спрашиваете в контексте парсеров рекурсивного спуска? Например, для грамматики
expr:: = expr + term | term
, почему-то вроде этого (оставлено рекурсивным):проблематично, но не это (правильно рекурсивно)?
Похоже, обе версии
expr()
сами себя называют. Но важным отличием является контекст - то есть текущий токен, когда выполняется этот рекурсивный вызов.В левом рекурсивном случае
expr()
постоянно вызывает себя с одним и тем же токеном, и никакого прогресса не происходит. В правильном рекурсивном случае он потребляет часть входных данных в вызовеterm()
и токен PLUS до достижения вызоваexpr()
. Таким образом, в этот момент рекурсивный вызов может вызвать термин и затем завершиться, прежде чем снова достигнет теста if.Например, рассмотрим синтаксический анализ 2 + 3 + 4. Левый рекурсивный синтаксический анализатор вызывает
expr()
бесконечно, когда застрял на первом токене, в то время как правый рекурсивный анализатор потребляет «2 +» передexpr()
повторным вызовом . Второй звонокexpr()
соответствует "3 +" и звонитexpr()
только с 4 слева. 4 соответствует условию, и синтаксический анализ завершается без дополнительных вызововexpr()
.источник
Из руководства Bison:
«Любая последовательность может быть определена с использованием левой или правой рекурсии, но вы всегда должны использовать левую рекурсию , потому что она может анализировать последовательность любого числа элементов с ограниченным пространством стека. Правая рекурсия занимает место в стеке Bison в пропорционально количеству элементов в последовательности, потому что все элементы должны быть сдвинуты в стек, прежде чем правило может быть применено хотя бы один раз. См. Алгоритм синтаксического анализатора Bison, для дальнейшего объяснения этого. "
http://www.gnu.org/software/bison/manual/html_node/Recursion.html
Так что это зависит от алгоритма парсера, но, как указано в других ответах, некоторые парсеры могут просто не работать с левой рекурсией
источник