LR(k)-грамматики — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(LR-разборщик)
(LR(k)-грамматика)
Строка 2: Строка 2:
  
 
== LR(k)-грамматика ==
 
== LR(k)-грамматика ==
 
 
{{Определение
 
{{Определение
 
|id=def_augmented_grammar)  
 
|id=def_augmented_grammar)  
Строка 8: Строка 7:
 
Пусть <tex>\Gamma =\langle \Sigma, N, S, P \rangle</tex> {{---}} [[Контекстно-свободные_грамматики,_вывод,_лево-_и_правосторонний_вывод,_дерево_разбора|контекстно-свободная]] грамматика. '''Пополненной грамматикой''' (англ. ''augmented grammar''), полученной из <tex>\Gamma</tex>, назовем грамматику <tex>\Gamma' =\langle \Sigma', N', S', P' \rangle</tex>, где <tex>\Sigma' = \Sigma; N' = N \cup \{S'\}; S' \notin N; P' = P \cup \{S' \to S\}</tex>
 
Пусть <tex>\Gamma =\langle \Sigma, N, S, P \rangle</tex> {{---}} [[Контекстно-свободные_грамматики,_вывод,_лево-_и_правосторонний_вывод,_дерево_разбора|контекстно-свободная]] грамматика. '''Пополненной грамматикой''' (англ. ''augmented grammar''), полученной из <tex>\Gamma</tex>, назовем грамматику <tex>\Gamma' =\langle \Sigma', N', S', P' \rangle</tex>, где <tex>\Sigma' = \Sigma; N' = N \cup \{S'\}; S' \notin N; P' = P \cup \{S' \to S\}</tex>
 
}}
 
}}
 
Использование в определении LR(k)-грамматики пополненной грамматики существенно для однозначного определения конца анализа. Действительно, если грамматика использует <tex>S</tex> в правых частях правил, то свертка основы в <tex>S</tex> не может служить сигналом приема входной цепочки. Свертка же в <tex>S'</tex> в пополненной грамматике служит таким сигналом, поскольку <tex>S'</tex> нигде, кроме начальной сентенциальной формы, не встречается.
 
 
// TODO сделать пример, когда нам точно нужно пополнять грамматику
 
 
// TODO написать нормальное определение LR(k)-грамматики
 
 
 
