Вы можете попробовать воспользоваться автоматом. Получив автомат для исходного языка, мы строим его для циклического сдвига. Новый автомат работает в два этапа, соответствующих y и x части слова yx (где xy на языке оригинала). На первом этапе, всякий раз, когда автомат хочет выдвинуть нетерминал A , он может вместо этого нажать нетерминал A′ ; идея состоит в том, что в конце первого этапа стек будет содержать в обратном порядке символы, которые находятся в стеке после чтения xоригинальным автоматом. На втором этапе (переключатель недетерминирован), вместо нажатия на нетерминал A , нам разрешено выталкивать нетерминал A′ . Если оригинальный автомат действительно может сгенерировать стек после чтения x , то новый сможет точно вытолкнуть весь стек.
Изменить: вот еще несколько деталей. Предположим, нам дан КПК с алфавитом , набором состояний Q , набором принимающих состояний F , нетерминалами Γ , начальным состоянием q 0 и набором допустимых переходов. Каждый допустимый переход имеет вид ( q , a , A , q ′ , α ) , что означает, что в состоянии q при чтении a ∈ A (или a = ϵ , в этом случае это свободный переход), если верх стека A ∈ΣQFΓq0(q,a,A,q′,α)qa∈Aa=ϵ (или A = ϵ , что означает, что стек пуст), тогда КПК может (это недетерминированная модель) перейти в состояние q ′ , заменив A на α ∈ Γ ∗ .A∈ΓA=ϵq′Aα∈Γ∗
Новый КПК имеет новый нетерминал для каждого A ∈ Γ . Для каждых двух состояний q , q ′ ∈ Q и A ∈ Γ ∪ { ϵ } существуют два состояния ( q , q ′ , 1 ) , ( q , q ′ , 2 , A ) . Исходные состояния (выбирается фактическое начальное состояние недетерминированно среди них с помощью ε - переходов) , являются (A′A∈Γq,q′∈QA∈Γ∪{ϵ}(q,q′,1),(q,q′,2,A)ϵ(q,q,1)(q,a,A,q′,α)( ( q , q ″ , 2 , B ) , a , A , ( q ′ , q ″ , 2 , Б ) , а )((q,q′′,1),a,A,(q′,q′′,1),α)((q,q′′,2,B),a,A,(q′,q′′,2,B),α)
Для каждого перехода существуют переходы , где и . Для каждого конечного состояния существуют переходы , где .( ( q , q ″ , 1 ) , a , B ′ , ( q ′ , q ″ , 1 ) , B ′ A ′ α ) B ∈ Γ ∪ { ϵ } ε ' = ε д ∈ F ( ( д ,(q,a,A,q′,α)((q,q′′,1),a,B′,(q′,q′′,1),B′A′α)B∈Γ∪{ϵ}ϵ′=ϵq∈FA ∈ Γ ∪ { ϵ }((q,q′′,1),ϵ,A,(q0,q′′,2,ϵ),A)A∈Γ∪{ϵ}
Для каждого перехода существуют переходы , где . Для каждого перехода существуют переходы , где . Для каждого перехода существуют «обобщенные переходы» ; они реализованы в виде последовательности двух переходов через новое промежуточное состояние. Переходы\ alpha) с( ( q , q ″ , 2 , A ) , a , B ′ , ( q ′ , q ″ , 2 , A ) , B ′ α ) A ∈ Γ ∪ { ϵ } ( q , a , ϵ , q ′(q,a,ϵ,q′,α)((q,q′′,2,A),a,B′,(q′,q′′,2,A),B′α)A∈Γ∪{ϵ}( ( q , q ″ , 2 , B ) , a , A ′ , ( q ′ , q ″ , 2 , A ) , ϵ ) B ∈ Γ ∪ { ϵ } ( q , a , A , q ′ , B ) ( ( q , q ″ , 2(q,a,ϵ,q′,A)((q,q′′,2,B),a,A′,(q′,q′′,2,A),ϵ)B∈Γ∪{ϵ}(q,a,A,q′,B)( q , a , ϵ , q ′ , α ) | α | ≥ 2 ( q , a , A , q ′ , A ) ( ( q , q ″ , 2 ,((q,q′′,2,C),a,B′A,(q,q′′,2,C),ϵ)(q,a,ϵ,q′,α)|α|≥2обрабатываются аналогично. Для каждого перехода существуют переходы , где . Переходы обрабатываются аналогично. Наконец, существует единственное конечное состояние и переходы .(q,a,A,q′,A)B ∈ Γ ′ ∪ { ϵ } ( q , a , A , q ′ , A α ) f ( ( q , q , 2 , А ) , ϵ , ϵ , f , ϵ((q,q′′,2,A),a,B,(q′,q′′,2,A),B)B∈Γ′∪{ϵ}(q,a,A,q′,Aα)f((q,q,2,A),ϵ,ϵ,f,ϵ)
(Там может быть несколько переходов, которые я пропустил, и некоторые детали, которые я опускаю, несколько беспорядочные.)
Напомним, мы пытаемся принять слово , где принимается оригинальным КПК. Состояние означает, что мы находимся на этапе 1, в состоянии , а исходный КПК находится в состоянии после чтения . Состояние аналогично, где соответствует последнему который был вытолкнут. На этапе 1, мы имеем право выдвинуть вместо того , чтобы хлопать . Мы делаем это для каждого нетерминала, который создается при обработке , но выталкивается только при обработке . На 2 -й ступени, нам позволено соватьx y ( q , q ′ , 1 ) q q ′ x ( q , q ′ , 2 , A ) A A ′ A ′ A x y A ′ A A ϵ B ′yxxy(q,q′,1)qq′x(q,q′,2,A)AA′A′AxyA′вместо того, чтобы нажимать . Если мы сделаем это, тогда мы должны помнить, что вершина акции действительно ; это применимо только в том случае, если в стеке нет «временных» объектов, которые в моделируемом КПК совпадают с вершинами стека или в форме .AAϵB′
Вот простой пример. Рассмотрим автомат для который толкает для каждого и выдает для каждого . Новый автомат принимает слова двух форм: и . Для слов первой формы, 1 -й ступени состоит из толкая раз«2 -й ступени состоит из выскакивают раз , толкая раз , и выскакивают раз . Для слов второй формы мы сначала нажимаем раз A x A y y k x n y n - k x k y n x n - k k A ′ k A ′ n - k A n - k A k A k A n - k A ′ n - k 'xnynAxAyykxnyn−kxkynxn−kkA′kA′n−kAn−kAkA, затем нажмите раз , нажмите раз , перейдите к этапу 2 и нажмите раз .kAn−kA′n−kA′
Вот более сложный пример для языка сбалансированных скобок различных типов ("()", "[]", "<>"), так что непосредственные потомки каждого типа скобок должны принадлежать к другому типу. Например, «([] <>)» в порядке, но «()» неверно. Для каждого «(», мы помещаем если стек топ-не , для каждого «)», мы выскочить . Аналогично , ассоциируются с «[]» и «<>». Вот как мы принимаем слово ">) ([()] <". Мы потребляем ">)", нажимая и переходя к этапу 2. Мы потребляем "(", выталкиваяи запоминание верхней границы стека . Мы потребляем "[()]", нажимая и щелкая ; при нажатииA A B C C ′ A ′ A ′ A B A B A B A A B ϵ X ′ B A C ′A AABCC′A′A′ABAB , мы знаем, что «реальная» вершина стека - это , и поэтому допускаются квадратные скобки (нас не обманул бы «>) (() <»); при нажатии , поскольку вершина стека - это (который не является или имеет форму ), то мы знаем, что также является «реальной» вершиной стека, и поэтому допускаются круглые скобки (даже если теневая вершина стека ). Наконец, мы потребляем "<" и поп .AABϵX′BAC′
Рассмотрим нормальную форму Грейбаха . Чтобы создать сдвинутый язык, вам нужно всего лишь изменить производство на и добавить новый нетерминальный который ведет себя так же, как раньше, в случае производство ссылки . S → A 1 … A n α S ′ S SS→αA1…An S→A1…Anα S′ S S
источник
Хорошей идеей оказалось проверить старое классическое « Введение в теорию автоматов» Хопкрофта и Уллмана (1979). Закрытие в цикле - это Упражнение 6.4c и помечено S **. Двойные звезды означают, что это одна из самых сложных проблем (в книге). К счастью, S указывает, что это одна из выбранных проблем с решением.
Решение заключается в следующем. Беру CFG в хомском нормальном виде. Рассмотрим любое деривационное дерево и в основном перевернем его. Рассмотрим путь в исходном дереве. На левом дереве есть вклады на правый , то есть строка выводится равных . ( На самом деле , как грамматика CNF , когда путь продолжается влево, вклад будет справа и соответствующий пуст, и т.д.)S=X1,X2,…,Xn x1,x2,…,xn y1,y2,…,yn x1x2…xnyn…y2y1 xi
У дерева вверх ногами есть путь с вкладами слева и справа, поэтому результат является производным для . Как требуется.у п , ... , у 2 у 1 х п , ... , х 2 х 1 у п ... у 2 у 1 х 1 х 2 ... х пS′,X^n,…X^2,X^1 yn,…,y2y1 xn,…,x2x1 yn…y2y1x1x2…xn
Полные детали конструкции приведены в книге.
Обратите внимание, как это напоминает (принятое) решение Ювала. Нетерминалы, которые вставляются, а не выталкиваются, расположены в стеке в обратном порядке. Совершенно похоже на перевернутый на дереве.
источник