<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Xottab</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Xottab"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/Xottab"/>
		<updated>2026-06-11T17:50:41Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=ORM._%D0%9A%D0%BB%D1%8E%D1%87%D0%B8_%D0%B8_%D1%81%D1%81%D1%8B%D0%BB%D0%BA%D0%B8&amp;diff=51177</id>
		<title>ORM. Ключи и ссылки</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=ORM._%D0%9A%D0%BB%D1%8E%D1%87%D0%B8_%D0%B8_%D1%81%D1%81%D1%8B%D0%BB%D0%BA%D0%B8&amp;diff=51177"/>
				<updated>2016-01-14T14:57:11Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: Новая страница: «&amp;lt;div style=&amp;quot;background-color: #ABCDEF; font-size: 16px; font-weight: bold; color: #000000; text-align: center; padding: 4px; border-style: solid; border-width: 1p...»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div style=&amp;quot;background-color: #ABCDEF; font-size: 16px; font-weight: bold; color: #000000; text-align: center; padding: 4px; border-style: solid; border-width: 1px;&amp;quot;&amp;gt;Эта статья находится в разработке!&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;includeonly&amp;gt;[[Категория: В разработке]]&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49470</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49470"/>
				<updated>2015-09-20T13:27:20Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: /* Алгоритм */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, при котором SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим состояние $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с ситуацией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях (англ. ''items'') больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
&lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' ситуации, а число $1$ в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$, и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх: либо $\gamma=\delta\alpha$, либо $a$ является первым символом $w$, либо$w=\varepsilon$ и $a=\char36$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\varepsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества наборов ситуаций $items$ для грамматики &lt;br /&gt;
$\Gamma' =\langle\Sigma, N, S, P\rangle$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] closure('''item'''[] $I$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[] $J$ = $I$   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in \Gamma'.P$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      $J$.add($[B\rightarrow\cdot\gamma,b]$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until not''' changed&lt;br /&gt;
      '''return''' $J$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] goto('''item'''[] $I$, '''char''' $X$):&lt;br /&gt;
      '''item'''[] $J=\varnothing$&lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          $J$.add($[A\rightarrow\alpha X\cdot\beta, a]$)&lt;br /&gt;
      '''return''' $closure(J)$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[][] items($\Gamma'$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[][] $C$&lt;br /&gt;
      $C$.add($closure(\{[S'\rightarrow\cdot S,\char36]\})\$)&lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' '''item'''[] $I\subset C$&lt;br /&gt;
              '''for''' $X \in \Gamma'.\Sigma$&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ '''and''' $goto(I,X)\not\subset C$&lt;br /&gt;
                      $C$.add($goto(I,X)$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until not''' changed&lt;br /&gt;
      '''return''' $C$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $\Gamma'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC\mid d$&lt;br /&gt;
Запустим процедуру $items(\Gamma')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\varepsilon;B=S;\beta=\varepsilon;a=\char36$.&lt;br /&gt;
&lt;br /&gt;
Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $[C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$ и $[C\rightarrow\cdot d, d]$. &lt;br /&gt;
Поскольку ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure()$ завершает свою работу.&lt;br /&gt;
&lt;br /&gt;
Начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и переходы между ними]]&lt;br /&gt;
*$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items()$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $\Gamma'$:&lt;br /&gt;
&lt;br /&gt;
#При $X=S$:&lt;br /&gt;
#:$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
#:Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом,  &lt;br /&gt;
#:*$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
#При $X=C$:&lt;br /&gt;
#:$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
#:*$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
#При $X=c$:&lt;br /&gt;
#:$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
#:*$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
#При $X=d$:&lt;br /&gt;
#:$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
#:*$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
*$$I_5=goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
:$$I_6=goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
*$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
&lt;br /&gt;
'''NB:''' Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
&lt;br /&gt;
*$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
*$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$: &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
*$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items()$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
В алгоритме будут использоваться структуры, описанные в конспекте про про [[LR(k)-грамматики]]&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;\Gamma'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблица &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; канонического &amp;lt;tex&amp;gt;LR(1)&amp;lt;/tex&amp;gt;-анализа&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1CanonicalTable}(\Gamma'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(\Gamma') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;\Gamma'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(T,&amp;lt;/tex&amp;gt; '''Error'''&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;goto(I_i,a) = I_j&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;T[i,a] = &amp;lt;/tex&amp;gt; '''Shift'''(&amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;T[i,a] = &amp;lt;/tex&amp;gt; '''Reduce'''(&amp;lt;tex&amp;gt;A  \to a&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;T[i,\char36] = &amp;lt;/tex&amp;gt; '''Accept'''&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;goto(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;goto[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $\Gamma$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для этой грамматики:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
! style=&amp;quot;background-color:#EEE;text-align:center&amp;quot;| &lt;br /&gt;
!style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$S$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$C$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$c$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$d$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$\char36$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$0$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px;text-align:center&amp;quot;| '''Accept'''&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$3$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$4$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$6$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$7$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
* [[LR(k)-грамматики]]&lt;br /&gt;
* [[LR(0)-разбор]]&lt;br /&gt;
* [[SLR(1)-разбор]]&lt;br /&gt;
* [[LALR-разбор]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;br /&gt;
* [http://window.edu.ru/resource/974/69974/files/lang_trans.pdf Б.К.Мартыненко. Языки и трансляции. Стр. 198-223]&lt;br /&gt;
* [http://gas-teach.narod.ru/au/tfl/tfl13.pdf Лекции по теории формальных языков, LR(0)-, SLR(1)-, LR(1)- и LALR(1)-анализ ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Методы трансляции]]&lt;br /&gt;
[[Категория: Восходящий разбор]]&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49469</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49469"/>
				<updated>2015-09-20T13:25:04Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: /* Пример */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, при котором SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим состояние $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с ситуацией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях (англ. ''items'') больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
&lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' ситуации, а число $1$ в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$, и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх: либо $\gamma=\delta\alpha$, либо $a$ является первым символом $w$, либо$w=\varepsilon$ и $a=\char36$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\varepsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества наборов ситуаций $items$ для грамматики &lt;br /&gt;
$\Gamma' =\langle\Sigma, N, S, P\rangle$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] closure('''item'''[] $I$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[] $J$ = $I$   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in \Gamma'.P$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      $J$.add($[B\rightarrow\cdot\gamma,b]$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until not''' changed&lt;br /&gt;
      '''return''' $J$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] goto('''item'''[] $I$, '''char''' $X$):&lt;br /&gt;
      '''item'''[] $J=\varnothing$&lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          $J$.add($[A\rightarrow\alpha X\cdot\beta, a]$)&lt;br /&gt;
      '''return''' $closure(J)$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[][] items($\Gamma'$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[][] $C$&lt;br /&gt;
      $C$.add($closure(\{[S'\rightarrow\cdot S,\char36]\})\$)&lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' '''item'''[] $I\subset C$&lt;br /&gt;
              '''for''' $X \in \Gamma'.\Sigma$&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ '''and''' $goto(I,X)\not\subset C$&lt;br /&gt;
                      $C$.add($goto(I,X)$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until not''' changed&lt;br /&gt;
      '''return''' $C$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $\Gamma'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC\mid d$&lt;br /&gt;
Запустим процедуру $items(\Gamma')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\varepsilon;B=S;\beta=\varepsilon;a=\char36$.&lt;br /&gt;
&lt;br /&gt;
Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $[C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$ и $[C\rightarrow\cdot d, d]$. &lt;br /&gt;
Поскольку ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure()$ завершает свою работу.&lt;br /&gt;
&lt;br /&gt;
Начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и переходы между ними]]&lt;br /&gt;
*$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items()$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $\Gamma'$:&lt;br /&gt;
&lt;br /&gt;
#При $X=S$:&lt;br /&gt;
#:$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
#:Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом,  &lt;br /&gt;
#:*$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
#При $X=C$:&lt;br /&gt;
#:$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
#:*$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
#При $X=c$:&lt;br /&gt;
#:$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
#:*$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
#При $X=d$:&lt;br /&gt;
#:$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
#:*$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
*$$I_5=goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
:$$I_6=goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
*$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
&lt;br /&gt;
'''NB:''' Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
&lt;br /&gt;
*$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
*$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$: &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
*$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items()$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
В алгоритме будут использоваться структуры, описанные в конспекте про про [[LR(k)-грамматики]]&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;\Gamma'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблица &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; канонического &amp;lt;tex&amp;gt;LR(1)&amp;lt;/tex&amp;gt;-анализа&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(\Gamma'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(\Gamma') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;\Gamma'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(T,&amp;lt;/tex&amp;gt; '''Error'''&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;goto(I_i,a) = I_j&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;T[i,a] = &amp;lt;/tex&amp;gt; '''Shift'''(&amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;T[i,a] = &amp;lt;/tex&amp;gt; '''Reduce'''(&amp;lt;tex&amp;gt;A  \to a&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;T[i,\char36] = &amp;lt;/tex&amp;gt; '''Accept'''&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;goto(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;goto[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $\Gamma$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для этой грамматики:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
! style=&amp;quot;background-color:#EEE;text-align:center&amp;quot;| &lt;br /&gt;
!style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$S$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$C$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$c$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$d$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$\char36$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$0$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px;text-align:center&amp;quot;| '''Accept'''&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$3$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$4$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$6$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$7$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
* [[LR(k)-грамматики]]&lt;br /&gt;
* [[LR(0)-разбор]]&lt;br /&gt;
* [[SLR(1)-разбор]]&lt;br /&gt;
* [[LALR-разбор]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;br /&gt;
* [http://window.edu.ru/resource/974/69974/files/lang_trans.pdf Б.К.Мартыненко. Языки и трансляции. Стр. 198-223]&lt;br /&gt;
* [http://gas-teach.narod.ru/au/tfl/tfl13.pdf Лекции по теории формальных языков, LR(0)-, SLR(1)-, LR(1)- и LALR(1)-анализ ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Методы трансляции]]&lt;br /&gt;
[[Категория: Восходящий разбор]]&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49468</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49468"/>
				<updated>2015-09-20T13:22:58Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: /* Пример */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, при котором SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим состояние $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с ситуацией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях (англ. ''items'') больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
&lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' ситуации, а число $1$ в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$, и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх: либо $\gamma=\delta\alpha$, либо $a$ является первым символом $w$, либо$w=\varepsilon$ и $a=\char36$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\varepsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества наборов ситуаций $items$ для грамматики &lt;br /&gt;
$\Gamma' =\langle\Sigma, N, S, P\rangle$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] closure('''item'''[] $I$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[] $J$ = $I$   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in \Gamma'.P$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      $J$.add($[B\rightarrow\cdot\gamma,b]$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until not''' changed&lt;br /&gt;
      '''return''' $J$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] goto('''item'''[] $I$, '''char''' $X$):&lt;br /&gt;
      '''item'''[] $J=\varnothing$&lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          $J$.add($[A\rightarrow\alpha X\cdot\beta, a]$)&lt;br /&gt;
      '''return''' $closure(J)$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[][] items($\Gamma'$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[][] $C$&lt;br /&gt;
      $C$.add($closure(\{[S'\rightarrow\cdot S,\char36]\})\$)&lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' '''item'''[] $I\subset C$&lt;br /&gt;
              '''for''' $X \in \Gamma'.\Sigma$&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ '''and''' $goto(I,X)\not\subset C$&lt;br /&gt;
                      $C$.add($goto(I,X)$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until not''' changed&lt;br /&gt;
      '''return''' $C$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $\Gamma'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC\mid d$&lt;br /&gt;
Запустим процедуру $items(\Gamma')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\varepsilon;B=S;\beta=\varepsilon;a=\char36$.&lt;br /&gt;
&lt;br /&gt;
Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $[C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$ и $[C\rightarrow\cdot d, d]$. &lt;br /&gt;
Поскольку ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure()$ завершает свою работу.&lt;br /&gt;
&lt;br /&gt;
Начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и переходы между ними]]&lt;br /&gt;
*$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items()$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $\Gamma'$:&lt;br /&gt;
&lt;br /&gt;
#При $X=S$:&lt;br /&gt;
#:$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
#:Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом,  &lt;br /&gt;
#:*$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
#При $X=C$:&lt;br /&gt;
#:$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
#:*$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
#При $X=c$:&lt;br /&gt;
#:$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
#:*$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
#При $X=d$:&lt;br /&gt;
#:$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
#:*$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
*$$I_5=goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
:$$I_6=goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
*$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
&lt;br /&gt;
'''NB:''' Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
&lt;br /&gt;
*$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
*$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$: &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
*$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items()$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
В алгоритме будут использоваться структуры, описанные в конспекте про про [[LR(k)-грамматики]]&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;\Gamma'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблица &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; канонического &amp;lt;tex&amp;gt;LR(1)&amp;lt;/tex&amp;gt;-анализа&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(\Gamma'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(\Gamma') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;\Gamma'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(T,&amp;lt;/tex&amp;gt; '''Error'''&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;goto(I_i,a) = I_j&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;T[i,a] = &amp;lt;/tex&amp;gt; '''Shift'''(&amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;T[i,a] = &amp;lt;/tex&amp;gt; '''Reduce'''(&amp;lt;tex&amp;gt;A  \to a&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;T[i,\char36] = &amp;lt;/tex&amp;gt; '''Accept'''&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;goto(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;goto[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $\Gamma$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для этой грамматики:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
! style=&amp;quot;background-color:#EEE;text-align:center&amp;quot;| Состояние&lt;br /&gt;
!style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$S$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$C$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$c$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$d$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$\char36$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$0$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px;text-align:center&amp;quot;| '''Accept'''&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$3$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$4$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$6$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$7$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
* [[LR(k)-грамматики]]&lt;br /&gt;
* [[LR(0)-разбор]]&lt;br /&gt;
* [[SLR(1)-разбор]]&lt;br /&gt;
* [[LALR-разбор]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;br /&gt;
* [http://window.edu.ru/resource/974/69974/files/lang_trans.pdf Б.К.Мартыненко. Языки и трансляции. Стр. 198-223]&lt;br /&gt;
* [http://gas-teach.narod.ru/au/tfl/tfl13.pdf Лекции по теории формальных языков, LR(0)-, SLR(1)-, LR(1)- и LALR(1)-анализ ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Методы трансляции]]&lt;br /&gt;
[[Категория: Восходящий разбор]]&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49467</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49467"/>
				<updated>2015-09-20T13:16:47Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: /* Канонические LR(1)-таблицы */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, при котором SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим состояние $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с ситуацией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях (англ. ''items'') больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
&lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' ситуации, а число $1$ в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$, и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх: либо $\gamma=\delta\alpha$, либо $a$ является первым символом $w$, либо$w=\varepsilon$ и $a=\char36$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\varepsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества наборов ситуаций $items$ для грамматики &lt;br /&gt;
$\Gamma' =\langle\Sigma, N, S, P\rangle$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] closure('''item'''[] $I$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[] $J$ = $I$   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in \Gamma'.P$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      $J$.add($[B\rightarrow\cdot\gamma,b]$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until not''' changed&lt;br /&gt;
      '''return''' $J$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] goto('''item'''[] $I$, '''char''' $X$):&lt;br /&gt;
      '''item'''[] $J=\varnothing$&lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          $J$.add($[A\rightarrow\alpha X\cdot\beta, a]$)&lt;br /&gt;
      '''return''' $closure(J)$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[][] items($\Gamma'$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[][] $C$&lt;br /&gt;
      $C$.add($closure(\{[S'\rightarrow\cdot S,\char36]\})\$)&lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' '''item'''[] $I\subset C$&lt;br /&gt;
              '''for''' $X \in \Gamma'.\Sigma$&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ '''and''' $goto(I,X)\not\subset C$&lt;br /&gt;
                      $C$.add($goto(I,X)$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until not''' changed&lt;br /&gt;
      '''return''' $C$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $\Gamma'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC\mid d$&lt;br /&gt;
Запустим процедуру $items(\Gamma')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\varepsilon;B=S;\beta=\varepsilon;a=\char36$.&lt;br /&gt;
&lt;br /&gt;
Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $[C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$ и $[C\rightarrow\cdot d, d]$. &lt;br /&gt;
Поскольку ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure()$ завершает свою работу.&lt;br /&gt;
&lt;br /&gt;
Начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и переходы между ними]]&lt;br /&gt;
*$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items()$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $\Gamma'$:&lt;br /&gt;
&lt;br /&gt;
#При $X=S$:&lt;br /&gt;
#:$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
#:Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом,  &lt;br /&gt;
#:*$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
#При $X=C$:&lt;br /&gt;
#:$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
#:*$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
#При $X=c$:&lt;br /&gt;
#:$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
#:*$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
#При $X=d$:&lt;br /&gt;
#:$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
#:*$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
*$$I_5=goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
:$$I_6=goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
*$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
&lt;br /&gt;
'''NB:''' Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
&lt;br /&gt;
*$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
*$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$: &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
*$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items()$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
В алгоритме будут использоваться структуры, описанные в конспекте про про [[LR(k)-грамматики]]&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;\Gamma'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблица &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; канонического &amp;lt;tex&amp;gt;LR(1)&amp;lt;/tex&amp;gt;-анализа&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(\Gamma'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(\Gamma') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;\Gamma'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(T,&amp;lt;/tex&amp;gt; '''Error'''&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;goto(I_i,a) = I_j&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;T[i,a] = &amp;lt;/tex&amp;gt; '''Shift'''(&amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;T[i,a] = &amp;lt;/tex&amp;gt; '''Reduce'''(&amp;lt;tex&amp;gt;A  \to a&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;T[i,\char36] = &amp;lt;/tex&amp;gt; '''Accept'''&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;goto(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;goto[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $\Gamma$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;left&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot;| Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; |$goto$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$c$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$d$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$\char36$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$S$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$C$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$0$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px;text-align:center&amp;quot;| '''Accept'''&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$3$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$4$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$6$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$7$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
* [[LR(k)-грамматики]]&lt;br /&gt;
* [[LR(0)-разбор]]&lt;br /&gt;
* [[SLR(1)-разбор]]&lt;br /&gt;
* [[LALR-разбор]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;br /&gt;
* [http://window.edu.ru/resource/974/69974/files/lang_trans.pdf Б.К.Мартыненко. Языки и трансляции. Стр. 198-223]&lt;br /&gt;
* [http://gas-teach.narod.ru/au/tfl/tfl13.pdf Лекции по теории формальных языков, LR(0)-, SLR(1)-, LR(1)- и LALR(1)-анализ ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Методы трансляции]]&lt;br /&gt;
[[Категория: Восходящий разбор]]&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49465</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49465"/>
				<updated>2015-09-20T13:13:17Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, при котором SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим состояние $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с ситуацией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях (англ. ''items'') больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
&lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' ситуации, а число $1$ в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$, и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх: либо $\gamma=\delta\alpha$, либо $a$ является первым символом $w$, либо$w=\varepsilon$ и $a=\char36$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\varepsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества наборов ситуаций $items$ для грамматики &lt;br /&gt;
$\Gamma' =\langle\Sigma, N, S, P\rangle$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] closure('''item'''[] $I$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[] $J$ = $I$   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in \Gamma'.P$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      $J$.add($[B\rightarrow\cdot\gamma,b]$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until not''' changed&lt;br /&gt;
      '''return''' $J$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] goto('''item'''[] $I$, '''char''' $X$):&lt;br /&gt;
      '''item'''[] $J=\varnothing$&lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          $J$.add($[A\rightarrow\alpha X\cdot\beta, a]$)&lt;br /&gt;
      '''return''' $closure(J)$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[][] items($\Gamma'$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[][] $C$&lt;br /&gt;
      $C$.add($closure(\{[S'\rightarrow\cdot S,\char36]\})\$)&lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' '''item'''[] $I\subset C$&lt;br /&gt;
              '''for''' $X \in \Gamma'.\Sigma$&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ '''and''' $goto(I,X)\not\subset C$&lt;br /&gt;
                      $C$.add($goto(I,X)$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until not''' changed&lt;br /&gt;
      '''return''' $C$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $\Gamma'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC\mid d$&lt;br /&gt;
Запустим процедуру $items(\Gamma')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\varepsilon;B=S;\beta=\varepsilon;a=\char36$.&lt;br /&gt;
&lt;br /&gt;
Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $[C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$ и $[C\rightarrow\cdot d, d]$. &lt;br /&gt;
Поскольку ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure()$ завершает свою работу.&lt;br /&gt;
&lt;br /&gt;
Начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и переходы между ними]]&lt;br /&gt;
*$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items()$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $\Gamma'$:&lt;br /&gt;
&lt;br /&gt;
#При $X=S$:&lt;br /&gt;
#:$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
#:Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом,  &lt;br /&gt;
#:*$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
#При $X=C$:&lt;br /&gt;
#:$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
#:*$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
#При $X=c$:&lt;br /&gt;
#:$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
#:*$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
#При $X=d$:&lt;br /&gt;
#:$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
#:*$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
*$$I_5=goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
:$$I_6=goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
*$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
&lt;br /&gt;
'''NB:''' Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
&lt;br /&gt;
*$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
*$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$: &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
*$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items()$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
В алгоритме будут использоваться структуры, описанные в конспекте про про [[LR(k)-грамматики]]&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;\Gamma'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблицы &amp;lt;tex&amp;gt;ACTION&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;GOTO&amp;lt;/tex&amp;gt; канонического &amp;lt;tex&amp;gt;LR&amp;lt;/tex&amp;gt;-анализа&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(\Gamma'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(\Gamma') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;\Gamma'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(ACTION,&amp;lt;/tex&amp;gt; '''Error'''&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;GOTO(I_i,a) = I_j&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Shift'''(&amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Reduce'''(&amp;lt;tex&amp;gt;A  \to a&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,\char36] = &amp;lt;/tex&amp;gt; '''Accept'''&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;GOTO(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;GOTO[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;left&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot;| Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; |$GOTO$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$c$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$d$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$\char36$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$S$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$C$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$0$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px;text-align:center&amp;quot;| '''Accept'''&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$3$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$4$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$6$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$7$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
* [[LR(k)-грамматики]]&lt;br /&gt;
* [[LR(0)-разбор]]&lt;br /&gt;
* [[SLR(1)-разбор]]&lt;br /&gt;
* [[LALR-разбор]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;br /&gt;
* [http://window.edu.ru/resource/974/69974/files/lang_trans.pdf Б.К.Мартыненко. Языки и трансляции. Стр. 198-223]&lt;br /&gt;
* [http://gas-teach.narod.ru/au/tfl/tfl13.pdf Лекции по теории формальных языков, LR(0)-, SLR(1)-, LR(1)- и LALR(1)-анализ ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Методы трансляции]]&lt;br /&gt;
[[Категория: Восходящий разбор]]&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49464</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49464"/>
				<updated>2015-09-20T13:06:27Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, при котором SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим состояние $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с ситуацией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях (англ. ''items'') больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
&lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' ситуации, а число $1$ в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$, и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх: либо $\gamma=\delta\alpha$, либо $a$ является первым символом $w$, либо$w=\varepsilon$ и $a=\char36$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\varepsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества наборов ситуаций $items$ для грамматики &lt;br /&gt;
$\Gamma' =\langle\Sigma, N, S, P\rangle$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] closure('''item'''[] $I$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[] $J$ = $I$   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in \Gamma'.P$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      $J$.add($[B\rightarrow\cdot\gamma,b]$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until not''' changed&lt;br /&gt;
      '''return''' $J$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] goto('''item'''[] $I$, '''char''' $X$):&lt;br /&gt;
      '''item'''[] $J=\varnothing$&lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          $J$.add($[A\rightarrow\alpha X\cdot\beta, a]$)&lt;br /&gt;
      '''return''' $closure(J)$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[][] items($\Gamma'$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[][] $C$&lt;br /&gt;
      $C$.add($closure(\{[S'\rightarrow\cdot S,\char36]\})\$)&lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' '''item'''[] $I\subset C$&lt;br /&gt;
              '''for''' $X \in \Gamma'.\Sigma$&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ '''and''' $goto(I,X)\not\subset C$&lt;br /&gt;
                      $C$.add($goto(I,X)$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until not''' changed&lt;br /&gt;
      '''return''' $C$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $\Gamma'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC\mid d$&lt;br /&gt;
Запустим процедуру $items(\Gamma')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\varepsilon;B=S;\beta=\varepsilon;a=\char36$.&lt;br /&gt;
&lt;br /&gt;
Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $[C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$ и $[C\rightarrow\cdot d, d]$. &lt;br /&gt;
Поскольку ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure()$ завершает свою работу.&lt;br /&gt;
&lt;br /&gt;
Начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и переходы между ними]]&lt;br /&gt;
*$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items()$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $\Gamma'$:&lt;br /&gt;
&lt;br /&gt;
#При $X=S$:&lt;br /&gt;
#:$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
#:Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом,  &lt;br /&gt;
#:*$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
#При $X=C$:&lt;br /&gt;
#:$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
#:*$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
#При $X=c$:&lt;br /&gt;
#:$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
#:*$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
#При $X=d$:&lt;br /&gt;
#:$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
#:*$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
*$$I_5=goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
:$$I_6=goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
*$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
&lt;br /&gt;
'''NB:''' Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
&lt;br /&gt;
*$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
*$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$: &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
*$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items()$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
В алгоритме будут использоваться структуры, описанные в конспекте про про [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;\Gamma'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблицы &amp;lt;tex&amp;gt;ACTION&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;GOTO&amp;lt;/tex&amp;gt; канонического &amp;lt;tex&amp;gt;LR&amp;lt;/tex&amp;gt;-анализа&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(\Gamma'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(\Gamma') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;\Gamma'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(ACTION,&amp;lt;/tex&amp;gt; '''Error'''&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;GOTO(I_i,a) = I_j&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Shift'''(&amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Reduce'''(&amp;lt;tex&amp;gt;A  \to a&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,\char36] = &amp;lt;/tex&amp;gt; '''Accept'''&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;GOTO(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;GOTO[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;left&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot;| Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; |$GOTO$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$c$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$d$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$\char36$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$S$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$C$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$0$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px;text-align:center&amp;quot;| '''Accept'''&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$3$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$4$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$6$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$7$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
* [[LR(k)-грамматики]]&lt;br /&gt;
* [[LR(0)-разбор]]&lt;br /&gt;
* [[SLR(1)-разбор]]&lt;br /&gt;
* [[LALR-разбор]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;br /&gt;
* [http://window.edu.ru/resource/974/69974/files/lang_trans.pdf Б.К.Мартыненко. Языки и трансляции. Стр. 198-223]&lt;br /&gt;
* [http://gas-teach.narod.ru/au/tfl/tfl13.pdf Лекции по теории формальных языков, LR(0)-, SLR(1)-, LR(1)- и LALR(1)-анализ ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Методы трансляции]]&lt;br /&gt;
[[Категория: Восходящий разбор]]&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49463</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49463"/>
				<updated>2015-09-20T13:02:52Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, при котором SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим состояние $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с ситуацией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях (англ. ''items'') больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
&lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' ситуации, а число $1$ в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$, и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх: либо $\gamma=\delta\alpha$, либо $a$ является первым символом $w$, либо$w=\varepsilon$ и $a=\char36$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\varepsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества наборов ситуаций $items$ для грамматики &lt;br /&gt;
$\Gamma' =\langle\Sigma, N, S, P\rangle$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] closure('''item'''[] $I$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[] $J$ = $I$   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in \Gamma'.P$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      $J$.add($[B\rightarrow\cdot\gamma,b]$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until not''' changed&lt;br /&gt;
      '''return''' $J$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] goto('''item'''[] $I$, '''char''' $X$):&lt;br /&gt;
      '''item'''[] $J=\varnothing$&lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          $J$.add($[A\rightarrow\alpha X\cdot\beta, a]$)&lt;br /&gt;
      '''return''' $closure(J)$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[][] items($\Gamma'$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[][] $C = \{closure({S'\rightarrow\cdot S,\char36})\}$&lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' '''item'''[] $I\subset C$&lt;br /&gt;
              '''for''' $X \in \Gamma'.\Sigma$&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ '''and''' $goto(I,X)\not\subset C$&lt;br /&gt;
                      $C$.add($goto(I,X)$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until not''' changed&lt;br /&gt;
      '''return''' $C$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $\Gamma'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC\mid d$&lt;br /&gt;
Запустим процедуру $items(\Gamma')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\varepsilon;B=S;\beta=\varepsilon;a=\char36$.&lt;br /&gt;
&lt;br /&gt;
Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $[C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$ и $[C\rightarrow\cdot d, d]$. &lt;br /&gt;
Поскольку ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure()$ завершает свою работу.&lt;br /&gt;
&lt;br /&gt;
Начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и переходы между ними]]&lt;br /&gt;
*$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items()$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $\Gamma'$:&lt;br /&gt;
&lt;br /&gt;
#При $X=S$:&lt;br /&gt;
#:$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
#:Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом,  &lt;br /&gt;
#:*$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
#При $X=C$:&lt;br /&gt;
#:$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
#:*$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
#При $X=c$:&lt;br /&gt;
#:$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
#:*$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
#При $X=d$:&lt;br /&gt;
#:$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
#:*$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
*$$I_5=goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
:$$I_6=goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
*$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
&lt;br /&gt;
'''NB:''' Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
&lt;br /&gt;
*$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
*$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$: &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
*$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items()$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
В алгоритме будут использоваться структуры, описанные в конспекте про про [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;\Gamma'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблицы &amp;lt;tex&amp;gt;ACTION&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;GOTO&amp;lt;/tex&amp;gt; канонического &amp;lt;tex&amp;gt;LR&amp;lt;/tex&amp;gt;-анализа&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(\Gamma'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(\Gamma') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;\Gamma'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(ACTION,&amp;lt;/tex&amp;gt; '''Error'''&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;GOTO(I_i,a) = I_j&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Shift'''(&amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Reduce'''(&amp;lt;tex&amp;gt;A  \to a&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,\char36] = &amp;lt;/tex&amp;gt; '''Accept'''&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;GOTO(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;GOTO[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;left&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot;| Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; |$GOTO$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$c$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$d$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$\char36$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$S$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$C$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$0$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px;text-align:center&amp;quot;| '''Accept'''&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$3$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$4$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$6$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$7$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
* [[LR(k)-грамматики]]&lt;br /&gt;
* [[LR(0)-разбор]]&lt;br /&gt;
* [[SLR(1)-разбор]]&lt;br /&gt;
* [[LALR-разбор]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;br /&gt;
* [http://window.edu.ru/resource/974/69974/files/lang_trans.pdf Б.К.Мартыненко. Языки и трансляции. Стр. 198-223]&lt;br /&gt;
* [http://gas-teach.narod.ru/au/tfl/tfl13.pdf Лекции по теории формальных языков, LR(0)-, SLR(1)-, LR(1)- и LALR(1)-анализ ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Методы трансляции]]&lt;br /&gt;
[[Категория: Восходящий разбор]]&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49462</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49462"/>
				<updated>2015-09-20T13:01:11Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, при котором SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим состояние $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с ситуацией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях (англ. ''items'') больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
&lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' ситуации, а число $1$ в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$, и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх: либо $\gamma=\delta\alpha$, либо $a$ является первым символом $w$, либо$w=\varepsilon$ и $a=\char36$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\varepsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества наборов ситуаций $items$ для грамматики &lt;br /&gt;
$\Gamma' =\langle\Sigma, N, S, P\rangle$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] closure('''item'''[] $I$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[] $J$ = $I$   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in \Gamma'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      $J$.add($[B\rightarrow\cdot\gamma,b]$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until not''' changed&lt;br /&gt;
      '''return''' $J$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] goto('''item'''[] $I$, '''char''' $X$):&lt;br /&gt;
      '''item'''[] $J=\varnothing$&lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          $J$.add($[A\rightarrow\alpha X\cdot\beta, a]$)&lt;br /&gt;
      '''return''' $closure(J)$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[][] items($\Gamma'$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[][] $C = \{closure({S'\rightarrow\cdot S,\char36})\}$&lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' '''item'''[] $I\subset C$&lt;br /&gt;
              '''for''' $X \in \Gamma'.\Sigma$&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ '''and''' $goto(I,X)\not\subset C$&lt;br /&gt;
                      $C$.add($goto(I,X)$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until not''' changed&lt;br /&gt;
      '''return''' $C$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $\Gamma'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC\mid d$&lt;br /&gt;
Запустим процедуру $items(\Gamma')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\varepsilon;B=S;\beta=\varepsilon;a=\char36$.&lt;br /&gt;
&lt;br /&gt;
Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $[C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$ и $[C\rightarrow\cdot d, d]$. &lt;br /&gt;
Поскольку ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure()$ завершает свою работу.&lt;br /&gt;
&lt;br /&gt;
Начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и переходы между ними]]&lt;br /&gt;
*$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items()$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $\Gamma'$:&lt;br /&gt;
&lt;br /&gt;
#При $X=S$:&lt;br /&gt;
#:$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
#:Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом,  &lt;br /&gt;
#:*$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
#При $X=C$:&lt;br /&gt;
#:$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
#:*$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
#При $X=c$:&lt;br /&gt;
#:$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
#:*$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
#При $X=d$:&lt;br /&gt;
#:$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
#:*$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
*$$I_5=goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
:$$I_6=goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
*$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
&lt;br /&gt;
'''NB:''' Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
&lt;br /&gt;
*$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
*$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$: &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
*$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items()$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
В алгоритме будут использоваться структуры, описанные в конспекте про про [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;\Gamma'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблицы &amp;lt;tex&amp;gt;ACTION&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;GOTO&amp;lt;/tex&amp;gt; канонического &amp;lt;tex&amp;gt;LR&amp;lt;/tex&amp;gt;-анализа&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(\Gamma'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(\Gamma') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;\Gamma'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(ACTION,&amp;lt;/tex&amp;gt; '''Error'''&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;GOTO(I_i,a) = I_j&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Shift'''(&amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Reduce'''(&amp;lt;tex&amp;gt;A  \to a&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,\char36] = &amp;lt;/tex&amp;gt; '''Accept'''&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;GOTO(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;GOTO[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;left&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot;| Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; |$GOTO$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$c$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$d$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$\char36$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$S$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$C$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$0$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px;text-align:center&amp;quot;| '''Accept'''&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$3$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$4$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$6$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$7$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
* [[LR(k)-грамматики]]&lt;br /&gt;
* [[LR(0)-разбор]]&lt;br /&gt;
* [[SLR(1)-разбор]]&lt;br /&gt;
* [[LALR-разбор]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;br /&gt;
* [http://window.edu.ru/resource/974/69974/files/lang_trans.pdf Б.К.Мартыненко. Языки и трансляции. Стр. 198-223]&lt;br /&gt;
* [http://gas-teach.narod.ru/au/tfl/tfl13.pdf Лекции по теории формальных языков, LR(0)-, SLR(1)-, LR(1)- и LALR(1)-анализ ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Методы трансляции]]&lt;br /&gt;
[[Категория: Восходящий разбор]]&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49461</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49461"/>
				<updated>2015-09-20T13:00:28Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: /* Пример */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, при котором SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим состояние $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с ситуацией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях (англ. ''items'') больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
&lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' ситуации, а число $1$ в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$, и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх: либо $\gamma=\delta\alpha$, либо $a$ является первым символом $w$, либо$w=\varepsilon$ и $a=\char36$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\varepsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества наборов ситуаций $items$ для грамматики &lt;br /&gt;
$\Gamma' =\langle\Sigma, N, S, P\rangle$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] closure('''item'''[] $I$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[] $J$ = $I$   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in \Gamma'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      $J$.add($[B\rightarrow\cdot\gamma,b]$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until not''' changed&lt;br /&gt;
      '''return''' $J$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] goto('''item'''[] $I$, '''char''' $X$):&lt;br /&gt;
      '''item'''[] $J=\varnothing$&lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          $J$.add($[A\rightarrow\alpha X\cdot\beta, a]$)&lt;br /&gt;
      '''return''' $closure(J)$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[][] items($\Gamma'$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[][] $C = \{closure({S'\rightarrow\cdot S,\char36})\}$&lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' '''item'''[] $I\subset C$&lt;br /&gt;
              '''for''' $X \in \Gamma'.\Sigma$&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ '''and''' $goto(I,X)\not\subset C$&lt;br /&gt;
                      $C$.add($goto(I,X)$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until not''' changed&lt;br /&gt;
      '''return''' $C$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $\Gamma'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC\mid d$&lt;br /&gt;
Запустим процедуру $items(\Gamma')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\varepsilon;B=S;\beta=\varepsilon;a=\char36$.&lt;br /&gt;
&lt;br /&gt;
Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $[C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$ и $[C\rightarrow\cdot d, d]$. &lt;br /&gt;
Поскольку ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure()$ завершает свою работу.&lt;br /&gt;
&lt;br /&gt;
Начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и переходы между ними]]&lt;br /&gt;
*$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items()$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $\Gamma'$:&lt;br /&gt;
&lt;br /&gt;
#При $X=S$:&lt;br /&gt;
#:$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
#:Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом,  &lt;br /&gt;
#:*$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
#При $X=C$:&lt;br /&gt;
#:$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
#:*$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
#При $X=c$:&lt;br /&gt;
#:$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
#:*$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
#При $X=d$:&lt;br /&gt;
#:$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
#:*$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
*$$I_5=goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
:$$I_6=goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
*$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
&lt;br /&gt;
'''NB:''' Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
&lt;br /&gt;
*$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
*$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$: &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
*$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items()$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
В алгоритме будут использоваться структуры, описанные в конспекте про про [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;\Gamma'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблицы &amp;lt;tex&amp;gt;ACTION&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;GOTO&amp;lt;/tex&amp;gt; канонического &amp;lt;tex&amp;gt;LR&amp;lt;/tex&amp;gt;-анализа&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(\Gamma'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(\Gamma') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;\Gamma'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(ACTION,&amp;lt;/tex&amp;gt; '''Error'''&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;GOTO(I_i,a) = I_j&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Shift'''(&amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Reduce'''(&amp;lt;tex&amp;gt;A  \to a&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,\char36] = &amp;lt;/tex&amp;gt; '''Accept'''&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;GOTO(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;GOTO[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;left&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot;| Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; |$GOTO$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$c$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$d$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$\char36$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$S$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$C$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$0$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px;text-align:center&amp;quot;| '''Accept'''&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$3$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$4$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$6$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$7$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
* [[LR(k)-грамматики]]&lt;br /&gt;
* [[LR(0)-разбор]]&lt;br /&gt;
* [[SLR(1)-разбор]]&lt;br /&gt;
* [[LALR-разбор]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;br /&gt;
* [http://window.edu.ru/resource/974/69974/files/lang_trans.pdf Б.К.Мартыненко. Языки и трансляции. Стр. 198-223]&lt;br /&gt;
* [http://gas-teach.narod.ru/au/tfl/tfl13.pdf Лекции по теории формальных языков, LR(0)-, SLR(1)-, LR(1)- и LALR(1)-анализ ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49460</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49460"/>
				<updated>2015-09-20T12:57:20Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, при котором SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим состояние $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с ситуацией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях (англ. ''items'') больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
&lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' ситуации, а число $1$ в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$, и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх: либо $\gamma=\delta\alpha$, либо $a$ является первым символом $w$, либо$w=\varepsilon$ и $a=\char36$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\varepsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества наборов ситуаций $items$ для грамматики &lt;br /&gt;
$\Gamma' =\langle\Sigma, N, S, P\rangle$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] closure('''item'''[] $I$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[] $J$ = $I$   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in \Gamma'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      $J$.add($[B\rightarrow\cdot\gamma,b]$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until not''' changed&lt;br /&gt;
      '''return''' $J$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] goto('''item'''[] $I$, '''char''' $X$):&lt;br /&gt;
      '''item'''[] $J=\varnothing$&lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          $J$.add($[A\rightarrow\alpha X\cdot\beta, a]$)&lt;br /&gt;
      '''return''' $closure(J)$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[][] items($\Gamma'$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[][] $C = \{closure({S'\rightarrow\cdot S,\char36})\}$&lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' '''item'''[] $I\subset C$&lt;br /&gt;
              '''for''' $X \in \Gamma'.\Sigma$&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ '''and''' $goto(I,X)\not\subset C$&lt;br /&gt;
                      $C$.add($goto(I,X)$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until not''' changed&lt;br /&gt;
      '''return''' $C$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $\Gamma'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC\mid d$&lt;br /&gt;
Запустим процедуру $items(\Gamma')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\varepsilon;B=S;\beta=\varepsilon;a=\char36$.&lt;br /&gt;
&lt;br /&gt;
Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $[C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$ и $[C\rightarrow\cdot d, d]$. &lt;br /&gt;
Поскольку ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure()$ завершает свою работу.&lt;br /&gt;
&lt;br /&gt;
Начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и переходы между ними]]&lt;br /&gt;
*$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items()$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $\Gamma'$:&lt;br /&gt;
&lt;br /&gt;
#При $X=S$:&lt;br /&gt;
#:$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
#:Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом,  &lt;br /&gt;
#:*$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
#При $X=C$:&lt;br /&gt;
#:$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
#:*$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
#При $X=c$:&lt;br /&gt;
#:$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
#:*$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
#При $X=d$:&lt;br /&gt;
#:$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
#:*$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
*$$I_5=goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
$$I_6=goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
*$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
&lt;br /&gt;
'''NB:''' Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
&lt;br /&gt;
*$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
*$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$: &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
*$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items()$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
В алгоритме будут использоваться структуры, описанные в конспекте про про [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;\Gamma'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблицы &amp;lt;tex&amp;gt;ACTION&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;GOTO&amp;lt;/tex&amp;gt; канонического &amp;lt;tex&amp;gt;LR&amp;lt;/tex&amp;gt;-анализа&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(\Gamma'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(\Gamma') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;\Gamma'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(ACTION,&amp;lt;/tex&amp;gt; '''Error'''&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;GOTO(I_i,a) = I_j&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Shift'''(&amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Reduce'''(&amp;lt;tex&amp;gt;A  \to a&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,\char36] = &amp;lt;/tex&amp;gt; '''Accept'''&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;GOTO(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;GOTO[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;left&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot;| Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; |$GOTO$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$c$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$d$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$\char36$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$S$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$C$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$0$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px;text-align:center&amp;quot;| '''Accept'''&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$3$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$4$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$6$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$7$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
* [[LR(k)-грамматики]]&lt;br /&gt;
* [[LR(0)-разбор]]&lt;br /&gt;
* [[SLR(1)-разбор]]&lt;br /&gt;
* [[LALR-разбор]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;br /&gt;
* [http://window.edu.ru/resource/974/69974/files/lang_trans.pdf Б.К.Мартыненко. Языки и трансляции. Стр. 198-223]&lt;br /&gt;
* [http://gas-teach.narod.ru/au/tfl/tfl13.pdf Лекции по теории формальных языков, LR(0)-, SLR(1)-, LR(1)- и LALR(1)-анализ ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49459</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49459"/>
				<updated>2015-09-20T12:50:58Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, при котором SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим состояние $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с ситуацией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях (англ. ''items'') больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
&lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' ситуации, а число $1$ в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$, и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх: либо $\gamma=\delta\alpha$, либо $a$ является первым символом $w$, либо$w=\varepsilon$ и $a=\char36$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\varepsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества наборов ситуаций $items$ для грамматики &lt;br /&gt;
$\Gamma' =\langle\Sigma, N, S, P\rangle$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] closure('''item'''[] $I$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[] $J$ = $I$   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in \Gamma'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      $J$.add($[B\rightarrow\cdot\gamma,b]$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until not''' changed&lt;br /&gt;
      '''return''' $J$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] goto('''item'''[] $I$, '''char''' $X$):&lt;br /&gt;
      '''item'''[] $J=\varnothing$&lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          $J$.add($[A\rightarrow\alpha X\cdot\beta, a]$)&lt;br /&gt;
      '''return''' $closure(J)$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[][] items($\Gamma'$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[][] $C = \{closure({S'\rightarrow\cdot S,\char36})\}$&lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' '''item'''[] $I\subset C$&lt;br /&gt;
              '''for''' $X \in \Gamma'.\Sigma$&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ '''and''' $goto(I,X)\not\subset C$&lt;br /&gt;
                      $C$.add($goto(I,X)$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until not''' changed&lt;br /&gt;
      '''return''' $C$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $\Gamma'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC\mid d$&lt;br /&gt;
Запустим процедуру $items(\Gamma')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\varepsilon;B=S;\beta=\varepsilon;a=\char36$.&lt;br /&gt;
&lt;br /&gt;
Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $[C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$ и $[C\rightarrow\cdot d, d]$. &lt;br /&gt;
Поскольку ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure()$ завершает свою работу.&lt;br /&gt;
&lt;br /&gt;
Начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и переходы между ними]]&lt;br /&gt;
*$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items()$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $\Gamma'$:&lt;br /&gt;
&lt;br /&gt;
#При $X=S$:&lt;br /&gt;
#:$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
#:Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом,  &lt;br /&gt;
#:*$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
#При $X=C$:&lt;br /&gt;
#:$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
#:*$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
#При $X=c$:&lt;br /&gt;
#:$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
#:*$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
#При $X=d$:&lt;br /&gt;
#:$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
#:*$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
*$$I_5=goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
$$I_6=goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
*$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
&lt;br /&gt;
'''NB:''' Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
&lt;br /&gt;
*$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
*$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$: &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
*$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items()$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
В алгоритме будут использоваться структуры, описанные в [http://neerc.ifmo.ru/wiki/index.php?title=LR(k)-%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8#.D0.A3.D0.BF.D1.80.D0.B0.D0.B2.D0.BB.D1.8F.D1.8E.D1.89.D0.B0.D1.8F_.D0.BF.D1.80.D0.BE.D0.B3.D1.80.D0.B0.D0.BC.D0.BC.D0.B0_.D0.B0.D0.BD.D0.B0.D0.BB.D0.B8.D0.B7.D0.B0.D1.82.D0.BE.D1.80.D0.B0 конспекте про LL(k) грамматики]&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;\Gamma'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблицы &amp;lt;tex&amp;gt;ACTION&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;GOTO&amp;lt;/tex&amp;gt; канонического &amp;lt;tex&amp;gt;LR&amp;lt;/tex&amp;gt;-анализа&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(\Gamma'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(\Gamma') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;\Gamma'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(ACTION,&amp;lt;/tex&amp;gt; '''Error'''&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;GOTO(I_i,a) = I_j&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Shift'''(&amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Reduce'''(&amp;lt;tex&amp;gt;A  \to a&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,\char36] = &amp;lt;/tex&amp;gt; '''Accept'''&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;GOTO(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;GOTO[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;left&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot;| Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; |$GOTO$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$c$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$d$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$\char36$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$S$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$C$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$0$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px;text-align:center&amp;quot;| '''Accept'''&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$3$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$4$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$6$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$7$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
* [[LR(k)-грамматики]]&lt;br /&gt;
* [[LR(0)-разбор]]&lt;br /&gt;
* [[SLR(1)-разбор]]&lt;br /&gt;
* [[LALR-разбор]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;br /&gt;
* [http://window.edu.ru/resource/974/69974/files/lang_trans.pdf Б.К.Мартыненко. Языки и трансляции. Стр. 198-223]&lt;br /&gt;
* [http://gas-teach.narod.ru/au/tfl/tfl13.pdf Лекции по теории формальных языков, LR(0)-, SLR(1)-, LR(1)- и LALR(1)-анализ ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49458</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49458"/>
				<updated>2015-09-20T12:50:13Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, при котором SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим состояние $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с ситуацией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях (англ. ''items'') больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
&lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' ситуации, а число $1$ в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$, и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх: либо $\gamma=\delta\alpha$, либо $a$ является первым символом $w$, либо$w=\varepsilon$ и $a=\char36$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\varepsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества наборов ситуаций $items$ для грамматики &lt;br /&gt;
$\Gamma' =\langle\Sigma, N, S, P\rangle$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] closure('''item'''[] $I$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[] $J$ = $I$   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in \Gamma'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      $J$.add($[B\rightarrow\cdot\gamma,b]$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until not''' changed&lt;br /&gt;
      '''return''' $J$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] goto('''item'''[] $I$, '''char''' $X$):&lt;br /&gt;
      '''item'''[] $J=\varnothing$&lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          $J$.add($[A\rightarrow\alpha X\cdot\beta, a]$)&lt;br /&gt;
      '''return''' $closure(J)$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[][] items($\Gamma'$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[][] $C = \{closure({S'\rightarrow\cdot S,\char36})\}$&lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' '''item'''[] $I\subset C$&lt;br /&gt;
              '''for''' $X \in \Gamma'.\Sigma$&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ '''and''' $goto(I,X)\not\subset C$&lt;br /&gt;
                      $C$.add($goto(I,X)$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until not''' changed&lt;br /&gt;
      '''return''' $C$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $\Gamma'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC|d$&lt;br /&gt;
Запустим процедуру $items(\Gamma')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\varepsilon;B=S;\beta=\varepsilon;a=\char36$.&lt;br /&gt;
&lt;br /&gt;
Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $[C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$ и $[C\rightarrow\cdot d, d]$. &lt;br /&gt;
Поскольку ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure()$ завершает свою работу.&lt;br /&gt;
&lt;br /&gt;
Начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и переходы между ними]]&lt;br /&gt;
*$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items()$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $\Gamma'$:&lt;br /&gt;
&lt;br /&gt;
#При $X=S$:&lt;br /&gt;
#:$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
#:Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом,  &lt;br /&gt;
#:*$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
#При $X=C$:&lt;br /&gt;
#:$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
#:*$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
#При $X=c$:&lt;br /&gt;
#:$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
#:*$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
#При $X=d$:&lt;br /&gt;
#:$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
#:*$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
*$$I_5=goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
$$I_6=goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
*$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
&lt;br /&gt;
'''NB:''' Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
&lt;br /&gt;
*$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
*$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$: &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
*$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items()$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
В алгоритме будут использоваться структуры, описанные в [http://neerc.ifmo.ru/wiki/index.php?title=LR(k)-%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8#.D0.A3.D0.BF.D1.80.D0.B0.D0.B2.D0.BB.D1.8F.D1.8E.D1.89.D0.B0.D1.8F_.D0.BF.D1.80.D0.BE.D0.B3.D1.80.D0.B0.D0.BC.D0.BC.D0.B0_.D0.B0.D0.BD.D0.B0.D0.BB.D0.B8.D0.B7.D0.B0.D1.82.D0.BE.D1.80.D0.B0 конспекте про LL(k) грамматики]&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;\Gamma'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблицы &amp;lt;tex&amp;gt;ACTION&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;GOTO&amp;lt;/tex&amp;gt; канонического &amp;lt;tex&amp;gt;LR&amp;lt;/tex&amp;gt;-анализа&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(\Gamma'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(\Gamma') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;\Gamma'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(ACTION,&amp;lt;/tex&amp;gt; '''Error'''&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;GOTO(I_i,a) = I_j&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Shift'''(&amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Reduce'''(&amp;lt;tex&amp;gt;A  \to a&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,\char36] = &amp;lt;/tex&amp;gt; '''Accept'''&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;GOTO(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;GOTO[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;left&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot;| Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; |$GOTO$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$c$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$d$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$\char36$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$S$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$C$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$0$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px;text-align:center&amp;quot;| '''Accept'''&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$3$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$4$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$6$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$7$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
* [[LR(k)-грамматики]]&lt;br /&gt;
* [[LR(0)-разбор]]&lt;br /&gt;
* [[SLR(1)-разбор]]&lt;br /&gt;
* [[LALR-разбор]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;br /&gt;
* [http://window.edu.ru/resource/974/69974/files/lang_trans.pdf Б.К.Мартыненко. Языки и трансляции. Стр. 198-223]&lt;br /&gt;
* [http://gas-teach.narod.ru/au/tfl/tfl13.pdf Лекции по теории формальных языков, LR(0)-, SLR(1)-, LR(1)- и LALR(1)-анализ ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49457</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49457"/>
				<updated>2015-09-20T12:48:46Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, при котором SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим состояние $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с ситуацией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях (англ. ''items'') больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
&lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' ситуации, а число $1$ в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$, и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх: либо $\gamma=\delta\alpha$, либо $a$ является первым символом $w$, либо$w=\varepsilon$ и $a=\char36$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\varepsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества наборов ситуаций $items$ для грамматики &lt;br /&gt;
$\Gamma' =\langle\Sigma, N, S, P\rangle$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] closure('''item'''[] $I$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[] $J$ = $I$   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in \Gamma'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      $J$.add($[B\rightarrow\cdot\gamma,b]$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' $J$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] goto('''item'''[] $I$, '''char''' $X$):&lt;br /&gt;
      '''item'''[] $J=\varnothing$&lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          $J$.add($[A\rightarrow\alpha X\cdot\beta, a]$)&lt;br /&gt;
      '''return''' $closure(J)$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[][] items($\Gamma'$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[][] $C = \{closure({S'\rightarrow\cdot S,\char36})\}$&lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' '''item'''[] $I\subset C$&lt;br /&gt;
              '''for''' $X \in \Gamma'.\Sigma$&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ and $goto(I,X)\not\subset C$&lt;br /&gt;
                      $C$.add($goto(I,X)$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' $C$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $\Gamma'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC|d$&lt;br /&gt;
Запустим процедуру $items(\Gamma')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\varepsilon;B=S;\beta=\varepsilon;a=\char36$.&lt;br /&gt;
&lt;br /&gt;
Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $[C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$ и $[C\rightarrow\cdot d, d]$. &lt;br /&gt;
Поскольку ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure()$ завершает свою работу.&lt;br /&gt;
&lt;br /&gt;
Начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и переходы между ними]]&lt;br /&gt;
*$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items()$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $\Gamma'$:&lt;br /&gt;
&lt;br /&gt;
#При $X=S$:&lt;br /&gt;
#:$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
#:Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом,  &lt;br /&gt;
#:*$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
#При $X=C$:&lt;br /&gt;
#:$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
#:*$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
#При $X=c$:&lt;br /&gt;
#:$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
#:*$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
#При $X=d$:&lt;br /&gt;
#:$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
#:*$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
*$$I_5=goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
$$I_6=goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
*$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
&lt;br /&gt;
'''NB:''' Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
&lt;br /&gt;
*$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
*$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$: &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
*$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items()$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
В алгоритме будут использоваться структуры, описанные в [http://neerc.ifmo.ru/wiki/index.php?title=LR(k)-%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8#.D0.A3.D0.BF.D1.80.D0.B0.D0.B2.D0.BB.D1.8F.D1.8E.D1.89.D0.B0.D1.8F_.D0.BF.D1.80.D0.BE.D0.B3.D1.80.D0.B0.D0.BC.D0.BC.D0.B0_.D0.B0.D0.BD.D0.B0.D0.BB.D0.B8.D0.B7.D0.B0.D1.82.D0.BE.D1.80.D0.B0 конспекте про LL(k) грамматики]&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;\Gamma'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблицы &amp;lt;tex&amp;gt;ACTION&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;GOTO&amp;lt;/tex&amp;gt; канонического &amp;lt;tex&amp;gt;LR&amp;lt;/tex&amp;gt;-анализа&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(\Gamma'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(\Gamma') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;\Gamma'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(ACTION,&amp;lt;/tex&amp;gt; '''Error'''&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;GOTO(I_i,a) = I_j&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Shift'''(&amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Reduce'''(&amp;lt;tex&amp;gt;A  \to a&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,\char36] = &amp;lt;/tex&amp;gt; '''Accept'''&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;GOTO(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;GOTO[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;left&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot;| Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; |$GOTO$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$c$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$d$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$\char36$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$S$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$C$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$0$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px;text-align:center&amp;quot;| '''Accept'''&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$3$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$4$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$6$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$7$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
* [[LR(k)-грамматики]]&lt;br /&gt;
* [[LR(0)-разбор]]&lt;br /&gt;
* [[SLR(1)-разбор]]&lt;br /&gt;
* [[LALR-разбор]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;br /&gt;
* [http://window.edu.ru/resource/974/69974/files/lang_trans.pdf Б.К.Мартыненко. Языки и трансляции. Стр. 198-223]&lt;br /&gt;
* [http://gas-teach.narod.ru/au/tfl/tfl13.pdf Лекции по теории формальных языков, LR(0)-, SLR(1)-, LR(1)- и LALR(1)-анализ ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49456</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49456"/>
				<updated>2015-09-20T12:47:30Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, при котором SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим состояние $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с ситуацией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях (англ. ''items'') больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
&lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' ситуации, а число $1$ в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$, и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх: либо $\gamma=\delta\alpha$, либо $a$ является первым символом $w$, либо$w=\varepsilon$ и $a=\char36$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\varepsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества наборов ситуаций $items$ для грамматики &lt;br /&gt;
$\Gamma' =\langle\Sigma, N, S, P\rangle$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] closure('''item'''[] $I$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[] $J$ = $I$   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in \Gamma'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      $J$.add($[B\rightarrow\cdot\gamma,b]$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' $J$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] goto('''item'''[] $I$, '''char''' $X$):&lt;br /&gt;
      '''item'''[] $J=\varnothing$&lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          $J$.add($[A\rightarrow\alpha X\cdot\beta, a]$)&lt;br /&gt;
      '''return''' $closure(J)$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[][] items($\Gamma'$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[][] $C = \{closure({S'\rightarrow\cdot S,\char36})\}$&lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' '''item'''[] $I\subset C$&lt;br /&gt;
              '''for''' $X \in \Gamma'.\Sigma$&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ and $goto(I,X)\not\subset C$&lt;br /&gt;
                      $C$.add($goto(I,X)$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' $C$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC|d$&lt;br /&gt;
Запустим процедуру $items(G')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\varepsilon;B=S;\beta=\varepsilon;a=\char36$.&lt;br /&gt;
&lt;br /&gt;
Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $[C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$ и $[C\rightarrow\cdot d, d]$. &lt;br /&gt;
Поскольку ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure()$ завершает свою работу.&lt;br /&gt;
&lt;br /&gt;
Начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и переходы между ними]]&lt;br /&gt;
*$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items()$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $G'$:&lt;br /&gt;
&lt;br /&gt;
#При $X=S$:&lt;br /&gt;
#:$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
#:Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом,  &lt;br /&gt;
#:*$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
#При $X=C$:&lt;br /&gt;
#:$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
#:*$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
#При $X=c$:&lt;br /&gt;
#:$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
#:*$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
#При $X=d$:&lt;br /&gt;
#:$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
#:*$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
*$$I_5=goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
$$I_6=goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
*$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
&lt;br /&gt;
'''NB:''' Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
&lt;br /&gt;
*$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
*$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$: &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
*$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items()$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
В алгоритме будут использоваться структуры, описанные в [http://neerc.ifmo.ru/wiki/index.php?title=LR(k)-%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8#.D0.A3.D0.BF.D1.80.D0.B0.D0.B2.D0.BB.D1.8F.D1.8E.D1.89.D0.B0.D1.8F_.D0.BF.D1.80.D0.BE.D0.B3.D1.80.D0.B0.D0.BC.D0.BC.D0.B0_.D0.B0.D0.BD.D0.B0.D0.BB.D0.B8.D0.B7.D0.B0.D1.82.D0.BE.D1.80.D0.B0 конспекте про LL(k) грамматики]&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблицы &amp;lt;tex&amp;gt;ACTION&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;GOTO&amp;lt;/tex&amp;gt; канонического &amp;lt;tex&amp;gt;LR&amp;lt;/tex&amp;gt;-анализа&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(G'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(G') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(ACTION,&amp;lt;/tex&amp;gt; '''Error'''&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;GOTO(I_i,a) = I_j&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Shift'''(&amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Reduce'''(&amp;lt;tex&amp;gt;A  \to a&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,\char36] = &amp;lt;/tex&amp;gt; '''Accept'''&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;GOTO(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;GOTO[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;left&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot;| Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; |$GOTO$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$c$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$d$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$\char36$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$S$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$C$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$0$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px;text-align:center&amp;quot;| '''Accept'''&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$3$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$4$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$6$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$7$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
* [[LR(k)-грамматики]]&lt;br /&gt;
* [[LR(0)-разбор]]&lt;br /&gt;
* [[SLR(1)-разбор]]&lt;br /&gt;
* [[LALR-разбор]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;br /&gt;
* [http://window.edu.ru/resource/974/69974/files/lang_trans.pdf Б.К.Мартыненко. Языки и трансляции. Стр. 198-223]&lt;br /&gt;
* [http://gas-teach.narod.ru/au/tfl/tfl13.pdf Лекции по теории формальных языков, LR(0)-, SLR(1)-, LR(1)- и LALR(1)-анализ ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49455</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49455"/>
				<updated>2015-09-20T12:46:29Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, при котором SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим состояние $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с ситуацией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях (англ. ''items'') больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
&lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' ситуации, а число $1$ в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$, и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх: либо $\gamma=\delta\alpha$, либо $a$ является первым символом $w$, либо$w=\varepsilon$ и $a=\char36$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\varepsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества наборов ситуаций $items$ для грамматики &lt;br /&gt;
$\Gamma' =\langle\Sigma, N, S, P\rangle$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] closure('''item'''[] $I$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[] $J$ = $I$   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in \Gamma'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      $J$.add($[B\rightarrow\cdot\gamma,b]$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' $J$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] goto('''item'''[] $I$, '''char''' $X$):&lt;br /&gt;
      '''item'''[] $J=\varnothing$&lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          $J$.add($[A\rightarrow\alpha X\cdot\beta, a]$)&lt;br /&gt;
      '''return''' $closure(J)$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[][] items($\Gamma'$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[][] $C = \{closure({S'\rightarrow\cdot S,\char36})\}$&lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' '''item'''[] $I\subset C$&lt;br /&gt;
              '''for''' $X \in \Sigma(\Gamma')$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;//по всем символам грамматики&amp;lt;/font&amp;gt;&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ and $goto(I,X)\not\subset C$&lt;br /&gt;
                      $C$.add($goto(I,X)$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' $C$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC|d$&lt;br /&gt;
Запустим процедуру $items(G')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\varepsilon;B=S;\beta=\varepsilon;a=\char36$.&lt;br /&gt;
&lt;br /&gt;
Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $[C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$ и $[C\rightarrow\cdot d, d]$. &lt;br /&gt;
Поскольку ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure()$ завершает свою работу.&lt;br /&gt;
&lt;br /&gt;
Начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и переходы между ними]]&lt;br /&gt;
*$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items()$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $G'$:&lt;br /&gt;
&lt;br /&gt;
#При $X=S$:&lt;br /&gt;
#:$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
#:Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом,  &lt;br /&gt;
#:*$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
#При $X=C$:&lt;br /&gt;
#:$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
#:*$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
#При $X=c$:&lt;br /&gt;
#:$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
#:*$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
#При $X=d$:&lt;br /&gt;
#:$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
#:*$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
*$$I_5=goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
$$I_6=goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
*$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
&lt;br /&gt;
'''NB:''' Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
&lt;br /&gt;
*$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
*$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$: &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
*$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items()$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
В алгоритме будут использоваться структуры, описанные в [http://neerc.ifmo.ru/wiki/index.php?title=LR(k)-%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8#.D0.A3.D0.BF.D1.80.D0.B0.D0.B2.D0.BB.D1.8F.D1.8E.D1.89.D0.B0.D1.8F_.D0.BF.D1.80.D0.BE.D0.B3.D1.80.D0.B0.D0.BC.D0.BC.D0.B0_.D0.B0.D0.BD.D0.B0.D0.BB.D0.B8.D0.B7.D0.B0.D1.82.D0.BE.D1.80.D0.B0 конспекте про LL(k) грамматики]&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблицы &amp;lt;tex&amp;gt;ACTION&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;GOTO&amp;lt;/tex&amp;gt; канонического &amp;lt;tex&amp;gt;LR&amp;lt;/tex&amp;gt;-анализа&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(G'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(G') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(ACTION,&amp;lt;/tex&amp;gt; '''Error'''&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;GOTO(I_i,a) = I_j&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Shift'''(&amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Reduce'''(&amp;lt;tex&amp;gt;A  \to a&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,\char36] = &amp;lt;/tex&amp;gt; '''Accept'''&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;GOTO(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;GOTO[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;left&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot;| Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; |$GOTO$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$c$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$d$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$\char36$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$S$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$C$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$0$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px;text-align:center&amp;quot;| '''Accept'''&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$3$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$4$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$6$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$7$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
* [[LR(k)-грамматики]]&lt;br /&gt;
* [[LR(0)-разбор]]&lt;br /&gt;
* [[SLR(1)-разбор]]&lt;br /&gt;
* [[LALR-разбор]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;br /&gt;
* [http://window.edu.ru/resource/974/69974/files/lang_trans.pdf Б.К.Мартыненко. Языки и трансляции. Стр. 198-223]&lt;br /&gt;
* [http://gas-teach.narod.ru/au/tfl/tfl13.pdf Лекции по теории формальных языков, LR(0)-, SLR(1)-, LR(1)- и LALR(1)-анализ ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49454</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49454"/>
				<updated>2015-09-20T12:40:55Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, при котором SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим состояние $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с ситуацией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях (англ. ''items'') больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
&lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' ситуации, а число $1$ в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$, и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх: либо $\gamma=\delta\alpha$, либо $a$ является первым символом $w$, либо$w=\varepsilon$ и $a=\char36$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\varepsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества наборов ситуаций $items$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] closure('''item'''[] $I$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[] $J$ = $I$   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in G'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      $J$.add($[B\rightarrow\cdot\gamma,b]$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' $J$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] goto('''item'''[] $I$, '''char''' $X$):&lt;br /&gt;
      '''item'''[] $J=\varnothing$&lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          $J$.add($[A\rightarrow\alpha X\cdot\beta, a]$)&lt;br /&gt;
      '''return''' $closure(J)$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[][] items($G'$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[][] $C = \{closure({S'\rightarrow\cdot S,\char36})\}$&lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' '''item'''[] $I\subset C$&lt;br /&gt;
              '''for''' $X \in G'$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;//по всем символам грамматики&amp;lt;/font&amp;gt;&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ and $goto(I,X)\not\subset C$&lt;br /&gt;
                      $C$.add($goto(I,X)$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' $C$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC|d$&lt;br /&gt;
Запустим процедуру $items(G')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\varepsilon;B=S;\beta=\varepsilon;a=\char36$.&lt;br /&gt;
&lt;br /&gt;
Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $[C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$ и $[C\rightarrow\cdot d, d]$. &lt;br /&gt;
Поскольку ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure()$ завершает свою работу.&lt;br /&gt;
&lt;br /&gt;
Начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и переходы между ними]]&lt;br /&gt;
*$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items()$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $G'$:&lt;br /&gt;
&lt;br /&gt;
#При $X=S$:&lt;br /&gt;
#:$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
#:Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом,  &lt;br /&gt;
#:*$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
#При $X=C$:&lt;br /&gt;
#:$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
#:*$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
#При $X=c$:&lt;br /&gt;
#:$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
#:*$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
#При $X=d$:&lt;br /&gt;
#:$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
#:*$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
*$$I_5=goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
$$I_6=goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
*$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
&lt;br /&gt;
'''NB:''' Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
&lt;br /&gt;
*$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
*$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$: &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
*$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items()$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
В алгоритме будут использоваться структуры, описанные в [http://neerc.ifmo.ru/wiki/index.php?title=LR(k)-%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8#.D0.A3.D0.BF.D1.80.D0.B0.D0.B2.D0.BB.D1.8F.D1.8E.D1.89.D0.B0.D1.8F_.D0.BF.D1.80.D0.BE.D0.B3.D1.80.D0.B0.D0.BC.D0.BC.D0.B0_.D0.B0.D0.BD.D0.B0.D0.BB.D0.B8.D0.B7.D0.B0.D1.82.D0.BE.D1.80.D0.B0 конспекте про LL(k) грамматики]&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблицы &amp;lt;tex&amp;gt;ACTION&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;GOTO&amp;lt;/tex&amp;gt; канонического &amp;lt;tex&amp;gt;LR&amp;lt;/tex&amp;gt;-анализа&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(G'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(G') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(ACTION,&amp;lt;/tex&amp;gt; '''Error'''&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;GOTO(I_i,a) = I_j&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Shift'''(&amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Reduce'''(&amp;lt;tex&amp;gt;A  \to a&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,\char36] = &amp;lt;/tex&amp;gt; '''Accept'''&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;GOTO(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;GOTO[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;left&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot;| Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; |$GOTO$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$c$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$d$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$\char36$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$S$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$C$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$0$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px;text-align:center&amp;quot;| '''Accept'''&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$3$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$4$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$6$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$7$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
* [[LR(k)-грамматики]]&lt;br /&gt;
* [[LR(0)-разбор]]&lt;br /&gt;
* [[SLR(1)-разбор]]&lt;br /&gt;
* [[LALR-разбор]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;br /&gt;
* [http://window.edu.ru/resource/974/69974/files/lang_trans.pdf Б.К.Мартыненко. Языки и трансляции. Стр. 198-223]&lt;br /&gt;
* [http://gas-teach.narod.ru/au/tfl/tfl13.pdf Лекции по теории формальных языков, LR(0)-, SLR(1)-, LR(1)- и LALR(1)-анализ ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49453</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49453"/>
				<updated>2015-09-20T12:40:27Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, при котором SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим состояние $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с ситуацией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях (англ. ''items'') больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
&lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' ситуации, а число $1$ в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$, и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх: либо $\gamma=\delta\alpha$, либо $a$ является первым символом $w$, либо$w=\varepsilon$ и $a=\char36$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\varepsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества наборов ситуаций $items$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] closure('''item'''[] $I$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[] $J$ = $I$   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in G'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      $J$.add($[B\rightarrow\cdot\gamma,b]$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' $J$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] goto('''item'''[] $I$, '''char''' $X$):&lt;br /&gt;
      '''item'''[] $J=\varnothing$&lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          $J$.add($[A\rightarrow\alpha X\cdot\beta, a]$)&lt;br /&gt;
      '''return''' $closure(J)$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[][] items($G'$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[][] $C = \{closure({S'\rightarrow\cdot S,\char36})\}$&lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' Item[] $I\subset C$&lt;br /&gt;
              '''for''' $X \in G'$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;//по всем символам грамматики&amp;lt;/font&amp;gt;&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ and $goto(I,X)\not\subset C$&lt;br /&gt;
                      $C$.add($goto(I,X)$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' $C$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC|d$&lt;br /&gt;
Запустим процедуру $items(G')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\varepsilon;B=S;\beta=\varepsilon;a=\char36$.&lt;br /&gt;
&lt;br /&gt;
Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $[C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$ и $[C\rightarrow\cdot d, d]$. &lt;br /&gt;
Поскольку ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure()$ завершает свою работу.&lt;br /&gt;
&lt;br /&gt;
Начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и переходы между ними]]&lt;br /&gt;
*$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items()$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $G'$:&lt;br /&gt;
&lt;br /&gt;
#При $X=S$:&lt;br /&gt;
#:$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
#:Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом,  &lt;br /&gt;
#:*$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
#При $X=C$:&lt;br /&gt;
#:$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
#:*$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
#При $X=c$:&lt;br /&gt;
#:$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
#:*$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
#При $X=d$:&lt;br /&gt;
#:$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
#:*$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
*$$I_5=goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
$$I_6=goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
*$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
&lt;br /&gt;
'''NB:''' Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
&lt;br /&gt;
*$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
*$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$: &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
*$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items()$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
В алгоритме будут использоваться структуры, описанные в [http://neerc.ifmo.ru/wiki/index.php?title=LR(k)-%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8#.D0.A3.D0.BF.D1.80.D0.B0.D0.B2.D0.BB.D1.8F.D1.8E.D1.89.D0.B0.D1.8F_.D0.BF.D1.80.D0.BE.D0.B3.D1.80.D0.B0.D0.BC.D0.BC.D0.B0_.D0.B0.D0.BD.D0.B0.D0.BB.D0.B8.D0.B7.D0.B0.D1.82.D0.BE.D1.80.D0.B0 конспекте про LL(k) грамматики]&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблицы &amp;lt;tex&amp;gt;ACTION&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;GOTO&amp;lt;/tex&amp;gt; канонического &amp;lt;tex&amp;gt;LR&amp;lt;/tex&amp;gt;-анализа&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(G'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(G') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(ACTION,&amp;lt;/tex&amp;gt; '''Error'''&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;GOTO(I_i,a) = I_j&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Shift'''(&amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Reduce'''(&amp;lt;tex&amp;gt;A  \to a&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,\char36] = &amp;lt;/tex&amp;gt; '''Accept'''&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;GOTO(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;GOTO[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;left&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot;| Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; |$GOTO$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$c$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$d$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$\char36$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$S$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$C$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$0$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px;text-align:center&amp;quot;| '''Accept'''&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$3$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$4$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$6$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$7$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
* [[LR(k)-грамматики]]&lt;br /&gt;
* [[LR(0)-разбор]]&lt;br /&gt;
* [[SLR(1)-разбор]]&lt;br /&gt;
* [[LALR-разбор]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;br /&gt;
* [http://window.edu.ru/resource/974/69974/files/lang_trans.pdf Б.К.Мартыненко. Языки и трансляции. Стр. 198-223]&lt;br /&gt;
* [http://gas-teach.narod.ru/au/tfl/tfl13.pdf Лекции по теории формальных языков, LR(0)-, SLR(1)-, LR(1)- и LALR(1)-анализ ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49452</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49452"/>
				<updated>2015-09-20T12:39:22Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, при котором SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим состояние $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с ситуацией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях (англ. ''items'') больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
&lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' ситуации, а число $1$ в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$, и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх: либо $\gamma=\delta\alpha$, либо $a$ является первым символом $w$, либо$w=\varepsilon$ и $a=\char36$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\varepsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества наборов ситуаций $items$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] closure(Item[] $I$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[] $J$ = $I$   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in G'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      $J$.add($[B\rightarrow\cdot\gamma,b]$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' $J$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[] goto(Item[] $I$, $X$):&lt;br /&gt;
      '''item'''[] $J=\varnothing$&lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          $J$.add($[A\rightarrow\alpha X\cdot\beta, a]$)&lt;br /&gt;
      '''return''' $closure(J)$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''item'''[][] items($G'$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      '''item'''[][] $C = \{closure({S'\rightarrow\cdot S,\char36})\}$&lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' Item[] $I\subset C$&lt;br /&gt;
              '''for''' $X \in symbols(G')$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;//по всем символам грамматики&amp;lt;/font&amp;gt;&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ and $goto(I,X)\not\subset C$&lt;br /&gt;
                      $C$.add($goto(I,X)$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' $C$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC|d$&lt;br /&gt;
Запустим процедуру $items(G')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\varepsilon;B=S;\beta=\varepsilon;a=\char36$.&lt;br /&gt;
&lt;br /&gt;
Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $[C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$ и $[C\rightarrow\cdot d, d]$. &lt;br /&gt;
Поскольку ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure()$ завершает свою работу.&lt;br /&gt;
&lt;br /&gt;
Начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и переходы между ними]]&lt;br /&gt;
*$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items()$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $G'$:&lt;br /&gt;
&lt;br /&gt;
#При $X=S$:&lt;br /&gt;
#:$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
#:Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом,  &lt;br /&gt;
#:*$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
#При $X=C$:&lt;br /&gt;
#:$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
#:*$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
#При $X=c$:&lt;br /&gt;
#:$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
#:*$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
#При $X=d$:&lt;br /&gt;
#:$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
#:*$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
*$$I_5=goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
$$I_6=goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
*$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
&lt;br /&gt;
'''NB:''' Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
&lt;br /&gt;
*$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
*$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$: &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
*$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items()$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
В алгоритме будут использоваться структуры, описанные в [http://neerc.ifmo.ru/wiki/index.php?title=LR(k)-%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8#.D0.A3.D0.BF.D1.80.D0.B0.D0.B2.D0.BB.D1.8F.D1.8E.D1.89.D0.B0.D1.8F_.D0.BF.D1.80.D0.BE.D0.B3.D1.80.D0.B0.D0.BC.D0.BC.D0.B0_.D0.B0.D0.BD.D0.B0.D0.BB.D0.B8.D0.B7.D0.B0.D1.82.D0.BE.D1.80.D0.B0 конспекте про LL(k) грамматики]&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблицы &amp;lt;tex&amp;gt;ACTION&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;GOTO&amp;lt;/tex&amp;gt; канонического &amp;lt;tex&amp;gt;LR&amp;lt;/tex&amp;gt;-анализа&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(G'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(G') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(ACTION,&amp;lt;/tex&amp;gt; '''Error'''&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;GOTO(I_i,a) = I_j&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Shift'''(&amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Reduce'''(&amp;lt;tex&amp;gt;A  \to a&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,\char36] = &amp;lt;/tex&amp;gt; '''Accept'''&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;GOTO(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;GOTO[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;left&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot;| Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; |$GOTO$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$c$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$d$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$\char36$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$S$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$C$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$0$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px;text-align:center&amp;quot;| '''Accept'''&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$3$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$4$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$6$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$7$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
* [[LR(k)-грамматики]]&lt;br /&gt;
* [[LR(0)-разбор]]&lt;br /&gt;
* [[SLR(1)-разбор]]&lt;br /&gt;
* [[LALR-разбор]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;br /&gt;
* [http://window.edu.ru/resource/974/69974/files/lang_trans.pdf Б.К.Мартыненко. Языки и трансляции. Стр. 198-223]&lt;br /&gt;
* [http://gas-teach.narod.ru/au/tfl/tfl13.pdf Лекции по теории формальных языков, LR(0)-, SLR(1)-, LR(1)- и LALR(1)-анализ ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49451</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49451"/>
				<updated>2015-09-20T12:38:00Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: /* Канонические LR(1)-ситуации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, при котором SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим состояние $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с ситуацией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях (англ. ''items'') больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
&lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' ситуации, а число $1$ в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$, и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх: либо $\gamma=\delta\alpha$, либо $a$ является первым символом $w$, либо$w=\varepsilon$ и $a=\char36$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\varepsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества наборов ситуаций $items$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Item[] closure(Item[] $I$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      Item[] $J$ = $I$   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in G'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      $J$.add($[B\rightarrow\cdot\gamma,b]$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' $J$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Item[] goto(Item[] $I$, $X$):&lt;br /&gt;
      Item[] $J=\varnothing$&lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          $J$.add($[A\rightarrow\alpha X\cdot\beta, a]$)&lt;br /&gt;
      '''return''' $closure(J)$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Item[][] items($G'$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      Item[][] $C = \{closure({S'\rightarrow\cdot S,\char36})\}$&lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' Item[] $I\subset C$&lt;br /&gt;
              '''for''' $X \in symbols(G')$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;//по всем символам грамматики&amp;lt;/font&amp;gt;&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ and $goto(I,X)\not\subset C$&lt;br /&gt;
                      $C$.add($goto(I,X)$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' $C$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC|d$&lt;br /&gt;
Запустим процедуру $items(G')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\varepsilon;B=S;\beta=\varepsilon;a=\char36$.&lt;br /&gt;
&lt;br /&gt;
Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $[C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$ и $[C\rightarrow\cdot d, d]$. &lt;br /&gt;
Поскольку ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure()$ завершает свою работу.&lt;br /&gt;
&lt;br /&gt;
Начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и переходы между ними]]&lt;br /&gt;
*$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items()$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $G'$:&lt;br /&gt;
&lt;br /&gt;
#При $X=S$:&lt;br /&gt;
#:$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
#:Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом,  &lt;br /&gt;
#:*$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
#При $X=C$:&lt;br /&gt;
#:$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
#:*$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
#При $X=c$:&lt;br /&gt;
#:$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
#:*$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
#При $X=d$:&lt;br /&gt;
#:$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
#:*$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
*$$I_5=goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
$$I_6=goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
*$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
&lt;br /&gt;
'''NB:''' Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
&lt;br /&gt;
*$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
*$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$: &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
*$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items()$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
В алгоритме будут использоваться структуры, описанные в [http://neerc.ifmo.ru/wiki/index.php?title=LR(k)-%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8#.D0.A3.D0.BF.D1.80.D0.B0.D0.B2.D0.BB.D1.8F.D1.8E.D1.89.D0.B0.D1.8F_.D0.BF.D1.80.D0.BE.D0.B3.D1.80.D0.B0.D0.BC.D0.BC.D0.B0_.D0.B0.D0.BD.D0.B0.D0.BB.D0.B8.D0.B7.D0.B0.D1.82.D0.BE.D1.80.D0.B0 конспекте про LL(k) грамматики]&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблицы &amp;lt;tex&amp;gt;ACTION&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;GOTO&amp;lt;/tex&amp;gt; канонического &amp;lt;tex&amp;gt;LR&amp;lt;/tex&amp;gt;-анализа&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(G'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(G') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(ACTION,&amp;lt;/tex&amp;gt; '''Error'''&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;GOTO(I_i,a) = I_j&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Shift'''(&amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Reduce'''(&amp;lt;tex&amp;gt;A  \to a&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,\char36] = &amp;lt;/tex&amp;gt; '''Accept'''&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;GOTO(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;GOTO[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;left&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot;| Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; |$GOTO$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$c$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$d$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$\char36$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$S$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$C$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$0$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px;text-align:center&amp;quot;| '''Accept'''&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$3$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$4$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$6$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$7$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
* [[LR(k)-грамматики]]&lt;br /&gt;
* [[LR(0)-разбор]]&lt;br /&gt;
* [[SLR(1)-разбор]]&lt;br /&gt;
* [[LALR-разбор]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;br /&gt;
* [http://window.edu.ru/resource/974/69974/files/lang_trans.pdf Б.К.Мартыненко. Языки и трансляции. Стр. 198-223]&lt;br /&gt;
* [http://gas-teach.narod.ru/au/tfl/tfl13.pdf Лекции по теории формальных языков, LR(0)-, SLR(1)-, LR(1)- и LALR(1)-анализ ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49450</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49450"/>
				<updated>2015-09-20T12:37:19Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: /* Канонические LR(1)-ситуации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, при котором SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим состояние $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с ситуацией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях (англ. ''items'') больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' ситуации, а число $1$ в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$, и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх: либо $\gamma=\delta\alpha$, либо $a$ является первым символом $w$, либо$w=\varepsilon$ и $a=\char36$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\varepsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества наборов ситуаций $items$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Item[] closure(Item[] $I$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      Item[] $J$ = $I$   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in G'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      $J$.add($[B\rightarrow\cdot\gamma,b]$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' $J$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Item[] goto(Item[] $I$, $X$):&lt;br /&gt;
      Item[] $J=\varnothing$&lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          $J$.add($[A\rightarrow\alpha X\cdot\beta, a]$)&lt;br /&gt;
      '''return''' $closure(J)$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Item[][] items($G'$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      Item[][] $C = \{closure({S'\rightarrow\cdot S,\char36})\}$&lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' Item[] $I\subset C$&lt;br /&gt;
              '''for''' $X \in symbols(G')$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;//по всем символам грамматики&amp;lt;/font&amp;gt;&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ and $goto(I,X)\not\subset C$&lt;br /&gt;
                      $C$.add($goto(I,X)$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' $C$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC|d$&lt;br /&gt;
Запустим процедуру $items(G')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\varepsilon;B=S;\beta=\varepsilon;a=\char36$.&lt;br /&gt;
&lt;br /&gt;
Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $[C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$ и $[C\rightarrow\cdot d, d]$. &lt;br /&gt;
Поскольку ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure()$ завершает свою работу.&lt;br /&gt;
&lt;br /&gt;
Начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и переходы между ними]]&lt;br /&gt;
*$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items()$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $G'$:&lt;br /&gt;
&lt;br /&gt;
#При $X=S$:&lt;br /&gt;
#:$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
#:Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом,  &lt;br /&gt;
#:*$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
#При $X=C$:&lt;br /&gt;
#:$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
#:*$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
#При $X=c$:&lt;br /&gt;
#:$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
#:*$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
#При $X=d$:&lt;br /&gt;
#:$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
#:*$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
*$$I_5=goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
$$I_6=goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
*$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
&lt;br /&gt;
'''NB:''' Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
&lt;br /&gt;
*$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
*$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$: &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
*$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items()$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
В алгоритме будут использоваться структуры, описанные в [http://neerc.ifmo.ru/wiki/index.php?title=LR(k)-%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8#.D0.A3.D0.BF.D1.80.D0.B0.D0.B2.D0.BB.D1.8F.D1.8E.D1.89.D0.B0.D1.8F_.D0.BF.D1.80.D0.BE.D0.B3.D1.80.D0.B0.D0.BC.D0.BC.D0.B0_.D0.B0.D0.BD.D0.B0.D0.BB.D0.B8.D0.B7.D0.B0.D1.82.D0.BE.D1.80.D0.B0 конспекте про LL(k) грамматики]&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблицы &amp;lt;tex&amp;gt;ACTION&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;GOTO&amp;lt;/tex&amp;gt; канонического &amp;lt;tex&amp;gt;LR&amp;lt;/tex&amp;gt;-анализа&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(G'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(G') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(ACTION,&amp;lt;/tex&amp;gt; '''Error'''&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;GOTO(I_i,a) = I_j&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Shift'''(&amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Reduce'''(&amp;lt;tex&amp;gt;A  \to a&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,\char36] = &amp;lt;/tex&amp;gt; '''Accept'''&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;GOTO(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;GOTO[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;left&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot;| Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; |$GOTO$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$c$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$d$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$\char36$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$S$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$C$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$0$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px;text-align:center&amp;quot;| '''Accept'''&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$3$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$4$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$6$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$7$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
* [[LR(k)-грамматики]]&lt;br /&gt;
* [[LR(0)-разбор]]&lt;br /&gt;
* [[SLR(1)-разбор]]&lt;br /&gt;
* [[LALR-разбор]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;br /&gt;
* [http://window.edu.ru/resource/974/69974/files/lang_trans.pdf Б.К.Мартыненко. Языки и трансляции. Стр. 198-223]&lt;br /&gt;
* [http://gas-teach.narod.ru/au/tfl/tfl13.pdf Лекции по теории формальных языков, LR(0)-, SLR(1)-, LR(1)- и LALR(1)-анализ ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49449</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49449"/>
				<updated>2015-09-20T12:36:03Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, при котором SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим состояние $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с ситуацией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' ситуации, а число $1$ в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$, и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх: либо $\gamma=\delta\alpha$, либо $a$ является первым символом $w$, либо$w=\varepsilon$ и $a=\char36$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\varepsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества наборов ситуаций $items$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Item[] closure(Item[] $I$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      Item[] $J$ = $I$   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in G'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      $J$.add($[B\rightarrow\cdot\gamma,b]$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' $J$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Item[] goto(Item[] $I$, $X$):&lt;br /&gt;
      Item[] $J=\varnothing$&lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          $J$.add($[A\rightarrow\alpha X\cdot\beta, a]$)&lt;br /&gt;
      '''return''' $closure(J)$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Item[][] items($G'$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      Item[][] $C = \{closure({S'\rightarrow\cdot S,\char36})\}$&lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' Item[] $I\subset C$&lt;br /&gt;
              '''for''' $X \in symbols(G')$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;//по всем символам грамматики&amp;lt;/font&amp;gt;&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ and $goto(I,X)\not\subset C$&lt;br /&gt;
                      $C$.add($goto(I,X)$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' $C$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC|d$&lt;br /&gt;
Запустим процедуру $items(G')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\varepsilon;B=S;\beta=\varepsilon;a=\char36$.&lt;br /&gt;
&lt;br /&gt;
Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $[C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$ и $[C\rightarrow\cdot d, d]$. &lt;br /&gt;
Поскольку ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure()$ завершает свою работу.&lt;br /&gt;
&lt;br /&gt;
Начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и переходы между ними]]&lt;br /&gt;
*$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items()$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $G'$:&lt;br /&gt;
&lt;br /&gt;
#При $X=S$:&lt;br /&gt;
#:$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
#:Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом,  &lt;br /&gt;
#:*$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
#При $X=C$:&lt;br /&gt;
#:$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
#:*$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
#При $X=c$:&lt;br /&gt;
#:$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
#:*$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
#При $X=d$:&lt;br /&gt;
#:$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
#:*$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
*$$I_5=goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
$$I_6=goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
*$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
&lt;br /&gt;
'''NB:''' Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
&lt;br /&gt;
*$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
*$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$: &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
*$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items()$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
В алгоритме будут использоваться структуры, описанные в [http://neerc.ifmo.ru/wiki/index.php?title=LR(k)-%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8#.D0.A3.D0.BF.D1.80.D0.B0.D0.B2.D0.BB.D1.8F.D1.8E.D1.89.D0.B0.D1.8F_.D0.BF.D1.80.D0.BE.D0.B3.D1.80.D0.B0.D0.BC.D0.BC.D0.B0_.D0.B0.D0.BD.D0.B0.D0.BB.D0.B8.D0.B7.D0.B0.D1.82.D0.BE.D1.80.D0.B0 конспекте про LL(k) грамматики]&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблицы &amp;lt;tex&amp;gt;ACTION&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;GOTO&amp;lt;/tex&amp;gt; канонического &amp;lt;tex&amp;gt;LR&amp;lt;/tex&amp;gt;-анализа&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(G'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(G') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(ACTION,&amp;lt;/tex&amp;gt; '''Error'''&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;GOTO(I_i,a) = I_j&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Shift'''(&amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Reduce'''(&amp;lt;tex&amp;gt;A  \to a&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,\char36] = &amp;lt;/tex&amp;gt; '''Accept'''&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;GOTO(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;GOTO[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;left&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot;| Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; |$GOTO$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$c$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$d$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$\char36$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$S$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$C$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$0$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px;text-align:center&amp;quot;| '''Accept'''&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$3$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$4$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$6$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$7$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
* [[LR(k)-грамматики]]&lt;br /&gt;
* [[LR(0)-разбор]]&lt;br /&gt;
* [[SLR(1)-разбор]]&lt;br /&gt;
* [[LALR-разбор]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;br /&gt;
* [http://window.edu.ru/resource/974/69974/files/lang_trans.pdf Б.К.Мартыненко. Языки и трансляции. Стр. 198-223]&lt;br /&gt;
* [http://gas-teach.narod.ru/au/tfl/tfl13.pdf Лекции по теории формальных языков, LR(0)-, SLR(1)-, LR(1)- и LALR(1)-анализ ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49447</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49447"/>
				<updated>2015-09-20T12:34:39Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, при котором SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим состояние $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с ситуацией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' ситуации, а число $1$ в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$, и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх: либо $\gamma=\delta\alpha$, либо $a$ является первым символом $w$, либо$w=\varepsilon$ и $a=\char36$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\varepsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества ситуаций $items$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Item[] closure(Item[] $I$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      Item[] $J$ = $I$   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in G'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      $J$.add($[B\rightarrow\cdot\gamma,b]$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' $J$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Item[] goto(Item[] $I$, $X$):&lt;br /&gt;
      Item[] $J=\varnothing$&lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          $J$.add($[A\rightarrow\alpha X\cdot\beta, a]$)&lt;br /&gt;
      '''return''' $closure(J)$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Item[][] items($G'$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      Item[][] $C = \{closure({S'\rightarrow\cdot S,\char36})\}$&lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' Item[] $I\subset C$&lt;br /&gt;
              '''for''' $X \in symbols(G')$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;//по всем символам грамматики&amp;lt;/font&amp;gt;&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ and $goto(I,X)\not\subset C$&lt;br /&gt;
                      $C$.add($goto(I,X)$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' $C$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC|d$&lt;br /&gt;
Запустим процедуру $items(G')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\varepsilon;B=S;\beta=\varepsilon;a=\char36$.&lt;br /&gt;
&lt;br /&gt;
Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $[C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$ и $[C\rightarrow\cdot d, d]$. &lt;br /&gt;
Поскольку ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure()$ завершает свою работу.&lt;br /&gt;
&lt;br /&gt;
Начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и переходы между ними]]&lt;br /&gt;
*$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items()$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $G'$:&lt;br /&gt;
&lt;br /&gt;
#При $X=S$:&lt;br /&gt;
#:$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
#:Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом,  &lt;br /&gt;
#:*$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
#При $X=C$:&lt;br /&gt;
#:$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
#:*$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
#При $X=c$:&lt;br /&gt;
#:$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
#:*$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
#При $X=d$:&lt;br /&gt;
#:$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
#:*$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
*$$I_5=goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
$$I_6=goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
*$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
&lt;br /&gt;
'''NB:''' Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
&lt;br /&gt;
*$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
*$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$: &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
*$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items()$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
В алгоритме будут использоваться структуры, описанные в [http://neerc.ifmo.ru/wiki/index.php?title=LR(k)-%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8#.D0.A3.D0.BF.D1.80.D0.B0.D0.B2.D0.BB.D1.8F.D1.8E.D1.89.D0.B0.D1.8F_.D0.BF.D1.80.D0.BE.D0.B3.D1.80.D0.B0.D0.BC.D0.BC.D0.B0_.D0.B0.D0.BD.D0.B0.D0.BB.D0.B8.D0.B7.D0.B0.D1.82.D0.BE.D1.80.D0.B0 конспекте про LL(k) грамматики]&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблицы &amp;lt;tex&amp;gt;ACTION&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;GOTO&amp;lt;/tex&amp;gt; канонического &amp;lt;tex&amp;gt;LR&amp;lt;/tex&amp;gt;-анализа&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(G'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(G') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(ACTION,&amp;lt;/tex&amp;gt; '''Error'''&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;GOTO(I_i,a) = I_j&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Shift'''(&amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Reduce'''(&amp;lt;tex&amp;gt;A  \to a&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,\char36] = &amp;lt;/tex&amp;gt; '''Accept'''&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;GOTO(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;GOTO[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;left&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot;| Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; |$GOTO$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$c$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$d$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$\char36$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$S$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$C$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$0$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px;text-align:center&amp;quot;| '''Accept'''&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$3$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$4$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$6$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$7$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
* [[LR(k)-грамматики]]&lt;br /&gt;
* [[LR(0)-разбор]]&lt;br /&gt;
* [[SLR(1)-разбор]]&lt;br /&gt;
* [[LALR-разбор]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;br /&gt;
* [http://window.edu.ru/resource/974/69974/files/lang_trans.pdf Б.К.Мартыненко. Языки и трансляции. Стр. 198-223]&lt;br /&gt;
* [http://gas-teach.narod.ru/au/tfl/tfl13.pdf Лекции по теории формальных языков, LR(0)-, SLR(1)-, LR(1)- и LALR(1)-анализ ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49446</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49446"/>
				<updated>2015-09-20T12:31:08Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: /* Отличия от SLR-разбора */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, при котором SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим состояние $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с ситуацией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' ситуации, а число $1$ в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$, и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх: либо $\gamma=\delta\alpha$, либо $a$ является первым символом $w$, либо$w=\varepsilon$ и $a=\char36$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\varepsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества ситуаций $items$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Item[] closure(Item[] $I$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      Item[] $J$ = $I$   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in G'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      $J$.add($[B\rightarrow\cdot\gamma,b]$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' $J$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Item[] goto(Item[] $I$, $X$):&lt;br /&gt;
      Item[] $J=\varnothing$&lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          $J$.add($[A\rightarrow\alpha X\cdot\beta, a]$)&lt;br /&gt;
      '''return''' $closure(J)$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Item[][] items($G'$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      Item[][] $C = \{closure({S'\rightarrow\cdot S,\char36})\}$&lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' Item[] $I\subset C$&lt;br /&gt;
              '''for''' $X \in symbols(G')$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;//по всем символам грамматики&amp;lt;/font&amp;gt;&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ and $goto(I,X)\not\subset C$&lt;br /&gt;
                      $C$.add($goto(I,X)$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' $C$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC|d$&lt;br /&gt;
Запустим процедуру $items(G')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\varepsilon;B=S;\beta=\varepsilon;a=\char36$.&lt;br /&gt;
&lt;br /&gt;
Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $[C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$ и $[C\rightarrow\cdot d, d]$. &lt;br /&gt;
Поскольку ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure()$ завершает свою работу.&lt;br /&gt;
&lt;br /&gt;
Начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и их переходы]]&lt;br /&gt;
*$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items()$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $G'$:&lt;br /&gt;
&lt;br /&gt;
#При $X=S$:&lt;br /&gt;
#:$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
#:Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом,  &lt;br /&gt;
#:*$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
#При $X=C$:&lt;br /&gt;
#:$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
#:*$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
#При $X=c$:&lt;br /&gt;
#:$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
#:*$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
#При $X=d$:&lt;br /&gt;
#:$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
#:*$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
*$$I_5=goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
$$I_6=goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
*$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
&lt;br /&gt;
'''NB:''' Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
&lt;br /&gt;
*$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
*$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$: &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
*$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items()$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
В алгоритме будут использоваться структуры, описанные в [http://neerc.ifmo.ru/wiki/index.php?title=LR(k)-%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8#.D0.A3.D0.BF.D1.80.D0.B0.D0.B2.D0.BB.D1.8F.D1.8E.D1.89.D0.B0.D1.8F_.D0.BF.D1.80.D0.BE.D0.B3.D1.80.D0.B0.D0.BC.D0.BC.D0.B0_.D0.B0.D0.BD.D0.B0.D0.BB.D0.B8.D0.B7.D0.B0.D1.82.D0.BE.D1.80.D0.B0 конспекте про LL(k) грамматики]&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблицы &amp;lt;tex&amp;gt;ACTION&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;GOTO&amp;lt;/tex&amp;gt; канонического &amp;lt;tex&amp;gt;LR&amp;lt;/tex&amp;gt;-анализа&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(G'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(G') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(ACTION,&amp;lt;/tex&amp;gt; '''Error'''&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;GOTO(I_i,a) = I_j&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Shift'''(&amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Reduce'''(&amp;lt;tex&amp;gt;A  \to a&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,\char36] = &amp;lt;/tex&amp;gt; '''Accept'''&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;GOTO(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;GOTO[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;left&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot;| Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; |$GOTO$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$c$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$d$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$\char36$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$S$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$C$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$0$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px;text-align:center&amp;quot;| '''Accept'''&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$3$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$4$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$6$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$7$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
* [[LR(k)-грамматики]]&lt;br /&gt;
* [[LR(0)-разбор]]&lt;br /&gt;
* [[SLR(1)-разбор]]&lt;br /&gt;
* [[LALR-разбор]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;br /&gt;
* [http://window.edu.ru/resource/974/69974/files/lang_trans.pdf Б.К.Мартыненко. Языки и трансляции. Стр. 198-223]&lt;br /&gt;
* [http://gas-teach.narod.ru/au/tfl/tfl13.pdf Лекции по теории формальных языков, LR(0)-, SLR(1)-, LR(1)- и LALR(1)-анализ ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49442</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49442"/>
				<updated>2015-09-20T10:40:31Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример ситуации, в которой SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим ситуацию $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с продукцией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' ситуации, а число $1$ в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$, и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх: либо $\gamma=\delta\alpha$, либо $a$ является первым символом $w$, либо$w=\varepsilon$ и $a=\char36$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\varepsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества ситуаций $items$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Item[] closure(Item[] I):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      Item[] J = I   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in G'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      J.add($[B\rightarrow\cdot\gamma,b]$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' J&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Item[] goto(Item[] I, X):&lt;br /&gt;
      Item[] J $=\varnothing$&lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          J.add($[A\rightarrow\alpha X\cdot\beta, a]$)&lt;br /&gt;
      '''return''' $closure(J)$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Item[][] items($G'$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      Item[][] $C = \{closure({S'\rightarrow\cdot S,\char36})\}$&lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' Item[] $I\subset C$&lt;br /&gt;
              '''for''' $X \in symbols(G')$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;//по всем символам грамматики&amp;lt;/font&amp;gt;&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ and $goto(I,X)\not\subset C$&lt;br /&gt;
                      C.add($goto(I,X)$)&lt;br /&gt;
                      changed = ''true''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' C&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC|d$&lt;br /&gt;
Запустим процедуру $items(G')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\varepsilon;B=S;\beta=\varepsilon;a=\char36$.&lt;br /&gt;
&lt;br /&gt;
Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $[C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$ и $[C\rightarrow\cdot d, d]$. &lt;br /&gt;
Поскольку ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure()$ завершает свою работу.&lt;br /&gt;
&lt;br /&gt;
Начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и их переходы]]&lt;br /&gt;
*$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items()$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $G'$:&lt;br /&gt;
&lt;br /&gt;
#При $X=S$:&lt;br /&gt;
#:$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
#:Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом,  &lt;br /&gt;
#:*$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
#При $X=C$:&lt;br /&gt;
#:$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
#:*$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
#При $X=c$:&lt;br /&gt;
#:$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
#:*$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
#При $X=d$:&lt;br /&gt;
#:$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
#:*$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
*$$I_5=goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
$$I_6=goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
*$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
&lt;br /&gt;
'''NB:''' Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
&lt;br /&gt;
*$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
*$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$: &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
*$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items()$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
В алгоритме будут использоваться структуры, описанные в [http://neerc.ifmo.ru/wiki/index.php?title=LR(k)-%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8#.D0.A3.D0.BF.D1.80.D0.B0.D0.B2.D0.BB.D1.8F.D1.8E.D1.89.D0.B0.D1.8F_.D0.BF.D1.80.D0.BE.D0.B3.D1.80.D0.B0.D0.BC.D0.BC.D0.B0_.D0.B0.D0.BD.D0.B0.D0.BB.D0.B8.D0.B7.D0.B0.D1.82.D0.BE.D1.80.D0.B0 конспекте про LL(k) грамматики]&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблицы &amp;lt;tex&amp;gt;ACTION&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;GOTO&amp;lt;/tex&amp;gt; канонического &amp;lt;tex&amp;gt;LR&amp;lt;/tex&amp;gt;-анализа&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(G'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(G') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(ACTION,&amp;lt;/tex&amp;gt; '''Error'''&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;GOTO(I_i,a) = I_j&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Shift'''(&amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; '''Reduce'''(&amp;lt;tex&amp;gt;A  \to a&amp;lt;/tex&amp;gt;)&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,\char36] = &amp;lt;/tex&amp;gt; '''Accept'''&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;GOTO(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;GOTO[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;left&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot;| Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:#EEE;text-align:center&amp;quot; |$GOTO$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$c$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$d$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$\char36$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$S$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$C$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$0$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$1$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px;text-align:center&amp;quot;| '''Accept'''&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$2$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$3$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(4)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$4$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$5$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(1)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$6$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(6)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$s(7)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$7$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(3)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$8$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$9$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px;text-align:center&amp;quot;|$r(2)$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 20px&amp;quot;|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br clear=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
* [[LR(k)-грамматики]]&lt;br /&gt;
* [[LR(0)-разбор]]&lt;br /&gt;
* [[SLR(1)-разбор]]&lt;br /&gt;
* [[LALR-разбор]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;br /&gt;
* [http://window.edu.ru/resource/974/69974/files/lang_trans.pdf Б.К.Мартыненко. Языки и трансляции. Стр. 198-223]&lt;br /&gt;
* [http://gas-teach.narod.ru/au/tfl/tfl13.pdf Лекции по теории формальных языков, LR(0)-, SLR(1)-, LR(1)- и LALR(1)-анализ ]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49369</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49369"/>
				<updated>2015-09-14T19:30:10Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример ситуации, в которой SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим ситуацию $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с продукцией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' (англ. ''lookahead'') ситуации, а число 1 в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$ и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх: либо $\gamma=\delta\alpha$, либо $a$ является первым символом $w$, либо$w=\varepsilon$ и $a=\char36$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\varepsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества ситуаций $items$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Item[] closure(Item[] I):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      Item[] J = I   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false'''&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in G'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      J.add($[B\rightarrow\cdot\gamma,b]$)&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' J&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Item[] goto(Item[] I, X):&lt;br /&gt;
      Item[] J=$\varnothing$&lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          J.add($[A\rightarrow\alpha X\cdot\beta, a]$)&lt;br /&gt;
      '''return''' $closure(J)$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Item[][] items($G'$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      Item[][] $C$ = $\{closure({S'\rightarrow\cdot S,\char36})\}$&lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false'''&lt;br /&gt;
          '''for''' Item[] $I\subset C$&lt;br /&gt;
              '''for''' $X \in symbols(G')$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;//по всем символам грамматики&amp;lt;/font&amp;gt;&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ and $goto(I,X)\not\subset C$&lt;br /&gt;
                      C.add($goto(I,X)$)&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' C&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC|d$&lt;br /&gt;
Запустим процедуру $items(G')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\varepsilon;B=S;\beta=\varepsilon;a=\char36$. Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$, и $C\rightarrow\cdot d, d]$. Т.к. ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure$ завершает свою работу и начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и их переходы]]&lt;br /&gt;
$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $G'$:&lt;br /&gt;
&lt;br /&gt;
При $X=S$:&lt;br /&gt;
$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом, &lt;br /&gt;
$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
При $X=C$:&lt;br /&gt;
$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
При $X=c$:&lt;br /&gt;
$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
При $X=d$:&lt;br /&gt;
$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
$$I_5 = goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
$$I_6 = goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
Продолжим:&lt;br /&gt;
$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$ &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблица канонического &amp;lt;tex&amp;gt;LR&amp;lt;/tex&amp;gt;-анализа с функциями &amp;lt;tex&amp;gt;ACTION&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;goto&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(G'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(G') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(ACTION,&amp;lt;/tex&amp;gt;&amp;quot;ошибка&amp;quot;&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; &amp;quot;перенос &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;&amp;quot;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; &amp;amp;&amp;amp; &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; &amp;quot;свертка &amp;lt;tex&amp;gt;A\rightarrow a&amp;lt;/tex&amp;gt;&amp;quot;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,\char36] = &amp;lt;/tex&amp;gt; &amp;quot;принятие&amp;quot;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;goto(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;goto[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;center&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; | Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot;  | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot;  |$goto$&lt;br /&gt;
|-&lt;br /&gt;
|$c$&lt;br /&gt;
|$d$&lt;br /&gt;
|$\char36$&lt;br /&gt;
|$S$&lt;br /&gt;
|$C$&lt;br /&gt;
|-&lt;br /&gt;
|$0$&lt;br /&gt;
|$s3$&lt;br /&gt;
|$s4$&lt;br /&gt;
|&lt;br /&gt;
|$1$&lt;br /&gt;
|$2$&lt;br /&gt;
|-&lt;br /&gt;
|$1$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
| style=&amp;quot;font-style:italic;color:green;&amp;quot; | ok&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$2$&lt;br /&gt;
|$s6$&lt;br /&gt;
|$s7$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$5$&lt;br /&gt;
|-&lt;br /&gt;
|$3$&lt;br /&gt;
|$s3$&lt;br /&gt;
|$s4$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$8$&lt;br /&gt;
|-&lt;br /&gt;
|$4$&lt;br /&gt;
|$r1$&lt;br /&gt;
|$r3$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$5$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$r1$&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$6$&lt;br /&gt;
|$s6$&lt;br /&gt;
|$s7$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$9$&lt;br /&gt;
|-&lt;br /&gt;
|$7$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$r3$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$8$&lt;br /&gt;
|$r2$&lt;br /&gt;
|$r2$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$9$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$r2$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
* [[LR(k)-грамматики]]&lt;br /&gt;
* [[LR(0)-разбор]]&lt;br /&gt;
* [[SLR(1)-разбор]]&lt;br /&gt;
* [[LALR-разбор]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9C%D0%B5%D1%82%D0%BE%D0%B4%D1%8B_%D1%82%D1%80%D0%B0%D0%BD%D1%81%D0%BB%D1%8F%D1%86%D0%B8%D0%B8&amp;diff=49368</id>
		<title>Методы трансляции</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9C%D0%B5%D1%82%D0%BE%D0%B4%D1%8B_%D1%82%D1%80%D0%B0%D0%BD%D1%81%D0%BB%D1%8F%D1%86%D0%B8%D0%B8&amp;diff=49368"/>
				<updated>2015-09-14T19:29:43Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: /* Восходящий разбор */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Нисходящий разбор ==&lt;br /&gt;
* [[LL(k)-грамматики, множества FIRST и FOLLOW]]&lt;br /&gt;
* [[Построение FIRST и FOLLOW]]&lt;br /&gt;
* [[Предиктивный синтаксический анализ]]&lt;br /&gt;
* [[Атрибутные транслирующие грамматики]]&lt;br /&gt;
== Восходящий разбор ==&lt;br /&gt;
* [[LR(k)-грамматики]]&lt;br /&gt;
* [[LR(0)-разбор]]&lt;br /&gt;
* [[SLR(1)-разбор]]&lt;br /&gt;
* [[LR(1)-разбор]]&lt;br /&gt;
* [[LALR-разбор]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Методы трансляции]]&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49367</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49367"/>
				<updated>2015-09-14T19:25:48Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-анализ|LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример ситуации, в которой SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим ситуацию $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с продукцией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' (англ. ''lookahead'') ситуации, а число 1 в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$ и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх: либо $\gamma=\delta\alpha$, либо $a$ является первым символом $w$, либо$w=\varepsilon$ и $a=\char36$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\varepsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества ситуаций $items$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Item[] closure(Item[] I):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      Item[] J = I   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false'''&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in G'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      J.add($[B\rightarrow\cdot\gamma,b]$)&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' J&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Item[] goto(Item[] I, X):&lt;br /&gt;
      Item[] J=$\varnothing$&lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          J.add($[A\rightarrow\alpha X\cdot\beta, a]$)&lt;br /&gt;
      '''return''' $closure(J)$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Item[][] items($G'$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      Item[][] $C$ = $\{closure({S'\rightarrow\cdot S,\char36})\}$&lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false'''&lt;br /&gt;
          '''for''' Item[] $I\subset C$&lt;br /&gt;
              '''for''' $X \in symbols(G')$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;//по всем символам грамматики&amp;lt;/font&amp;gt;&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ and $goto(I,X)\not\subset C$&lt;br /&gt;
                      C.add($goto(I,X)$)&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' C&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC|d$&lt;br /&gt;
Запустим процедуру $items(G')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\varepsilon;B=S;\beta=\varepsilon;a=\char36$. Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$, и $C\rightarrow\cdot d, d]$. Т.к. ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure$ завершает свою работу и начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и их переходы]]&lt;br /&gt;
$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $G'$:&lt;br /&gt;
&lt;br /&gt;
При $X=S$:&lt;br /&gt;
$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом, &lt;br /&gt;
$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
При $X=C$:&lt;br /&gt;
$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
При $X=c$:&lt;br /&gt;
$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
При $X=d$:&lt;br /&gt;
$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
$$I_5 = goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
$$I_6 = goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
Продолжим:&lt;br /&gt;
$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$ &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблица канонического &amp;lt;tex&amp;gt;LR&amp;lt;/tex&amp;gt;-анализа с функциями &amp;lt;tex&amp;gt;ACTION&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;goto&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(G'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(G') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(ACTION,&amp;lt;/tex&amp;gt;&amp;quot;ошибка&amp;quot;&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; &amp;quot;перенос &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;&amp;quot;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; &amp;amp;&amp;amp; &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; &amp;quot;свертка &amp;lt;tex&amp;gt;A\rightarrow a&amp;lt;/tex&amp;gt;&amp;quot;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,\char36] = &amp;lt;/tex&amp;gt; &amp;quot;принятие&amp;quot;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;goto(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;goto[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;center&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; | Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot;  | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot;  |$goto$&lt;br /&gt;
|-&lt;br /&gt;
|$c$&lt;br /&gt;
|$d$&lt;br /&gt;
|$\char36$&lt;br /&gt;
|$S$&lt;br /&gt;
|$C$&lt;br /&gt;
|-&lt;br /&gt;
|$0$&lt;br /&gt;
|$s3$&lt;br /&gt;
|$s4$&lt;br /&gt;
|&lt;br /&gt;
|$1$&lt;br /&gt;
|$2$&lt;br /&gt;
|-&lt;br /&gt;
|$1$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
| style=&amp;quot;font-style:italic;color:green;&amp;quot; | ok&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$2$&lt;br /&gt;
|$s6$&lt;br /&gt;
|$s7$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$5$&lt;br /&gt;
|-&lt;br /&gt;
|$3$&lt;br /&gt;
|$s3$&lt;br /&gt;
|$s4$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$8$&lt;br /&gt;
|-&lt;br /&gt;
|$4$&lt;br /&gt;
|$r1$&lt;br /&gt;
|$r3$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$5$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$r1$&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$6$&lt;br /&gt;
|$s6$&lt;br /&gt;
|$s7$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$9$&lt;br /&gt;
|-&lt;br /&gt;
|$7$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$r3$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$8$&lt;br /&gt;
|$r2$&lt;br /&gt;
|$r2$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$9$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$r2$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Теория формальных языков]]&lt;br /&gt;
[[Категория: Контекстно-свободные грамматики]]&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49366</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49366"/>
				<updated>2015-09-14T19:22:22Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-анализ|LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример ситуации, в которой SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим ситуацию $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с продукцией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' (англ. ''lookahead'') ситуации, а число 1 в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$ и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх: либо $\gamma=\delta\alpha$, либо $a$ является первым символом $w$, либо$w=\varepsilon$ и $a=\char36$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\varepsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества ситуаций $items$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Item[] closure(Item[] I):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      Item[] J = I   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false'''&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in G'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      J.add($[B\rightarrow\cdot\gamma,b]$)&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' J&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Item[] goto(Item[] I, X):&lt;br /&gt;
      Item[] J=$\varnothing$&lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          J.add($[A\rightarrow\alpha X\cdot\beta, a]$)&lt;br /&gt;
      '''return''' $closure(J)$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Item[][] items($G'$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      Item[][] $C$ = $\{closure({S'\rightarrow\cdot S,\char36})\}$&lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false'''&lt;br /&gt;
          '''for''' Item[] $I\subset C$&lt;br /&gt;
              '''for''' $X \in symbols(G')$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;//по всем символам грамматики&amp;lt;/font&amp;gt;&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ and $goto(I,X)\not\subset C$&lt;br /&gt;
                      C.add($goto(I,X)$)&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' C&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC|d$&lt;br /&gt;
Запустим процедуру $items(G')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\varepsilon;B=S;\beta=\varepsilon;a=\char36$. Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$, и $C\rightarrow\cdot d, d]$. Т.к. ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure$ завершает свою работу и начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и их переходы]]&lt;br /&gt;
$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $G'$:&lt;br /&gt;
&lt;br /&gt;
При $X=S$:&lt;br /&gt;
$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом, &lt;br /&gt;
$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
При $X=C$:&lt;br /&gt;
$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
При $X=c$:&lt;br /&gt;
$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
При $X=d$:&lt;br /&gt;
$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
$$I_5 = goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
$$I_6 = goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
Продолжим:&lt;br /&gt;
$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$ &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблица канонического &amp;lt;tex&amp;gt;LR&amp;lt;/tex&amp;gt;-анализа с функциями &amp;lt;tex&amp;gt;ACTION&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;goto&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(G'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(G') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(ACTION,&amp;lt;/tex&amp;gt;&amp;quot;ошибка&amp;quot;&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; &amp;quot;перенос &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;&amp;quot;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; &amp;amp;&amp;amp; &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; &amp;quot;свертка &amp;lt;tex&amp;gt;A\rightarrow a&amp;lt;/tex&amp;gt;&amp;quot;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,\char36] = &amp;lt;/tex&amp;gt; &amp;quot;принятие&amp;quot;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;goto(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;goto[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;center&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; | Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot;  | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot;  |$goto$&lt;br /&gt;
|-&lt;br /&gt;
|$c$&lt;br /&gt;
|$d$&lt;br /&gt;
|$\char36$&lt;br /&gt;
|$S$&lt;br /&gt;
|$C$&lt;br /&gt;
|-&lt;br /&gt;
|$0$&lt;br /&gt;
|$s3$&lt;br /&gt;
|$s4$&lt;br /&gt;
|&lt;br /&gt;
|$1$&lt;br /&gt;
|$2$&lt;br /&gt;
|-&lt;br /&gt;
|$1$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
| style=&amp;quot;font-style:italic;color:green;&amp;quot; | ok&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$2$&lt;br /&gt;
|$s6$&lt;br /&gt;
|$s7$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$5$&lt;br /&gt;
|-&lt;br /&gt;
|$3$&lt;br /&gt;
|$s3$&lt;br /&gt;
|$s4$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$8$&lt;br /&gt;
|-&lt;br /&gt;
|$4$&lt;br /&gt;
|$r1$&lt;br /&gt;
|$r3$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$5$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$r1$&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$6$&lt;br /&gt;
|$s6$&lt;br /&gt;
|$s7$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$9$&lt;br /&gt;
|-&lt;br /&gt;
|$7$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$r3$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$8$&lt;br /&gt;
|$r2$&lt;br /&gt;
|$r2$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$9$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$r2$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49365</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49365"/>
				<updated>2015-09-14T19:15:04Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-анализ|LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример ситуации, в которой SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим ситуацию $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с продукцией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' (англ. ''lookahead'') ситуации, а число 1 в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$ и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх: либо $\gamma=\delta\alpha$, либо $a$ является первым символом $w$, либо$w=\varepsilon$ и $a=\char36$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\varepsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества ситуаций $items$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Item&amp;gt; closure(Set&amp;lt;Item&amp;gt; I):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      Set&amp;lt;Item&amp;gt; $J$=$I$   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false'''&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in G'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      J.add($[B\rightarrow\cdot\gamma,b]$)&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' J&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Item&amp;gt; goto(Set&amp;lt;Item&amp;gt; I, X):&lt;br /&gt;
      Set&amp;lt;Item&amp;gt; $J$=$\varnothing$&lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          J.add($[A\rightarrow\alpha X\cdot\beta, a]$)&lt;br /&gt;
      '''return''' $closure(J)$&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Set&amp;lt;Item&amp;gt;&amp;gt; items($G'$):&lt;br /&gt;
      '''bool''' changed&lt;br /&gt;
      Set&amp;lt;Set&amp;lt;Item&amp;gt;&amp;gt; $C$ = $\{closure({S'\rightarrow\cdot S,\char36})\}$&lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false'''&lt;br /&gt;
          '''for''' Set&amp;lt;Item&amp;gt; $I\subset C$&lt;br /&gt;
              '''for''' $X \in symbols(G')$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;//по всем символам грамматики&amp;lt;/font&amp;gt;&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ and $goto(I,X)\not\subset C$&lt;br /&gt;
                      C.add($goto(I,X)$)&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' not changed&lt;br /&gt;
      '''return''' C&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC|d$&lt;br /&gt;
Запустим процедуру $items(G')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\varepsilon;B=S;\beta=\varepsilon;a=\char36$. Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$, и $C\rightarrow\cdot d, d]$. Т.к. ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure$ завершает свою работу и начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и их переходы]]&lt;br /&gt;
$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $G'$:&lt;br /&gt;
&lt;br /&gt;
При $X=S$:&lt;br /&gt;
$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом, &lt;br /&gt;
$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
При $X=C$:&lt;br /&gt;
$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
При $X=c$:&lt;br /&gt;
$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
При $X=d$:&lt;br /&gt;
$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
$$I_5 = goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
$$I_6 = goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
Продолжим:&lt;br /&gt;
$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$ &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблица канонического &amp;lt;tex&amp;gt;LR&amp;lt;/tex&amp;gt;-анализа с функциями &amp;lt;tex&amp;gt;ACTION&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;goto&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(G'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(G') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(ACTION,&amp;lt;/tex&amp;gt;&amp;quot;ошибка&amp;quot;&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; &amp;quot;перенос &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;&amp;quot;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; &amp;amp;&amp;amp; &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; &amp;quot;свертка &amp;lt;tex&amp;gt;A\rightarrow a&amp;lt;/tex&amp;gt;&amp;quot;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,\char36] = &amp;lt;/tex&amp;gt; &amp;quot;принятие&amp;quot;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;goto(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;goto[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;center&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; | Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot;  | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot;  |$goto$&lt;br /&gt;
|-&lt;br /&gt;
|$c$&lt;br /&gt;
|$d$&lt;br /&gt;
|$\char36$&lt;br /&gt;
|$S$&lt;br /&gt;
|$C$&lt;br /&gt;
|-&lt;br /&gt;
|$0$&lt;br /&gt;
|$s3$&lt;br /&gt;
|$s4$&lt;br /&gt;
|&lt;br /&gt;
|$1$&lt;br /&gt;
|$2$&lt;br /&gt;
|-&lt;br /&gt;
|$1$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
| style=&amp;quot;font-style:italic;color:green;&amp;quot; | ok&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$2$&lt;br /&gt;
|$s6$&lt;br /&gt;
|$s7$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$5$&lt;br /&gt;
|-&lt;br /&gt;
|$3$&lt;br /&gt;
|$s3$&lt;br /&gt;
|$s4$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$8$&lt;br /&gt;
|-&lt;br /&gt;
|$4$&lt;br /&gt;
|$r1$&lt;br /&gt;
|$r3$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$5$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$r1$&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$6$&lt;br /&gt;
|$s6$&lt;br /&gt;
|$s7$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$9$&lt;br /&gt;
|-&lt;br /&gt;
|$7$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$r3$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$8$&lt;br /&gt;
|$r2$&lt;br /&gt;
|$r2$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$9$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$r2$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49364</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49364"/>
				<updated>2015-09-14T19:13:39Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-анализ|LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример ситуации, в которой SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим ситуацию $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с продукцией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' (англ. ''lookahead'') ситуации, а число 1 в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$ и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх: либо $\gamma=\delta\alpha$, либо $a$ является первым символом $w$, либо$w=\varepsilon$ и $a=\char36$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\varepsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества ситуаций $items$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Item&amp;gt; closure(Set&amp;lt;Item&amp;gt; I):&lt;br /&gt;
      '''bool''' changed;&lt;br /&gt;
      Set&amp;lt;Item&amp;gt; $J$=$I$;   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false''';&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in G'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      J.add($[B\rightarrow\cdot\gamma,b]$);&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' not changed;&lt;br /&gt;
      '''return''' J;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Item&amp;gt; goto(Set&amp;lt;Item&amp;gt; I, X):&lt;br /&gt;
      Set&amp;lt;Item&amp;gt; $J$=$\varnothing$;   &lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          J.add($[A\rightarrow\alpha X\cdot\beta, a]$);&lt;br /&gt;
      '''return''' $closure(J)$;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Set&amp;lt;Item&amp;gt;&amp;gt; items($G'$):&lt;br /&gt;
      '''bool''' changed;&lt;br /&gt;
      Set&amp;lt;Set&amp;lt;Item&amp;gt;&amp;gt; $C$ = $\{closure({S'\rightarrow\cdot S,\char36})\}$;   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false''';&lt;br /&gt;
          '''for''' Set&amp;lt;Item&amp;gt; $I\subset C$&lt;br /&gt;
              '''for''' $X \in symbols(G')$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;//по всем символам грамматики&amp;lt;/font&amp;gt;&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ and $goto(I,X)\not\subset C$&lt;br /&gt;
                      C.add($goto(I,X)$);&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' not changed;&lt;br /&gt;
      '''return''' C;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC|d$&lt;br /&gt;
Запустим процедуру $items(G')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\varepsilon;B=S;\beta=\varepsilon;a=\char36$. Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$, и $C\rightarrow\cdot d, d]$. Т.к. ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure$ завершает свою работу и начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и их переходы]]&lt;br /&gt;
$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $G'$:&lt;br /&gt;
&lt;br /&gt;
При $X=S$:&lt;br /&gt;
$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом, &lt;br /&gt;
$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
При $X=C$:&lt;br /&gt;
$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
При $X=c$:&lt;br /&gt;
$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
При $X=d$:&lt;br /&gt;
$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
$$I_5 = goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
$$I_6 = goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
Продолжим:&lt;br /&gt;
$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$ &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблица канонического &amp;lt;tex&amp;gt;LR&amp;lt;/tex&amp;gt;-анализа с функциями &amp;lt;tex&amp;gt;ACTION&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;goto&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(G'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(G') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(ACTION,&amp;lt;/tex&amp;gt;&amp;quot;ошибка&amp;quot;&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; &amp;quot;перенос &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;&amp;quot;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; &amp;amp;&amp;amp; &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; &amp;quot;свертка &amp;lt;tex&amp;gt;A\rightarrow a&amp;lt;/tex&amp;gt;&amp;quot;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,\char36] = &amp;lt;/tex&amp;gt; &amp;quot;принятие&amp;quot;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;goto(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;goto[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;center&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; | Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot;  | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot;  |$goto$&lt;br /&gt;
|-&lt;br /&gt;
|$c$&lt;br /&gt;
|$d$&lt;br /&gt;
|$\char36$&lt;br /&gt;
|$S$&lt;br /&gt;
|$C$&lt;br /&gt;
|-&lt;br /&gt;
|$0$&lt;br /&gt;
|$s3$&lt;br /&gt;
|$s4$&lt;br /&gt;
|&lt;br /&gt;
|$1$&lt;br /&gt;
|$2$&lt;br /&gt;
|-&lt;br /&gt;
|$1$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
| style=&amp;quot;font-style:italic;color:green;&amp;quot; | ok&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$2$&lt;br /&gt;
|$s6$&lt;br /&gt;
|$s7$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$5$&lt;br /&gt;
|-&lt;br /&gt;
|$3$&lt;br /&gt;
|$s3$&lt;br /&gt;
|$s4$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$8$&lt;br /&gt;
|-&lt;br /&gt;
|$4$&lt;br /&gt;
|$r1$&lt;br /&gt;
|$r3$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$5$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$r1$&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$6$&lt;br /&gt;
|$s6$&lt;br /&gt;
|$s7$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$9$&lt;br /&gt;
|-&lt;br /&gt;
|$7$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$r3$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$8$&lt;br /&gt;
|$r2$&lt;br /&gt;
|$r2$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$9$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$r2$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49363</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49363"/>
				<updated>2015-09-14T19:08:07Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-анализ|LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример ситуации, в которой SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим ситуацию $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с продукцией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' (англ. ''lookahead'') ситуации, а число 1 в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$ и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх:&lt;br /&gt;
* $\gamma=\delta\alpha$&lt;br /&gt;
* $a$ является первым символом $w$&lt;br /&gt;
* $w=\epsilon$ и $a=\char36$&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества ситуаций, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\epsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества ситуаций $items$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Item&amp;gt; closure(Set&amp;lt;Item&amp;gt; I):&lt;br /&gt;
      '''bool''' changed;&lt;br /&gt;
      Set&amp;lt;Item&amp;gt; $J$=$I$;   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false''';&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in G'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      J.add($[B\rightarrow\cdot\gamma,b]$);&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' not changed;&lt;br /&gt;
      '''return''' J;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Item&amp;gt; goto(Set&amp;lt;Item&amp;gt; I, X):&lt;br /&gt;
      Set&amp;lt;Item&amp;gt; $J$=$\varnothing$;   &lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          J.add($[A\rightarrow\alpha X\cdot\beta, a]$);&lt;br /&gt;
      '''return''' $closure(J)$;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Set&amp;lt;Item&amp;gt;&amp;gt; items($G'$):&lt;br /&gt;
      '''bool''' changed;&lt;br /&gt;
      Set&amp;lt;Set&amp;lt;Item&amp;gt;&amp;gt; $C$ = $\{closure({S'\rightarrow\cdot S,\char36})\}$;   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false''';&lt;br /&gt;
          '''for''' Set&amp;lt;Item&amp;gt; $I\subset C$&lt;br /&gt;
              '''for''' $X \in symbols(G')$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;//по всем символам грамматики&amp;lt;/font&amp;gt;&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ and $goto(I,X)\not\subset C$&lt;br /&gt;
                      C.add($goto(I,X)$);&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' not changed;&lt;br /&gt;
      '''return''' C;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC|d$&lt;br /&gt;
Запустим процедуру $items(G')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\epsilon;B=S;\beta=\epsilon;a=\char36$. Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$, и $C\rightarrow\cdot d, d]$. Т.к. ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure$ завершает свою работу и начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и их переходы]]&lt;br /&gt;
$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $G'$:&lt;br /&gt;
&lt;br /&gt;
При $X=S$:&lt;br /&gt;
$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом, &lt;br /&gt;
$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
При $X=C$:&lt;br /&gt;
$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
При $X=c$:&lt;br /&gt;
$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
При $X=d$:&lt;br /&gt;
$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
$$I_5 = goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
$$I_6 = goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
Продолжим:&lt;br /&gt;
$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$ &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблица канонического &amp;lt;tex&amp;gt;LR&amp;lt;/tex&amp;gt;-анализа с функциями &amp;lt;tex&amp;gt;ACTION&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;goto&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(G'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(G') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(ACTION,&amp;lt;/tex&amp;gt;&amp;quot;ошибка&amp;quot;&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; &amp;quot;перенос &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;&amp;quot;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; &amp;amp;&amp;amp; &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; &amp;quot;свертка &amp;lt;tex&amp;gt;A\rightarrow a&amp;lt;/tex&amp;gt;&amp;quot;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,\char36] = &amp;lt;/tex&amp;gt; &amp;quot;принятие&amp;quot;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;goto(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;goto[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия {{---}} это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;center&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; | Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot;  | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot;  |$goto$&lt;br /&gt;
|-&lt;br /&gt;
|$c$&lt;br /&gt;
|$d$&lt;br /&gt;
|$\char36$&lt;br /&gt;
|$S$&lt;br /&gt;
|$C$&lt;br /&gt;
|-&lt;br /&gt;
|$0$&lt;br /&gt;
|$s3$&lt;br /&gt;
|$s4$&lt;br /&gt;
|&lt;br /&gt;
|$1$&lt;br /&gt;
|$2$&lt;br /&gt;
|-&lt;br /&gt;
|$1$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
| style=&amp;quot;font-style:italic;color:green;&amp;quot; | ok&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$2$&lt;br /&gt;
|$s6$&lt;br /&gt;
|$s7$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$5$&lt;br /&gt;
|-&lt;br /&gt;
|$3$&lt;br /&gt;
|$s3$&lt;br /&gt;
|$s4$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$8$&lt;br /&gt;
|-&lt;br /&gt;
|$4$&lt;br /&gt;
|$r1$&lt;br /&gt;
|$r3$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$5$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$r1$&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$6$&lt;br /&gt;
|$s6$&lt;br /&gt;
|$s7$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$9$&lt;br /&gt;
|-&lt;br /&gt;
|$7$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$r3$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$8$&lt;br /&gt;
|$r2$&lt;br /&gt;
|$r2$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$9$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$r2$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49362</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49362"/>
				<updated>2015-09-14T19:00:26Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-анализ|LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример ситуации, в которой SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим ситуацию $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с продукцией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
Добавим в ситуацию второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' (англ. ''lookahead'') ситуации, а число 1 в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$ и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх:&lt;br /&gt;
* $\gamma=\delta\alpha$&lt;br /&gt;
* $a$ является первым символом $w$&lt;br /&gt;
* $w=\epsilon$ и $a=\char36$&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества пунктов, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных ситуаций должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим ситуацию вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве ситуаций, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\epsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества ситуаций $items$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Item&amp;gt; closure(Set&amp;lt;Item&amp;gt; I):&lt;br /&gt;
      '''bool''' changed;&lt;br /&gt;
      Set&amp;lt;Item&amp;gt; $J$=$I$;   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false''';&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in G'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      J.add($[B\rightarrow\cdot\gamma,b]$);&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' not changed;&lt;br /&gt;
      '''return''' J;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Item&amp;gt; goto(Set&amp;lt;Item&amp;gt; I, X):&lt;br /&gt;
      Set&amp;lt;Item&amp;gt; $J$=$\varnothing$;   &lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          J.add($[A\rightarrow\alpha X\cdot\beta, a]$);&lt;br /&gt;
      '''return''' $closure(J)$;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Set&amp;lt;Item&amp;gt;&amp;gt; items($G'$):&lt;br /&gt;
      '''bool''' changed;&lt;br /&gt;
      Set&amp;lt;Set&amp;lt;Item&amp;gt;&amp;gt; $C$ = $\{closure({S'\rightarrow\cdot S,\char36})\}$;   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false''';&lt;br /&gt;
          '''for''' Set&amp;lt;Item&amp;gt; $I\subset C$&lt;br /&gt;
              '''for''' $X \in symbols(G')$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;//по всем символам грамматики&amp;lt;/font&amp;gt;&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ and $goto(I,X)\not\subset C$&lt;br /&gt;
                      C.add($goto(I,X)$);&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' not changed;&lt;br /&gt;
      '''return''' C;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC|d$&lt;br /&gt;
Запустим процедуру $items(G')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\epsilon;B=S;\beta=\epsilon;a=\char36$. Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество ситуаций $[C\rightarrow\cdot C, c]$, $C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$, и $C\rightarrow\cdot d, d]$. Т.к. ни одна из новых ситуаций не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех ситуациях терминалы), то функция $closure$ завершает свою работу и начальное множество ситуаций в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества ситуаций и их переходы]]&lt;br /&gt;
$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $G'$:&lt;br /&gt;
&lt;br /&gt;
При $X=S$:&lt;br /&gt;
$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
Мы не добавили ни одной ситуации, т.к. точка является крайней справа. Таким образом, &lt;br /&gt;
$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
При $X=C$:&lt;br /&gt;
$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
При $X=c$:&lt;br /&gt;
$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
При $X=d$:&lt;br /&gt;
$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
$$I_5 = goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
$$I_6 = goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями ситуаций. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
Продолжим:&lt;br /&gt;
$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все ситуации имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$ &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества ситуаций не дают нам значений $goto$, процедура $items$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблица канонического &amp;lt;tex&amp;gt;LR&amp;lt;/tex&amp;gt;-анализа с функциями &amp;lt;tex&amp;gt;ACTION&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;goto&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(G'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(G') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических ситуаций для &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(ACTION,&amp;lt;/tex&amp;gt;&amp;quot;ошибка&amp;quot;&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; - терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; &amp;quot;перенос &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;&amp;quot;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; &amp;amp;&amp;amp; &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; &amp;quot;свертка &amp;lt;tex&amp;gt;A\rightarrow a&amp;lt;/tex&amp;gt;&amp;quot;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,\char36] = &amp;lt;/tex&amp;gt; &amp;quot;принятие&amp;quot;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;goto(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;goto[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия - это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;center&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; | Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot;  | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot;  |$goto$&lt;br /&gt;
|-&lt;br /&gt;
|$c$&lt;br /&gt;
|$d$&lt;br /&gt;
|$\char36$&lt;br /&gt;
|$S$&lt;br /&gt;
|$C$&lt;br /&gt;
|-&lt;br /&gt;
|$0$&lt;br /&gt;
|$s3$&lt;br /&gt;
|$s4$&lt;br /&gt;
|&lt;br /&gt;
|$1$&lt;br /&gt;
|$2$&lt;br /&gt;
|-&lt;br /&gt;
|$1$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
| style=&amp;quot;font-style:italic;color:green;&amp;quot; | ok&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$2$&lt;br /&gt;
|$s6$&lt;br /&gt;
|$s7$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$5$&lt;br /&gt;
|-&lt;br /&gt;
|$3$&lt;br /&gt;
|$s3$&lt;br /&gt;
|$s4$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$8$&lt;br /&gt;
|-&lt;br /&gt;
|$4$&lt;br /&gt;
|$r1$&lt;br /&gt;
|$r3$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$5$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$r1$&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$6$&lt;br /&gt;
|$s6$&lt;br /&gt;
|$s7$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$9$&lt;br /&gt;
|-&lt;br /&gt;
|$7$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$r3$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$8$&lt;br /&gt;
|$r2$&lt;br /&gt;
|$r2$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$9$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$r2$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49361</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49361"/>
				<updated>2015-09-14T18:57:51Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-анализ|LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример ситуации, в которой SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим ситуацию $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с продукцией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
Добавим в пункт второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' (англ. ''lookahead'') ситуации, а число 1 в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$ и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх:&lt;br /&gt;
* $\gamma=\delta\alpha$&lt;br /&gt;
* $a$ является первым символом $w$&lt;br /&gt;
* $w=\epsilon$ и $a=\char36$&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества пунктов, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных пунктов должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим пункт вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве пунктов, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\epsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества пунктов $items$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Item&amp;gt; closure(Set&amp;lt;Item&amp;gt; I):&lt;br /&gt;
      '''bool''' changed;&lt;br /&gt;
      Set&amp;lt;Item&amp;gt; $J$=$I$;   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false''';&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in G'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      J.add($[B\rightarrow\cdot\gamma,b]$);&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' not changed;&lt;br /&gt;
      '''return''' J;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Item&amp;gt; goto(Set&amp;lt;Item&amp;gt; I, X):&lt;br /&gt;
      Set&amp;lt;Item&amp;gt; $J$=$\varnothing$;   &lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          J.add($[A\rightarrow\alpha X\cdot\beta, a]$);&lt;br /&gt;
      '''return''' $closure(J)$;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Set&amp;lt;Item&amp;gt;&amp;gt; items($G'$):&lt;br /&gt;
      '''bool''' changed;&lt;br /&gt;
      Set&amp;lt;Set&amp;lt;Item&amp;gt;&amp;gt; $C$ = $\{closure({S'\rightarrow\cdot S,\char36})\}$;   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false''';&lt;br /&gt;
          '''for''' Set&amp;lt;Item&amp;gt; $I\subset C$&lt;br /&gt;
              '''for''' $X \in symbols(G')$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;//по всем символам грамматики&amp;lt;/font&amp;gt;&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ and $goto(I,X)\not\subset C$&lt;br /&gt;
                      C.add($goto(I,X)$);&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' not changed;&lt;br /&gt;
      '''return''' C;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC|d$&lt;br /&gt;
Запустим процедуру $items(G')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\epsilon;B=S;\beta=\epsilon;a=\char36$. Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество пунктов $[C\rightarrow\cdot C, c]$, $C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$, и $C\rightarrow\cdot d, d]$. Т.к. ни один из новых пунктов не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех пунктах терминалы), то функция $closure$ завершает свою работу и начальное множество пунктов в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества пунктов и их переходы]]&lt;br /&gt;
$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $G'$:&lt;br /&gt;
&lt;br /&gt;
При $X=S$:&lt;br /&gt;
$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
Мы не добавили ни одного пункта, т.к. точка является крайней справа. Таким образом, &lt;br /&gt;
$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
При $X=C$:&lt;br /&gt;
$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
При $X=c$:&lt;br /&gt;
$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
При $X=d$:&lt;br /&gt;
$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
$$I_5 = goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
$$I_6 = goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями пунктов. Такое явление является частым в LR(1)-анализе, из-за него результирующая таблица будет неоправданно большой. LALR-анализ борется с этим явлением.&lt;br /&gt;
Продолжим:&lt;br /&gt;
$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все пункты имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$ &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества пунктов не дают нам значений $goto$, процедура $items$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблица канонического &amp;lt;tex&amp;gt;LR&amp;lt;/tex&amp;gt;-анализа с функциями &amp;lt;tex&amp;gt;ACTION&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;goto&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(G'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(G') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических пунктов для &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(ACTION,&amp;lt;/tex&amp;gt;&amp;quot;ошибка&amp;quot;&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; - терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; &amp;quot;перенос &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;&amp;quot;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; &amp;amp;&amp;amp; &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; &amp;quot;свертка &amp;lt;tex&amp;gt;A\rightarrow a&amp;lt;/tex&amp;gt;&amp;quot;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,\char36] = &amp;lt;/tex&amp;gt; &amp;quot;принятие&amp;quot;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;goto(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;goto[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия - это значит, что грамматика не принадлежит классу LR(1)&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' LR(1)-анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;center&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; | Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot;  | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot;  |$goto$&lt;br /&gt;
|-&lt;br /&gt;
|$c$&lt;br /&gt;
|$d$&lt;br /&gt;
|$\char36$&lt;br /&gt;
|$S$&lt;br /&gt;
|$C$&lt;br /&gt;
|-&lt;br /&gt;
|$0$&lt;br /&gt;
|$s3$&lt;br /&gt;
|$s4$&lt;br /&gt;
|&lt;br /&gt;
|$1$&lt;br /&gt;
|$2$&lt;br /&gt;
|-&lt;br /&gt;
|$1$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
| style=&amp;quot;font-style:italic;color:green;&amp;quot; | ok&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$2$&lt;br /&gt;
|$s6$&lt;br /&gt;
|$s7$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$5$&lt;br /&gt;
|-&lt;br /&gt;
|$3$&lt;br /&gt;
|$s3$&lt;br /&gt;
|$s4$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$8$&lt;br /&gt;
|-&lt;br /&gt;
|$4$&lt;br /&gt;
|$r1$&lt;br /&gt;
|$r3$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$5$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$r1$&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$6$&lt;br /&gt;
|$s6$&lt;br /&gt;
|$s7$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$9$&lt;br /&gt;
|-&lt;br /&gt;
|$7$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$r3$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$8$&lt;br /&gt;
|$r2$&lt;br /&gt;
|$r2$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$9$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$r2$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49360</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=49360"/>
				<updated>2015-09-14T18:55:33Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях [[SLR(1)-разбор|SLR-разбор]] может выдать неправильный результат. В таких случаях используют более сложные методы, такие как  LR(1) и [[LALR-анализ|LALR-разбор]]. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример ситуации, в которой SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R \mid R \\&lt;br /&gt;
L \to *R \mid id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0)-набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим ситуацию $I_2$. Если SLR-парсер находится в $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с продукцией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=\ldots$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в ситуации больший объём информации, который позволит не делать таких ошибочных свёрток.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Канонические LR(1)-ситуации ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в ситуациях больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
Добавим в пункт второй компонент: терминальный символ. Таким образом, LR(1)-ситуации будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть {{---}} продукция, а вторая {{---}} терминал или маркер конца входной строки $\char36$. Здесь $a$ называется '''предпросмотром''' (англ. ''lookahead'') ситуации, а число 1 в LR(1) означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если находимся в ситуации $[A\rightarrow\alpha\cdot\beta, a]$ и $a$ {{---}} входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём LR(1)-ситуацию $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимой''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх:&lt;br /&gt;
* $\gamma=\delta\alpha$&lt;br /&gt;
* $a$ является первым символом $w$&lt;br /&gt;
* $w=\epsilon$ и $a=\char36$&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-ситуаций ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$-разбора, с двумя изменёнными функциями: $closure(I)$ {{---}} замыкание множества пунктов, и $goto(X,I)$ {{---}} функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} \mid b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in closure(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных пунктов должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим пункт вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве пунктов, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\epsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $closure$ и $goto$, а также множества пунктов $items$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Item&amp;gt; closure(Set&amp;lt;Item&amp;gt; I):&lt;br /&gt;
      '''bool''' changed;&lt;br /&gt;
      Set&amp;lt;Item&amp;gt; $J$=$I$;   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false''';&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in G'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      J.add($[B\rightarrow\cdot\gamma,b]$);&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' not changed;&lt;br /&gt;
      '''return''' J;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Item&amp;gt; goto(Set&amp;lt;Item&amp;gt; I, X):&lt;br /&gt;
      Set&amp;lt;Item&amp;gt; $J$=$\varnothing$;   &lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          J.add($[A\rightarrow\alpha X\cdot\beta, a]$);&lt;br /&gt;
      '''return''' $closure(J)$;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Set&amp;lt;Item&amp;gt;&amp;gt; items($G'$):&lt;br /&gt;
      '''bool''' changed;&lt;br /&gt;
      Set&amp;lt;Set&amp;lt;Item&amp;gt;&amp;gt; $C$ = $\{closure({S'\rightarrow\cdot S,\char36})\}$;   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false''';&lt;br /&gt;
          '''for''' Set&amp;lt;Item&amp;gt; $I\subset C$&lt;br /&gt;
              '''for''' $X \in symbols(G')$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;//по всем символам грамматики&amp;lt;/font&amp;gt;&lt;br /&gt;
                  '''if''' $goto(I,X)\neq\varnothing$ and $goto(I,X)\not\subset C$&lt;br /&gt;
                      C.add($goto(I,X)$);&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' not changed;&lt;br /&gt;
      '''return''' C;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC|d$&lt;br /&gt;
Запустим процедуру $items(G')$. Она начинается с вычисления $closure([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\epsilon;B=S;\beta=\epsilon;a=\char36$. Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество пунктов $[C\rightarrow\cdot C, c]$, $C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$, и $C\rightarrow\cdot d, d]$. Т.к. ни один из новых пунктов не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех пунктах терминалы), то функция $closure$ завершает свою работу и начальное множество пунктов в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества пунктов и их переходы]]&lt;br /&gt;
$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items$ будет вычисление функции переходов автомата $goto(I_0,X)$ для всех символов $X$ грамматики $G'$:&lt;br /&gt;
&lt;br /&gt;
При $X=S$:&lt;br /&gt;
$$closure({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
Мы не добавили ни одного пункта, т.к. точка является крайней справа. Таким образом, &lt;br /&gt;
$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
При $X=C$:&lt;br /&gt;
$$I_2 = closure(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
При $X=c$:&lt;br /&gt;
$$I_3 = closure(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
При $X=d$:&lt;br /&gt;
$$I_4 = closure(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$goto(I_1, *)=\varnothing$$&lt;br /&gt;
$$I_5 = goto(I_2, C) = closure(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
$$I_6 = goto(I_2, c) = closure(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями пунктов. Такое явление является частым в $LR(1)$ - анализе, из-за него результирующая таблица будет неоправданно большой. $LALR$-анализ борется с этим явлением.&lt;br /&gt;
Продолжим:&lt;br /&gt;
$$I_7 = goto(I_2, d) = closure(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $goto(I_2)$ завершено, переходим к $goto(I_3)$:&lt;br /&gt;
$$I_8 = goto(I_3, C) = closure(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все пункты имеют точки в крайнем положении справа, следовательно эти множества не имеют $goto$ &lt;br /&gt;
$$goto(I_6, c) = I_6$$&lt;br /&gt;
$$goto(I_6, d) = I_7$$&lt;br /&gt;
$$I_9 = goto(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества пунктов не дают нам значений $goto$, процедура $items$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Канонические LR(1)-таблицы ===&lt;br /&gt;
==== Алгоритм ====&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// вход: &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt; {{---}} расширенная грамматика&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// выход: таблица канонического &amp;lt;tex&amp;gt;LR&amp;lt;/tex&amp;gt;-анализа с функциями &amp;lt;tex&amp;gt;ACTION&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;goto&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{getLR1LexTable}(G'):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt; C'(G') \leftarrow \{I_0,I_1..I_n\}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// множество канонических пунктов для &amp;lt;tex&amp;gt;G'&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{fillArray}(ACTION,&amp;lt;/tex&amp;gt;&amp;quot;ошибка&amp;quot;&amp;lt;tex&amp;gt; ):&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''foreach''' &amp;lt;tex&amp;gt;I_i \in (E(G))\&amp;lt;/tex&amp;gt;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot a\beta, b] \in I_i&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;здесь &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; - терминал&amp;lt;/font&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; &amp;quot;перенос &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;&amp;quot;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[A\rightarrow \alpha\cdot, a] \in I_i&amp;lt;/tex&amp;gt; &amp;amp;&amp;amp; &amp;lt;tex&amp;gt;A\neq S'&amp;lt;/tex&amp;gt; &lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,a] = &amp;lt;/tex&amp;gt; &amp;quot;свертка &amp;lt;tex&amp;gt;A\rightarrow a&amp;lt;/tex&amp;gt;&amp;quot;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;[S'\rightarrow S\cdot, \char36] \in I_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;ACTION[i,\char36] = &amp;lt;/tex&amp;gt; &amp;quot;принятие&amp;quot;&lt;br /&gt;
        '''if''' &amp;lt;tex&amp;gt;goto(I_i,A) = I_j&amp;lt;/tex&amp;gt;&lt;br /&gt;
            &amp;lt;tex&amp;gt;goto[i,A]\leftarrow j&amp;lt;/tex&amp;gt;&lt;br /&gt;
Если в процессе построения обнаружатся конфликтующие действия - это значит, что грамматика не принадлежит классу &amp;lt;tex&amp;gt;LR(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таблица, построенная в результате применения алгоритм называется ''канонической таблицей'' &amp;lt;tex&amp;gt;LR(1)&amp;lt;/tex&amp;gt; - анализа.&lt;br /&gt;
&lt;br /&gt;
==== Пример ====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G$:&lt;br /&gt;
# $S\rightarrow CC$&lt;br /&gt;
# $C\rightarrow cC$&lt;br /&gt;
# $C\rightarrow d$&lt;br /&gt;
Приведем каноническую таблицу синтаксического анализа для этой грамматики:&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;10&amp;quot; align=&amp;quot;center&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; | Состояние&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot;  | $ACTION$&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot;  |$goto$&lt;br /&gt;
|-&lt;br /&gt;
|$c$&lt;br /&gt;
|$d$&lt;br /&gt;
|$\char36$&lt;br /&gt;
|$S$&lt;br /&gt;
|$C$&lt;br /&gt;
|-&lt;br /&gt;
|$0$&lt;br /&gt;
|$s3$&lt;br /&gt;
|$s4$&lt;br /&gt;
|&lt;br /&gt;
|$1$&lt;br /&gt;
|$2$&lt;br /&gt;
|-&lt;br /&gt;
|$1$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
| style=&amp;quot;font-style:italic;color:green;&amp;quot; | ok&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$2$&lt;br /&gt;
|$s6$&lt;br /&gt;
|$s7$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$5$&lt;br /&gt;
|-&lt;br /&gt;
|$3$&lt;br /&gt;
|$s3$&lt;br /&gt;
|$s4$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$8$&lt;br /&gt;
|-&lt;br /&gt;
|$4$&lt;br /&gt;
|$r1$&lt;br /&gt;
|$r3$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$5$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$r1$&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$6$&lt;br /&gt;
|$s6$&lt;br /&gt;
|$s7$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$9$&lt;br /&gt;
|-&lt;br /&gt;
|$7$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$r3$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$8$&lt;br /&gt;
|$r2$&lt;br /&gt;
|$r2$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|$9$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|$r2$&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 331-338.&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE%D0%B1%D0%B5%D0%B4%D0%B0%D1%8E%D1%89%D0%B8%D1%85_%D1%84%D0%B8%D0%BB%D0%BE%D1%81%D0%BE%D1%84%D0%BE%D0%B2&amp;diff=48878</id>
		<title>Задача обедающих философов</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE%D0%B1%D0%B5%D0%B4%D0%B0%D1%8E%D1%89%D0%B8%D1%85_%D1%84%D0%B8%D0%BB%D0%BE%D1%81%D0%BE%D1%84%D0%BE%D0%B2&amp;diff=48878"/>
				<updated>2015-06-28T16:40:45Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Категория: Параллельное программирование]]&lt;br /&gt;
==Задача обедающих философов==&lt;br /&gt;
За круглым столом сидят шесть философов. На столе шесть тарелок с рисом и шесть вилок.&lt;br /&gt;
В каждый момент философ может либо есть (тогда ему необходимо две вилки), либо думать (для этого ему нужен только он сам). Философы не разговаривают между собой. Необходимо, чтобы все философы поели и не возникло драки за вилки.&lt;br /&gt;
&lt;br /&gt;
==Обобщение==&lt;br /&gt;
Данная задача представляет из себя задачу получения взаимной блокировки.&lt;br /&gt;
&lt;br /&gt;
==Решение==&lt;br /&gt;
1)Процесс ест когда у него есть вилки от всех процессов&lt;br /&gt;
&lt;br /&gt;
2)После еды вилки переворачиваются (меняется направление ребра в графе), но не сразу.Просто помечаем что вилка грязная&lt;br /&gt;
&lt;br /&gt;
3)Чтобы войти в критическую секцию - все вилки должны быть чистыми&lt;br /&gt;
&lt;br /&gt;
4)При получении запроса на вилку, чистые вилки не отдавать&lt;br /&gt;
&lt;br /&gt;
5)Полученные вилки считаются чистыми&lt;br /&gt;
&lt;br /&gt;
6)Грязные вилки можно мыть когда есть все остальные&lt;br /&gt;
&lt;br /&gt;
===Token ring===&lt;br /&gt;
Все процессы объединяются в логическое кольцо независимо от реальной структуры сети.&lt;br /&gt;
&lt;br /&gt;
По кольцу передается маркер (token). Процесс, получивший маркер, проверяет, нужно ли ему войти в критическую секцию. Если нужно, то входит, а после ее завершения отправляет маркер дальше по кольцу. Если не нужно, то сразу отправляет маркер дальше.&lt;br /&gt;
&lt;br /&gt;
То есть, если ни один из процессов не заинтересован в критической секции, то маркер будет просто циркулировать по кольцу.&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Lr1_sets.png&amp;diff=48877</id>
		<title>Файл:Lr1 sets.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Lr1_sets.png&amp;diff=48877"/>
				<updated>2015-06-27T17:28:21Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: Красивая картинка, перерисованная мной из Ахо-Сети-Ульмана&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Красивая картинка, перерисованная мной из Ахо-Сети-Ульмана&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=48876</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=48876"/>
				<updated>2015-06-27T17:26:53Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: /* Пример */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях SLR-разбор может дать неправильный результат разбора. В таких случаях используют более сложные методы, такие как $LR(1)$ и $LALR$ - разбор. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием $LR(1)$ - разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, ситуации, в которой SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R | R \\&lt;br /&gt;
L \to *R | id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0) - набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим пункт $I_2$. Если SLR-парсер находится в состоянии $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с продукцией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=...$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в пункте больший объём информации, который позволит не делать таких ошибочных свёрток&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Канонические LR(1)-пункты ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в пунктах больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
Добавим в пункт второй компонент: терминальный символ. Таким образом, $LR(1)$ -пункты будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть - продукция, а вторая - терминал или маркер конца входной строки $\char36$. Здесь $a$ называется предпросмотром (англ. ''lookahead'') пункта, а цифра $1$ в $LR(1)$ означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если пункт $[A\rightarrow\alpha\cdot\beta, a]$ принадлежит состоянию на вершине стека, и $a$ - входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём $LR(1)$ - пункт $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимым''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх:&lt;br /&gt;
* $\gamma=\delta\alpha$&lt;br /&gt;
* $a$ является первым символом $w$&lt;br /&gt;
* $w=\epsilon$ и $a=\char36$&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-пунктов ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$ - разбора, с двумя изменёнными функциями: $CLOSURE(I)$ - замыкание множества пунктов, и $GOTO(X,I)$ - функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} | b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in CLOSURE(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных пунктов должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим пункт вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве пунктов, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\epsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $CLOSURE$ и $GOTO$, а также множества пунктов $items$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Item&amp;gt; CLOSURE(Set&amp;lt;Item&amp;gt; I):&lt;br /&gt;
      '''bool''' changed;&lt;br /&gt;
      Set&amp;lt;Item&amp;gt; $J$=$I$;   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false''';&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in G'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      J.add($[B\rightarrow\cdot\gamma,b]$);&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' !changed;&lt;br /&gt;
      '''return''' J;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Item&amp;gt; GOTO(Set&amp;lt;Item&amp;gt; I, X):&lt;br /&gt;
      Set&amp;lt;Item&amp;gt; $J$=$\varnothing$;   &lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          J.add($[A\rightarrow\alpha X\cdot\beta, a]$);&lt;br /&gt;
      '''return''' $CLOSURE(J)$;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Set&amp;lt;Item&amp;gt;&amp;gt; items($G'$):&lt;br /&gt;
      '''bool''' changed;&lt;br /&gt;
      Set&amp;lt;Set&amp;lt;Item&amp;gt;&amp;gt; $C$ = $\{CLOSURE({S'\rightarrow\cdot S,\char36})\}$;   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false''';&lt;br /&gt;
          '''for''' Set&amp;lt;Item&amp;gt; $I\subset C$&lt;br /&gt;
              '''for''' $X \in symbols(G')$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;//по всем символам грамматики&amp;lt;/font&amp;gt;&lt;br /&gt;
                  '''if''' $GOTO(I,X)\neq\varnothing$ and $GOTO(I,X)\not\subset C$&lt;br /&gt;
                      C.add($GOTO(I,X)$);&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' !changed;&lt;br /&gt;
      '''return''' C;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC|d$&lt;br /&gt;
Запустим процедуру $items(G')$. Она начинается с вычисления $CLOSURE([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\epsilon;B=S;\beta=\epsilon;a=\char36$. Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество пунктов $[C\rightarrow\cdot C, c]$, $C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$, и $C\rightarrow\cdot d, d]$. Т.к. ни один из новых пунктов не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех пунктах терминалы), то функция $CLOSURE$ завершает свою работу и начальное множество пунктов в данном случае равно:&lt;br /&gt;
&lt;br /&gt;
[[Файл:lr1_sets.png|400px|thumb|Рис. 1 Множества пунктов и их переходы]]&lt;br /&gt;
$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items$ будет вычисление функции переходов автомата $GOTO(I_0,X)$ для всех символов $X$ грамматики $G'$:&lt;br /&gt;
&lt;br /&gt;
При $X=S$:&lt;br /&gt;
$$CLOSURE({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
Мы не добавили ни одного пункта, т.к. точка является крайней справа. Таким образом, &lt;br /&gt;
$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
При $X=C$:&lt;br /&gt;
$$I_2 = CLOSURE(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
При $X=c$:&lt;br /&gt;
$$I_3 = CLOSURE(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
При $X=d$:&lt;br /&gt;
$$I_4 = CLOSURE(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$GOTO(I_1, *)=\varnothing$$&lt;br /&gt;
$$I_5 = GOTO(I_2, C) = CLOSURE(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
$$I_6 = GOTO(I_2, c) = CLOSURE(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями пунктов. Такое явление является частым в $LR(1)$-анализе, из-за него результирующая таблица будет неоправданно большой. $LALR$-анализ борется с этим явлением.&lt;br /&gt;
Продолжим:&lt;br /&gt;
$$I_7 = GOTO(I_2, d) = CLOSURE(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $GOTO(I_2)$ завершено, переходим к $GOTO(I_3)$:&lt;br /&gt;
$$I_8 = GOTO(I_3, C) = CLOSURE(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все пункты имеют точки в крайнем положении справа, следовательно эти множества не имеют $GOTO$ &lt;br /&gt;
$$GOTO(I_6, c) = I_6$$&lt;br /&gt;
$$GOTO(I_6, d) = I_7$$&lt;br /&gt;
$$I_9 = GOTO(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества пунктов не дают нам значений $GOTO$, процедура $items$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=48875</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=48875"/>
				<updated>2015-06-27T10:15:31Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: /* Пример */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях SLR-разбор может дать неправильный результат разбора. В таких случаях используют более сложные методы, такие как $LR(1)$ и $LALR$ - разбор. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием $LR(1)$ - разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, ситуации, в которой SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R | R \\&lt;br /&gt;
L \to *R | id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0) - набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим пункт $I_2$. Если SLR-парсер находится в состоянии $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с продукцией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=...$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в пункте больший объём информации, который позволит не делать таких ошибочных свёрток&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Канонические LR(1)-пункты ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в пунктах больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
Добавим в пункт второй компонент: терминальный символ. Таким образом, $LR(1)$ -пункты будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть - продукция, а вторая - терминал или маркер конца входной строки $\char36$. Здесь $a$ называется предпросмотром (англ. ''lookahead'') пункта, а цифра $1$ в $LR(1)$ означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если пункт $[A\rightarrow\alpha\cdot\beta, a]$ принадлежит состоянию на вершине стека, и $a$ - входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём $LR(1)$ - пункт $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимым''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх:&lt;br /&gt;
* $\gamma=\delta\alpha$&lt;br /&gt;
* $a$ является первым символом $w$&lt;br /&gt;
* $w=\epsilon$ и $a=\char36$&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-пунктов ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$ - разбора, с двумя изменёнными функциями: $CLOSURE(I)$ - замыкание множества пунктов, и $GOTO(X,I)$ - функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} | b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in CLOSURE(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных пунктов должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим пункт вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве пунктов, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\epsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $CLOSURE$ и $GOTO$, а также множества пунктов $items$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Item&amp;gt; CLOSURE(Set&amp;lt;Item&amp;gt; I):&lt;br /&gt;
      '''bool''' changed;&lt;br /&gt;
      Set&amp;lt;Item&amp;gt; $J$=$I$;   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false''';&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in G'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      J.add($[B\rightarrow\cdot\gamma,b]$);&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' !changed;&lt;br /&gt;
      '''return''' J;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Item&amp;gt; GOTO(Set&amp;lt;Item&amp;gt; I, X):&lt;br /&gt;
      Set&amp;lt;Item&amp;gt; $J$=$\varnothing$;   &lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          J.add($[A\rightarrow\alpha X\cdot\beta, a]$);&lt;br /&gt;
      '''return''' $CLOSURE(J)$;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Set&amp;lt;Item&amp;gt;&amp;gt; items($G'$):&lt;br /&gt;
      '''bool''' changed;&lt;br /&gt;
      Set&amp;lt;Set&amp;lt;Item&amp;gt;&amp;gt; $C$ = $\{CLOSURE({S'\rightarrow\cdot S,\char36})\}$;   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false''';&lt;br /&gt;
          '''for''' Set&amp;lt;Item&amp;gt; $I\subset C$&lt;br /&gt;
              '''for''' $X \in symbols(G')$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;//по всем символам грамматики&amp;lt;/font&amp;gt;&lt;br /&gt;
                  '''if''' $GOTO(I,X)\neq\varnothing$ and $GOTO(I,X)\not\subset C$&lt;br /&gt;
                      C.add($GOTO(I,X)$);&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' !changed;&lt;br /&gt;
      '''return''' C;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC|d$&lt;br /&gt;
Запустим процедуру $items(G')$. Она начинается с вычисления $CLOSURE([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\epsilon;B=S;\beta=\epsilon;a=\char36$. Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество пунктов $[C\rightarrow\cdot C, c]$, $C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$, и $C\rightarrow\cdot d, d]$. Т.к. ни один из новых пунктов не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех пунктах терминалы), то функция $CLOSURE$ завершает свою работу и начальное множество пунктов в данном случае равно:&lt;br /&gt;
$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items$ будет вычисление функции переходов автомата $GOTO(I_0,X)$ для всех символов $X$ грамматики $G'$:&lt;br /&gt;
&lt;br /&gt;
При $X=S$:&lt;br /&gt;
$$CLOSURE({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
Мы не добавили ни одного пункта, т.к. точка является крайней справа. Таким образом, &lt;br /&gt;
$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
При $X=C$:&lt;br /&gt;
$$I_2 = CLOSURE(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
При $X=c$:&lt;br /&gt;
$$I_3 = CLOSURE(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
При $X=d$:&lt;br /&gt;
$$I_4 = CLOSURE(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
На этом завершается выполнение цикла из процедуры $items$ для $I_0$. &lt;br /&gt;
$$GOTO(I_1, *)=\varnothing$$&lt;br /&gt;
$$I_5 = GOTO(I_2, C) = CLOSURE(\{[S\rightarrow CC\cdot,\char36]\})=\{[S\rightarrow CC\cdot,\char36]\}$$&lt;br /&gt;
$$I_6 = GOTO(I_2, c) = CLOSURE(\{[C\rightarrow c\cdot C,\char36]\})$$&lt;br /&gt;
$$I_6=\{[C\rightarrow c\cdot C,\char36],[C\rightarrow \cdot cC,\char36],[C\rightarrow \cdot d,\char36]\}$$&lt;br /&gt;
Обратим внимание, что $I_6$ отличается от $I_3$ только правыми частями пунктов. Такое явление является частым в $LR(1)$-анализе, из-за него результирующая таблица будет неоправданно большой. $LALR$-анализ борется с этим явлением.&lt;br /&gt;
Продолжим:&lt;br /&gt;
$$I_7 = GOTO(I_2, d) = CLOSURE(\{[C\rightarrow d\cdot ,\char36]\}) = \{[C\rightarrow d\cdot ,\char36]\}$$&lt;br /&gt;
На этом рассмотрение $GOTO(I_2)$ завершено, переходим к $GOTO(I_3)$:&lt;br /&gt;
$$I_8 = GOTO(I_3, C) = CLOSURE(\{[C\rightarrow cC\cdot ,c/d]\}) = \{[C\rightarrow cC\cdot ,c/d]\}$$&lt;br /&gt;
В множествах $I_4$ и $I_5$ все пункты имеют точки в крайнем положении справа, следовательно эти множества не имеют $GOTO$ &lt;br /&gt;
$$GOTO(I_6, c) = I_6$$&lt;br /&gt;
$$GOTO(I_6, d) = I_7$$&lt;br /&gt;
$$I_9 = GOTO(I_6, C) = \{[C\rightarrow cC\cdot,\char36]\}$$&lt;br /&gt;
Остальные множества пунктов не дают нам значений $GOTO$, процедура $items$ завершает работу. &lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=48874</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=48874"/>
				<updated>2015-06-27T09:42:41Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: /* Построение множеств LR(1)-пунктов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях SLR-разбор может дать неправильный результат разбора. В таких случаях используют более сложные методы, такие как $LR(1)$ и $LALR$ - разбор. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием $LR(1)$ - разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, ситуации, в которой SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R | R \\&lt;br /&gt;
L \to *R | id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0) - набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим пункт $I_2$. Если SLR-парсер находится в состоянии $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с продукцией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=...$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в пункте больший объём информации, который позволит не делать таких ошибочных свёрток&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Канонические LR(1)-пункты ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в пунктах больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
Добавим в пункт второй компонент: терминальный символ. Таким образом, $LR(1)$ -пункты будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть - продукция, а вторая - терминал или маркер конца входной строки $\char36$. Здесь $a$ называется предпросмотром (англ. ''lookahead'') пункта, а цифра $1$ в $LR(1)$ означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если пункт $[A\rightarrow\alpha\cdot\beta, a]$ принадлежит состоянию на вершине стека, и $a$ - входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём $LR(1)$ - пункт $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимым''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх:&lt;br /&gt;
* $\gamma=\delta\alpha$&lt;br /&gt;
* $a$ является первым символом $w$&lt;br /&gt;
* $w=\epsilon$ и $a=\char36$&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-пунктов ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$ - разбора, с двумя изменёнными функциями: $CLOSURE(I)$ - замыкание множества пунктов, и $GOTO(X,I)$ - функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} | b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in CLOSURE(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных пунктов должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим пункт вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве пунктов, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\epsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $CLOSURE$ и $GOTO$, а также множества пунктов $items$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Item&amp;gt; CLOSURE(Set&amp;lt;Item&amp;gt; I):&lt;br /&gt;
      '''bool''' changed;&lt;br /&gt;
      Set&amp;lt;Item&amp;gt; $J$=$I$;   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false''';&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in G'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      J.add($[B\rightarrow\cdot\gamma,b]$);&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' !changed;&lt;br /&gt;
      '''return''' J;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Item&amp;gt; GOTO(Set&amp;lt;Item&amp;gt; I, X):&lt;br /&gt;
      Set&amp;lt;Item&amp;gt; $J$=$\varnothing$;   &lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          J.add($[A\rightarrow\alpha X\cdot\beta, a]$);&lt;br /&gt;
      '''return''' $CLOSURE(J)$;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Set&amp;lt;Item&amp;gt;&amp;gt; items($G'$):&lt;br /&gt;
      '''bool''' changed;&lt;br /&gt;
      Set&amp;lt;Set&amp;lt;Item&amp;gt;&amp;gt; $C$ = $\{CLOSURE({S'\rightarrow\cdot S,\char36})\}$;   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false''';&lt;br /&gt;
          '''for''' Set&amp;lt;Item&amp;gt; $I\subset C$&lt;br /&gt;
              '''for''' $X \in symbols(G')$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;//по всем символам грамматики&amp;lt;/font&amp;gt;&lt;br /&gt;
                  '''if''' $GOTO(I,X)\neq\varnothing$ and $GOTO(I,X)\not\subset C$&lt;br /&gt;
                      C.add($GOTO(I,X)$);&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' !changed;&lt;br /&gt;
      '''return''' C;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC|d$&lt;br /&gt;
Запустим процедуру $items(G')$. Она начинается с вычисления $CLOSURE([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\epsilon;B=S;\beta=\epsilon;a=\char36$. Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество пунктов $[C\rightarrow\cdot C, c]$, $C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$, и $C\rightarrow\cdot d, d]$. Т.к. ни один из новых пунктов не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$ (справа от точки во всех пунктах терминалы), то функция $CLOSURE$ завершает свою работу и начальное множество пунктов в данном случае равно:&lt;br /&gt;
$$I_0: \{[S'\rightarrow \cdot S, \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items$ будет вычисление функции переходов автомата $GOTO(I_0,X)$ для всех символов $X$ грамматики $G'$:&lt;br /&gt;
&lt;br /&gt;
При $X=S$:&lt;br /&gt;
$$CLOSURE({[S'\rightarrow S\cdot,\char36]}) = \varnothing$$&lt;br /&gt;
Мы не добавили ни одного пункта, т.к. точка является крайней справа. Таким образом, &lt;br /&gt;
$$I_1: \{[S'\rightarrow S\cdot,\char36]\}$$&lt;br /&gt;
При $X=C$:&lt;br /&gt;
$$I_2 = CLOSURE(\{[S\rightarrow C\cdot C,\char36]\})$$&lt;br /&gt;
$$I_2 = \{[S\rightarrow C\cdot C,\char36],[C\rightarrow\cdot cC,\char36],[C\rightarrow\cdot d,\char36]\}$$&lt;br /&gt;
При $X=c$:&lt;br /&gt;
$$I_3 = CLOSURE(\{[C\rightarrow c\cdot C,c/d]\})$$&lt;br /&gt;
$$I_3 = \{[C\rightarrow c\cdot C,c/d],[C\rightarrow\cdot cC,c/d],[C\rightarrow\cdot d,c/d]\}$$&lt;br /&gt;
При $X=d$:&lt;br /&gt;
$$I_4 = CLOSURE(\{[C\rightarrow d\cdot ,c/d]\})$$&lt;br /&gt;
$$I_4 = \{[C\rightarrow d\cdot,c/d]\}$$&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=48873</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=48873"/>
				<updated>2015-06-27T09:10:40Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях SLR-разбор может дать неправильный результат разбора. В таких случаях используют более сложные методы, такие как $LR(1)$ и $LALR$ - разбор. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием $LR(1)$ - разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, ситуации, в которой SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R | R \\&lt;br /&gt;
L \to *R | id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0) - набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим пункт $I_2$. Если SLR-парсер находится в состоянии $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с продукцией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=...$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в пункте больший объём информации, который позволит не делать таких ошибочных свёрток&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Канонические LR(1)-пункты ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в пунктах больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
Добавим в пункт второй компонент: терминальный символ. Таким образом, $LR(1)$ -пункты будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть - продукция, а вторая - терминал или маркер конца входной строки $\char36$. Здесь $a$ называется предпросмотром (англ. ''lookahead'') пункта, а цифра $1$ в $LR(1)$ означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если пункт $[A\rightarrow\alpha\cdot\beta, a]$ принадлежит состоянию на вершине стека, и $a$ - входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём $LR(1)$ - пункт $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимым''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх:&lt;br /&gt;
* $\gamma=\delta\alpha$&lt;br /&gt;
* $a$ является первым символом $w$&lt;br /&gt;
* $w=\epsilon$ и $a=\char36$&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-пунктов ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$ - разбора, с двумя изменёнными функциями: $CLOSURE(I)$ - замыкание множества пунктов, и $GOTO(X,I)$ - функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} | b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in CLOSURE(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных пунктов должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим пункт вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве пунктов, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\epsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств $CLOSURE$ и $GOTO$, а также множества пунктов $items$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Item&amp;gt; CLOSURE(Set&amp;lt;Item&amp;gt; I):&lt;br /&gt;
      '''bool''' changed;&lt;br /&gt;
      Set&amp;lt;Item&amp;gt; $J$=$I$;   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false''';&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in G'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      J.add($[B\rightarrow\cdot\gamma,b]$);&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' !changed;&lt;br /&gt;
      '''return''' J;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Item&amp;gt; GOTO(Set&amp;lt;Item&amp;gt; I, X):&lt;br /&gt;
      Set&amp;lt;Item&amp;gt; $J$=$\varnothing$;   &lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          J.add($[A\rightarrow\alpha X\cdot\beta, a]$);&lt;br /&gt;
      '''return''' $CLOSURE(J)$;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Set&amp;lt;Item&amp;gt;&amp;gt; items($G'$):&lt;br /&gt;
      '''bool''' changed;&lt;br /&gt;
      Set&amp;lt;Set&amp;lt;Item&amp;gt;&amp;gt; $C$ = $CLOSURE({S'\rightarrow\cdot S,\char36})$;   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false''';&lt;br /&gt;
          '''for''' Set&amp;lt;Item&amp;gt; $I\subset C$&lt;br /&gt;
              '''for''' $X \in terminals(G')$&lt;br /&gt;
                  '''if''' $GOTO(I,X)\neq\varnothing$ and $GOTO(I,X)\not\subset C$&lt;br /&gt;
                      C.add($GOTO(I,X)$);&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' !changed;&lt;br /&gt;
      '''return''' C;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Пример====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Рассмотрим следующую грамматику $G'$:&lt;br /&gt;
* $S'\rightarrow S$&lt;br /&gt;
* $S\rightarrow CC$&lt;br /&gt;
* $S\rightarrow cC|d$&lt;br /&gt;
Запустим процедуру $items(G')$. Она начинается с вычисления $CLOSURE([S\rightarrow S', \char36])$. Это правило вида $[A\rightarrow\alpha\cdot B\beta, a]$, где $A=S';\alpha=\epsilon;B=S;\beta=\epsilon;a=\char36$. Т.к. в таком случае $FIRST(\beta\alpha) = {\char36}$, то мы добавим только правило $[S\rightarrow\cdot CC,\char36]$.&lt;br /&gt;
&lt;br /&gt;
Продолжив вычислять замыкание таким образом, мы добавим во множество пунктов $[C\rightarrow\cdot C, c]$, $C\rightarrow\cdot C, d]$, $C\rightarrow\cdot d, c]$, и $C\rightarrow\cdot d, d]$. Т.к. ни один из новых пунктов не имеет вид $[A\rightarrow\alpha\cdot B\beta, a]$(справа от точки во всех пунктах терминалы), то функция $CLOSURE$ завершает свою работу и начальное множество пунктов в данном случае равно:&lt;br /&gt;
$$I_0: \{[S\rightarrow S', \char36],[S\rightarrow\cdot CC,\char36],[C\rightarrow\cdot C, c/d],[C\rightarrow\cdot d, c/d]\}$$&lt;br /&gt;
Следующим шагом процедуры $items$ будет вычисление функции переходов автомата $GOTO(I_0,X)$ для всех терминалов $I_0$.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=48872</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=48872"/>
				<updated>2015-06-27T08:46:01Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях SLR-разбор может дать неправильный результат разбора. В таких случаях используют более сложные методы, такие как $LR(1)$ и $LALR$ - разбор. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием $LR(1)$ - разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, ситуации, в которой SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R | R \\&lt;br /&gt;
L \to *R | id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0) - набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим пункт $I_2$. Если SLR-парсер находится в состоянии $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с продукцией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=...$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в пункте больший объём информации, который позволит не делать таких ошибочных свёрток&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Канонические LR(1)-пункты ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в пунктах больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
Добавим в пункт второй компонент: терминальный символ. Таким образом, $LR(1)$ -пункты будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть - продукция, а вторая - терминал или маркер конца входной строки $\char36$. Здесь $a$ называется предпросмотром (англ. ''lookahead'') пункта, а цифра $1$ в $LR(1)$ означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если пункт $[A\rightarrow\alpha\cdot\beta, a]$ принадлежит состоянию на вершине стека, и $a$ - входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём $LR(1)$ - пункт $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимым''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх:&lt;br /&gt;
* $\gamma=\delta\alpha$&lt;br /&gt;
* $a$ является первым символом $w$&lt;br /&gt;
* $w=\epsilon$ и $a=\char36$&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-пунктов ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$ - разбора, с двумя изменёнными функциями: $CLOSURE(I)$ - замыкание множества пунктов, и $GOTO(X,I)$ - функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} | b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in CLOSURE(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных пунктов должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим пункт вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве пунктов, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\epsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Псевдокод построения множеств &amp;lt;tex&amp;gt;CLOSURE&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;GOTO&amp;lt;/tex&amp;gt;, а также множества пунктов &amp;lt;tex&amp;gt;items&amp;lt;/tex&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Item&amp;gt; CLOSURE(Set&amp;lt;Item&amp;gt; I):&lt;br /&gt;
      '''bool''' changed;&lt;br /&gt;
      Set&amp;lt;Item&amp;gt; $J$=$I$;   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false''';&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in G'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      J.add($[B\rightarrow\cdot\gamma,b]$);&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' !changed;&lt;br /&gt;
      '''return''' J;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Item&amp;gt; GOTO(Set&amp;lt;Item&amp;gt; I, X):&lt;br /&gt;
      Set&amp;lt;Item&amp;gt; $J$=$\varnothing$;   &lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          J.add($[A\rightarrow\alpha X\cdot\beta, a]$);&lt;br /&gt;
      '''return''' $CLOSURE(J)$;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Set&amp;lt;Item&amp;gt;&amp;gt; items($G'$):&lt;br /&gt;
      '''bool''' changed;&lt;br /&gt;
      Set&amp;lt;Set&amp;lt;Item&amp;gt;&amp;gt; $C$ = $CLOSURE({S'\rightarrow\cdot S,\char36})$;   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false''';&lt;br /&gt;
          '''for''' Set&amp;lt;Item&amp;gt; $I\subset C$&lt;br /&gt;
              '''for''' $X \in terminals(G')$&lt;br /&gt;
                  '''if''' $GOTO(I,X)\neq\varnothing$ and $GOTO(I,X)\not\subset C$&lt;br /&gt;
                      C.add($GOTO(I,X)$);&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' !changed;&lt;br /&gt;
      '''return''' C;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=48821</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=48821"/>
				<updated>2015-06-24T15:21:29Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: /* Построение множеств LR(1)-пунктов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях SLR-разбор может дать неправильный результат разбора. В таких случаях используют более сложные методы, такие как $LR(1)$ и $LALR$ - разбор. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием $LR(1)$ - разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, ситуации, в которой SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R | R \\&lt;br /&gt;
L \to *R | id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0) - набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим пункт $I_2$. Если SLR-парсер находится в состоянии $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с продукцией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=...$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в пункте больший объём информации, который позволит не делать таких ошибочных свёрток&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Канонические LR(1)-пункты ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в пунктах больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
Добавим в пункт второй компонент: терминальный символ. Таким образом, $LR(1)$ -пункты будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть - продукция, а вторая - терминал или маркер конца входной строки $\char36$. Здесь $a$ называется предпросмотром (англ. ''lookahead'') пункта, а цифра $1$ в $LR(1)$ означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если пункт $[A\rightarrow\alpha\cdot\beta, a]$ принадлежит состоянию на вершине стека, и $a$ - входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём $LR(1)$ - пункт $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимым''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх:&lt;br /&gt;
* $\gamma=\delta\alpha$&lt;br /&gt;
* $a$ является первым символом $w$&lt;br /&gt;
* $w=\epsilon$ и $a=\char36$&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-пунктов ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$ - разбора, с двумя изменёнными функциями: $CLOSURE(I)$ - замыкание множества пунктов, и $GOTO(X,I)$ - функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} | b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in CLOSURE(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных пунктов должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим пункт вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве пунктов, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\epsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
====Псевдокод====&lt;br /&gt;
Псевдокод построения множеств $CLOSURE$ и $GOTO$, а также множества пунктов $items$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Item&amp;gt; CLOSURE(Set&amp;lt;Item&amp;gt; I):&lt;br /&gt;
      '''bool''' changed;&lt;br /&gt;
      Set&amp;lt;Item&amp;gt; $J$=$I$;   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false''';&lt;br /&gt;
          '''for''' $[A\rightarrow\alpha\cdot B\beta, a]\in I$&lt;br /&gt;
              '''for''' $(B\rightarrow\gamma)\in G'$&lt;br /&gt;
                  '''for''' $b\in FIRST(\beta\alpha)$&lt;br /&gt;
                      J.add($[B\rightarrow\cdot\gamma,b]$);&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' !changed;&lt;br /&gt;
      '''return''' J;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Item&amp;gt; GOTO(Set&amp;lt;Item&amp;gt; I, X):&lt;br /&gt;
      Set&amp;lt;Item&amp;gt; $J$=$\varnothing$;   &lt;br /&gt;
      '''for''' $[A\rightarrow\alpha\cdot X\beta, a]\in I$&lt;br /&gt;
          J.add($[A\rightarrow\alpha X\cdot\beta, a]$);&lt;br /&gt;
      '''return''' $CLOSURE(J)$;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  Set&amp;lt;Set&amp;lt;Item&amp;gt;&amp;gt; items($G'$):&lt;br /&gt;
      '''bool''' changed;&lt;br /&gt;
      Set&amp;lt;Set&amp;lt;Item&amp;gt;&amp;gt; $C$ = $CLOSURE({S'\rightarrow\cdot S,\char36})$;   &lt;br /&gt;
      '''repeat'''&lt;br /&gt;
          changed = '''false''';&lt;br /&gt;
          '''for''' Set&amp;lt;Item&amp;gt; $I\subset C$&lt;br /&gt;
              '''for''' $X \in terminals(G')$&lt;br /&gt;
                  '''if''' $GOTO(I,X)\neq\varnothing$ and $GOTO(I,X)\not\subset C$&lt;br /&gt;
                      C.add($GOTO(I,X)$);&lt;br /&gt;
                      changed = '''true'''&lt;br /&gt;
      '''until''' !changed;&lt;br /&gt;
      '''return''' C;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=48820</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=48820"/>
				<updated>2015-06-24T14:49:44Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: /* Канонические LR(1)-пункты */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях SLR-разбор может дать неправильный результат разбора. В таких случаях используют более сложные методы, такие как $LR(1)$ и $LALR$ - разбор. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием $LR(1)$ - разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, ситуации, в которой SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R | R \\&lt;br /&gt;
L \to *R | id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0) - набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим пункт $I_2$. Если SLR-парсер находится в состоянии $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с продукцией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=...$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в пункте больший объём информации, который позволит не делать таких ошибочных свёрток&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Канонические LR(1)-пункты ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в пунктах больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
Добавим в пункт второй компонент: терминальный символ. Таким образом, $LR(1)$ -пункты будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть - продукция, а вторая - терминал или маркер конца входной строки $\char36$. Здесь $a$ называется предпросмотром (англ. ''lookahead'') пункта, а цифра $1$ в $LR(1)$ означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если пункт $[A\rightarrow\alpha\cdot\beta, a]$ принадлежит состоянию на вершине стека, и $a$ - входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём $LR(1)$ - пункт $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимым''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх:&lt;br /&gt;
* $\gamma=\delta\alpha$&lt;br /&gt;
* $a$ является первым символом $w$&lt;br /&gt;
* $w=\epsilon$ и $a=\char36$&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-пунктов ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Метод построения похож на метод для $LR(0)$ - разбора, с двумя изменёнными функциями: $CLOSURE(I)$ - замыкание множества пунктов, и $GOTO(X,I)$ - функция переходов в автомате по символу $X$.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemmaclosure &lt;br /&gt;
|statement= $$\forall{b} | b\in FIRST(\beta\alpha): [A\rightarrow\alpha\cdot B\beta, a]\in I\Rightarrow [B\rightarrow\cdot\gamma, b]\in CLOSURE(I)$$&lt;br /&gt;
Другими словами, при построении замыкания вторая часть добавленных пунктов должна принадлежать $FIRST(\beta\alpha)$&lt;br /&gt;
|proof= Рассмотрим пункт вида $[A\rightarrow\alpha\cdot B\beta, a]$ в множестве пунктов, допустимых для некоторого активного префикса $\gamma$. Тогда существует правое порождение $S\Rightarrow^{*}\delta Aax\Rightarrow\delta\alpha B\beta ax$, где $\gamma=\delta\alpha$. Предположим, что $\beta ax$ порождает строку терминалов $by$. Тогда для каждой продукции вида $\forall{B\rightarrow\eta}\exists{\eta}$ мы имеем порождение $ S\Rightarrow^{*}\delta Bby\Rightarrow\delta\eta by$. Таким образом, $[B\rightarrow\cdot\eta,b]$ является допустимым для $\gamma$. Заметим, что $b$ может быть первым терминалом, порожденным из $\beta$, либо, возможно что $\beta$ порождает $\epsilon$ слева: $\beta ax\Rightarrow^{*}by$, следовательно $b=a$. Таким образом, $b\in FIRST(\beta ax)$. Поскольку $x$ не может содержать первый терминал из $by$, то $FIRST(\beta ax)=FIRST(\beta a)$&lt;br /&gt;
Значит, $b\in FIRST(\beta a)$.&lt;br /&gt;
}}&lt;br /&gt;
Псевдокод построения множеств $CLOSURE$ и $GOTO$, а также множества пунктов $items$:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  '''function''' constructFOLLOW():&lt;br /&gt;
      '''for''' &amp;lt;tex&amp;gt;( A  \in N )&amp;lt;/tex&amp;gt;&lt;br /&gt;
          &amp;lt;tex&amp;gt;\mathrm{FOLLOW}[A] =  \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
      &amp;lt;tex&amp;gt;\mathrm{FOLLOW}[S] =  \{\$\} &amp;lt;/tex&amp;gt;  &amp;lt;font color=green&amp;gt; // в стартовый терминал помещается символ конца строки &amp;lt;/font&amp;gt;&lt;br /&gt;
      changed = ''true''&lt;br /&gt;
      '''while''' changed&lt;br /&gt;
          changed = ''false''&lt;br /&gt;
          '''for''' &amp;lt;tex&amp;gt;( A \to \alpha \in P )&amp;lt;/tex&amp;gt;&lt;br /&gt;
              '''for''' &amp;lt;tex&amp;gt;( B : \alpha = \beta B \gamma)&amp;lt;/tex&amp;gt;&lt;br /&gt;
                  &amp;lt;tex&amp;gt; \mathrm{FOLLOW}[B]\ \cup =\ \mathrm{FIRST}(\gamma) \setminus \{\varepsilon\} &amp;lt;/tex&amp;gt;&lt;br /&gt;
                  '''if''' &amp;lt;tex&amp;gt; \varepsilon \in \mathrm{FIRST}(\gamma) &amp;lt;/tex&amp;gt;&lt;br /&gt;
                      &amp;lt;tex&amp;gt; \mathrm{FOLLOW}[B]\ \cup =\ \mathrm{FOLLOW}[A]&amp;lt;/tex&amp;gt;&lt;br /&gt;
                  changed = ''true'' '''if''' &amp;lt;tex&amp;gt; \mathrm{FOLLOW}[B] &amp;lt;/tex&amp;gt; изменился&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=48816</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=48816"/>
				<updated>2015-06-24T13:09:19Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях SLR-разбор может дать неправильный результат разбора. В таких случаях используют более сложные методы, такие как $LR(1)$ и $LALR$ - разбор. Рассмотрим первый из них.&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Отличия от SLR-разбора ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием $LR(1)$ - разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, ситуации, в которой SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R | R \\&lt;br /&gt;
L \to *R | id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0) - набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим пункт $I_2$. Если SLR-парсер находится в состоянии $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с продукцией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=...$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в пункте больший объём информации, который позволит не делать таких ошибочных свёрток&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
== Канонические LR(1)-пункты ==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в пунктах больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
Добавим в пункт второй компонент: терминальный символ. Таким образом, $LR(1)$ -пункты будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть - продукция, а вторая - терминал или маркер конца входной строки $\char36$. Здесь $a$ называется предпросмотром (англ. ''lookahead'') пункта, а цифра $1$ в $LR(1)$ означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если пункт $[A\rightarrow\alpha\cdot\beta, a]$ принадлежит состоянию на вершине стека, и $a$ - входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём $LR(1)$ - пункт $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимым''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх:&lt;br /&gt;
* $\gamma=\delta\alpha$&lt;br /&gt;
* $a$ является первым символом $w$&lt;br /&gt;
* $w=\epsilon$ и $a=\char36$&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
=== Построение множеств LR(1)-пунктов ===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=48807</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=48807"/>
				<updated>2015-06-24T11:30:09Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;wikitex&amp;gt;&lt;br /&gt;
В некоторых случаях SLR-разбор может дать неправильный результат разбора. В таких случаях используют более сложные методы, такие как $LR(1)$ и $LALR$ - разбор. Рассмотрим первый из них.&lt;br /&gt;
==Отличия от SLR-разбора==&lt;br /&gt;
Основным отличием $LR(1)$ - разбора от SLR-разбора является использование '''предпросмотра''' (англ. ''lookahead'') символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, ситуации, в которой SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R | R \\&lt;br /&gt;
L \to *R | id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0) - набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим пункт $I_2$. Если SLR-парсер находится в состоянии $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с продукцией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=...$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в пункте больший объём информации, который позволит не делать таких ошибочных свёрток&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Канонические LR(1)-пункты==&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в пунктах больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
Добавим в пункт второй компонент: терминальный символ. Таким образом, $LR(1)$ -пункты будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть - продукция, а вторая - терминал или маркер конца входной строки $\char36$. Здесь $a$ называется предпросмотром (англ. ''lookahead'') пункта, а цифра $1$ в $LR(1)$ означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если пункт $[A\rightarrow\alpha\cdot\beta, a]$ принадлежит состоянию на вершине стека, и $a$ - входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём $LR(1)$ - пункт $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимым''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх:&lt;br /&gt;
* $\gamma=\delta\alpha$&lt;br /&gt;
* $a$ является первым символом $w$&lt;br /&gt;
* $w=\epsilon$ и $a=\char36$&lt;br /&gt;
}}&lt;br /&gt;
===Построение множеств LR(1)-пунктов===&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=48806</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=48806"/>
				<updated>2015-06-24T11:24:10Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: /* Отличия от SLR-разбора */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Отличия от SLR-разбора==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование предпросмотра(англ. lookahead) символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, ситуации, в которой SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R | R \\&lt;br /&gt;
L \to *R | id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0) - набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим пункт $I_2$. Если SLR-парсер находится в состоянии $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с продукцией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=...$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в пункте больший объём информации, который позволит не делать таких ошибочных свёрток&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Канонические LR(1)-пункты==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в пунктах больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
Добавим в пункт второй компонент: терминальный символ. Таким образом, $LR(1)$-пункты будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть - продукция, а вторая - терминал или маркер конца входной строки $\char36$. Здесь $a$ называется предпросмотром (англ. ''lookahead'') пункта, а цифра $1$ в $LR(1)$ означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если пункт $[A\rightarrow\alpha\cdot\beta, a]$ принадлежит состоянию на вершине стека, и $a$ - входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём $LR(1)$ - пункт $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимым''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх:&lt;br /&gt;
* $\gamma=\delta\alpha$&lt;br /&gt;
* $a$ является первым символом $w$&lt;br /&gt;
* $w=\epsilon$ и $a=\char36$&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
===Построение множеств LR(1)-пунктов===&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=48805</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=48805"/>
				<updated>2015-06-24T11:23:32Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: /* Канонические LR(1)-состояния */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Отличия от SLR-разбора==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование предпросмотра(англ. lookahead) символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, ситуации, в которой SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R | R \\&lt;br /&gt;
L \to *R | id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0) - набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим пункт $I_2$. Если SLR-парсер находится в состоянии $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с продукцией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=...$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в состоянии больший объём информации, который позволит не делать таких ошибочных свёрток&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
==Канонические LR(1)-пункты==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основная идея заключается в том, чтобы хранить в пунктах больше информации, чтобы не производить некорректных свёрток. &lt;br /&gt;
Добавим в пункт второй компонент: терминальный символ. Таким образом, $LR(1)$-пункты будут выглядеть следующим образом: &lt;br /&gt;
&lt;br /&gt;
$[A\rightarrow\alpha\cdot\beta, a]$, где первая часть - продукция, а вторая - терминал или маркер конца входной строки $\char36$. Здесь $a$ называется предпросмотром (англ. ''lookahead'') пункта, а цифра $1$ в $LR(1)$ означает его длину.&lt;br /&gt;
Теперь мы будем выполнять свёртку в соответствии с продукцией $A\rightarrow\alpha$, только в том случае, если пункт $[A\rightarrow\alpha\cdot\beta, a]$ принадлежит состоянию на вершине стека, и $a$ - входной символ.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defValid &lt;br /&gt;
|definition=&lt;br /&gt;
Назовём $LR(1)$ - пункт $[A\rightarrow\alpha\cdot\beta, a]$ '''допустимым''' (англ. ''valid'') для активного префикса $\gamma$, если существует правое порождение $S\Rightarrow^{*}\delta A w\Rightarrow\delta\alpha\beta w$, где верно одно из трёх:&lt;br /&gt;
* $\gamma=\delta\alpha$&lt;br /&gt;
* $a$ является первым символом $w$&lt;br /&gt;
* $w=\epsilon$ и $a=\char36$&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
===Построение множеств LR(1)-пунктов===&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=48510</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=48510"/>
				<updated>2015-06-15T16:39:29Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Отличия от SLR-разбора==&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование предпросмотра(англ. lookahead) символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, ситуации, в которой SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R | R \\&lt;br /&gt;
L \to *R | id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0) - набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим пункт $I_2$. Если SLR-парсер находится в состоянии $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с продукцией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=...$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в состоянии больший объём информации, который позволит не делать таких ошибочных свёрток&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;br /&gt;
==Канонические LR(1)-состояния==&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=48509</id>
		<title>LR(1)-разбор</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LR(1)-%D1%80%D0%B0%D0%B7%D0%B1%D0%BE%D1%80&amp;diff=48509"/>
				<updated>2015-06-15T16:29:01Z</updated>
		
		<summary type="html">&lt;p&gt;Xottab: /* Отличия от SLR-разбора */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{В разработке}}&lt;br /&gt;
===Отличия от SLR-разбора===&lt;br /&gt;
&amp;lt;wikitex&amp;gt;&lt;br /&gt;
Основным отличием LR(1)-разбора от SLR-разбора является использование предпросмотра(англ. lookahead) символов.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, ситуации, в которой SLR-разбор не справится с задачей:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим грамматику вида:&lt;br /&gt;
$&lt;br /&gt;
S \to L=R | R \\&lt;br /&gt;
L \to *R | id \\&lt;br /&gt;
R \to L&lt;br /&gt;
$&lt;br /&gt;
&lt;br /&gt;
Покажем её канонический LR(0) - набор:&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_0$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_1$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_2$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_3$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_4$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_5$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_6$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_7$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_8$&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| $I_9$&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to \cdot S \\ &lt;br /&gt;
S \to \cdot L = R \\ &lt;br /&gt;
S \to \cdot R \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id \\&lt;br /&gt;
R \to \cdot L$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S' \to S \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L \cdot = R \\&lt;br /&gt;
R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to id \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = \cdot R \\&lt;br /&gt;
R \to \cdot L \\&lt;br /&gt;
L \to \cdot * R \\&lt;br /&gt;
L \to \cdot id$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$L \to * R \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$R \to L \cdot$&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 15px&amp;quot;| &lt;br /&gt;
$S \to L = R \cdot$&lt;br /&gt;
|}&lt;br /&gt;
Рассмотрим пункт $I_2$. Если SLR-парсер находится в состоянии $I_2$ и очередной входной символ равен $=$, то парсер выполняет свёртку в соответствии с продукцией $R \to L$, что неверно, т.к. в этой грамматике не выводится выражение $R=...$ и парсер должен был выполнить перенос, а не свёртку.&lt;br /&gt;
&lt;br /&gt;
Чтобы решить эту проблему, необходимо хранить в состоянии больший объём информации, который позволит не делать таких ошибочных свёрток&lt;br /&gt;
&amp;lt;/wikitex&amp;gt;&lt;/div&gt;</summary>
		<author><name>Xottab</name></author>	</entry>

	</feed>