{{Определение
 
{{Определение
 
|id=def_LR_K  
 
|id=def_LR_K  
 
|definition=
 
|definition=
Пусть <tex>\Gamma' =\langle \Sigma', N', S', P' \rangle</tex> {{---}} пополненная грамматика для КС-грамматики <tex>\Gamma</tex>. Грамматика <tex>\Gamma</tex> явяется '''LR(k)-грамматикой''', если для любых двух [[Контекстно-свободные_грамматики,_вывод,_лево-_и_правосторонний_вывод,_дерево_разбора#Лево-_и_правосторонний_вывод_слова|правосторонних выводов]] вида:
+
Пусть <tex>\Gamma' =\langle \Sigma', N', S', P' \rangle</tex> {{---}} пополненная грамматика для КС-грамматики <tex>\Gamma</tex>. Грамматика <tex>\Gamma</tex> явяется '''LR(k)-грамматикой''', если для любых двух [[Контекстно-свободные_грамматики,_вывод,_лево-_и_правосторонний_вывод,_дерево_разбора#Лево-_и_правосторонний_вывод_слова|правосторонних выводов]]:
* <tex>S' \Rightarrow^* \alpha A w \Rightarrow \alpha \beta w </tex>,
+
* <tex>S' \Rightarrow^* \beta A t z \Rightarrow \beta \alpha t z  \Rightarrow^* w,  </tex> если <tex>|t|=k</tex> или <tex>|t|<k, |z|=0 (z = \varepsilon)</tex>
* <tex>S' \Rightarrow^* \gamma B x \Rightarrow \alpha \beta y </tex>,
+
* <tex>S' \Rightarrow^* \gamma B t z' \Rightarrow \gamma \xi t z' \Rightarrow^* w',  </tex> если <tex> |t|<k \Rightarrow z= \varepsilon </tex>
в которых <tex> \mathrm{FIRST}_k(w) = \mathrm{FIRST}_k(y)</tex>, должно быть <tex>\alpha A y = \gamma B x</tex>. Другими словами, <tex>\alpha = \gamma, A=B, y=x </tex>.
+
 
 +
верно, что <tex>\gamma \xi = \beta \alpha</tex>,  
 +
 
 +
следует, что <tex>\beta = \gamma</tex> и <tex>A = B</tex>
 
}}
 
}}
 +
Говоря неформально, мы делаем правостороннюю свёртку нашей строки в стартовый нетерминал. Если по не более чем <tex>k</tex> символам неразобранной строки мы можем однозначно определить, во что сворачивается хвост выведенного правила, то грамматика будет LR(k).
 +
 +
Использование в определении LR(k)-грамматики пополненной грамматики существенно для однозначного определения конца анализа. Действительно, если грамматика использует <tex>S</tex> в правых частях правил, то свертка основы в <tex>S</tex> не может служить сигналом приема входной цепочки. Свертка же в <tex>S'</tex> в пополненной грамматике служит таким сигналом, поскольку <tex>S'</tex> нигде, кроме начальной сентенциальной формы, не встречается.
  
Говоря неформально, если согласно первому выводу <tex>\beta</tex> {{---}} основа, сворачиваемая в нетерминал <tex>A</tex>, то и во втором выводе <tex>\beta</tex> должна быть основой, сворачиваемой в нетерминал <tex>A</tex>.
+
Существенность использования пополненной грамматики в определении LR(k)-грамматик продемонстрируем на следующем конкретном примере:
Из этого определения следует, что если имеется правовыводимая цепочка <tex>\alpha_i = \alpha \beta w</tex>, где <tex>\beta</tex> {{---}} основа, полученная из <tex>A</tex>, и если <tex>\alpha \beta = X_1 X_2 ... X_r</tex>, то
 
* зная первые символы <tex>X_1 X_2 ... X_j</tex> цепочки <tex>\alpha \beta</tex> и не более, чем <tex>k</tex> следующих символов цепочки <tex>X_{j+1} X_{j+2} ... X_r w</tex>, мы можем быть уверены, что правый конец основы не будет достигнут до тех пор, пока <tex> j \ne r</tex>;
 
* зная цепочку <tex>\alpha \beta = X_1 X_2 ... X_r</tex> и не более <tex>k</tex> символов цепочки <tex>w</tex>, мы можем быть уверены, что именно <tex>\beta</tex> является основой, сворачиваемой в нетерминал <tex>A</tex>;
 
* если <tex>\alpha_{i-1} = S'</tex>, можно сигнализировать о выводимости исходной терминальной цепочки из <tex>S'</tex> и, следовательно, из <tex>S</tex>.
 
  
// TODO end
+
--- TODO ---
  
 
LR(k) означает, что  
 
LR(k) означает, что  

Версия 13:13, 29 августа 2015

Восходящий разбор (англ. Bottom-up parsing) предназначен для построения дерево разбора. Мы можем представить себе этот процесс как "свертку" исходной строки [math]w[/math] к правилу грамматики. Каждый шаг свертки заключается в сопоставлении некоторой подстроки [math]w[/math] и правой части какого-то правила грамматики, затем происходит замена этой подстроки на нетерминал, являющийся левой частью правила. Восходящий разбор менее интуитивный, чем нисходящий, но зато позволяет разбирать большее множество грамматик.

LR(k)-грамматика

Определение:
Пусть [math]\Gamma =\langle \Sigma, N, S, P \rangle[/math]контекстно-свободная грамматика. Пополненной грамматикой (англ. augmented grammar), полученной из [math]\Gamma[/math], назовем грамматику [math]\Gamma' =\langle \Sigma', N', S', P' \rangle[/math], где [math]\Sigma' = \Sigma; N' = N \cup \{S'\}; S' \notin N; P' = P \cup \{S' \to S\}[/math]


Определение:
Пусть [math]\Gamma' =\langle \Sigma', N', S', P' \rangle[/math] — пополненная грамматика для КС-грамматики [math]\Gamma[/math]. Грамматика [math]\Gamma[/math] явяется LR(k)-грамматикой, если для любых двух правосторонних выводов:
  • [math]S' \Rightarrow^* \beta A t z \Rightarrow \beta \alpha t z \Rightarrow^* w, [/math] если [math]|t|=k[/math] или [math]|t|\lt k, |z|=0 (z = \varepsilon)[/math]
  • [math]S' \Rightarrow^* \gamma B t z' \Rightarrow \gamma \xi t z' \Rightarrow^* w', [/math] если [math] |t|\lt k \Rightarrow z= \varepsilon [/math]

верно, что [math]\gamma \xi = \beta \alpha[/math],

следует, что [math]\beta = \gamma[/math] и [math]A = B[/math]

Говоря неформально, мы делаем правостороннюю свёртку нашей строки в стартовый нетерминал. Если по не более чем [math]k[/math] символам неразобранной строки мы можем однозначно определить, во что сворачивается хвост выведенного правила, то грамматика будет LR(k).

Использование в определении LR(k)-грамматики пополненной грамматики существенно для однозначного определения конца анализа. Действительно, если грамматика использует [math]S[/math] в правых частях правил, то свертка основы в [math]S[/math] не может служить сигналом приема входной цепочки. Свертка же в [math]S'[/math] в пополненной грамматике служит таким сигналом, поскольку [math]S'[/math] нигде, кроме начальной сентенциальной формы, не встречается.

Существенность использования пополненной грамматики в определении LR(k)-грамматик продемонстрируем на следующем конкретном примере:

--- TODO ---

LR(k) означает, что

  • входная цепочка обрабатывается слева направо (англ. left-to-right parse);
  • выполняется правый вывод (англ. rightmost derivation);
  • не более [math]k[/math] символов цепочки (англ. k-token lookahead) используются для принятия решения.

LR-разборщик

Принцип переноса-свёртки

При LR(k)-анализе применяется метод перенос-свертка (англ. shift-reduce). Суть метода сводится к следующему:

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

Структура

Метод перенос-свертка использует следующие компоненты:

  • Входная строка
  • Стек (для запоминания рассмотренных символов)
  • Управляющая таблица (для определения, какое действие применить - перенос или свертку)
  • Автомат (для запоминания информации о текущем состоянии стека)

Управляющая программа анализатора

Управляющая программа одинакова для всех LR-анализаторов, а таблица и автомат изменяются от одного анализатора к другому.

Для запоминания строки запись в стек имеет вид: [math]s_0X_1s_1X_2...X_ms_m[/math], где [math]s_m[/math] — вершина стека. Каждый [math]X_i[/math] — символ грамматики(терминал или нетерминал), а [math]s_i[/math] — состояние автомата. Каждое состояние суммирует информацию, cодержащуюся в стеке перед ним. [math]s_0[/math] — стартовае состояние автомата.

Обращение к таблице происходит по паре [math][s_m, a_i][/math], где

  • [math]s_m[/math] — текущее состояние автомата,
  • [math]a_i[/math] — текущий входной символ;

В таблице информация отображается слудующим образом:

  • переход в стостояние [math](shift)[/math]
  • свертка по правилу [math](reduce)[/math],
  • допуск [math](accept)[/math],
  • ошибка [math](error)[/math].

Алгоритм

  1. Программа читает символ из входной цепочки.
  2. Обращается к утравляющей таблице.
  3. Совершает соответствующее действие.
  4. Возвращается к первому пункту, пока входная цепочка не закончится.

 bool algorithmLR(w: string)
     curToken — указатель на перый символ в строке w
     while цепочка не закончилась
         s = top()
         a = w[ip]
         if action [s, a] == shift s’ 
             push(a)
             push(s’)
             ip++
         else if action [s, a] == reduce A [math] \to \beta[/math] 
             for j = 1 to [math]|\beta |[/math]  
                 pop()
                 pop()
             s’ = top()
             push(A)
             push(goto [s’, A]) 
             Вывод правила (A [math] \to \beta[/math])
         else if action [s, a] == accept 
             return true
         else 
             return false     

Функция [math]goto[/math] получает состояние и символ грамматики и выдает состояние. Функция [math]goto[/math], строящаяся по грамматике [math]\Gamma[/math], есть функция переходов детерминированного магазинного автомата, который распознает язык, порождаемый грамматикой [math]\Gamma[/math].

См. также

Источники информации