Zadanie 2.
Jak wyglądałaby tablica priorytetów obliczona algorytmem dla gramatyki E → E + E ∣ E − E ∣ E ∗ E ∣ E / E ∣ i d
E \to E + E | E - E | E * E | E / E | id
E → E + E ∣ E − E ∣ E ∗ E ∣ E / E ∣ i d
«Gramatyki operatorowe»
Zbiory LEADING \operatorname{LEADING} L E A D I N G oraz TRAILING \operatorname{TRAILING} T R A I L I N G
Standardowy algorytm dla danej produkcji A A A (pierwsze terminale wyprowadzane z A A A ):
a ∈ LEADING ( A ) a \in \operatorname{LEADING}(A) a ∈ L E A D I N G ( A ) jeśli mamy produkcję A → B a β A \to B a \beta A → B a β lub A → a β A \to a \beta A → a β .
Jeśli istnieje produkcja A → B α A \to B \alpha A → B α oraz a ∈ LEADING ( B ) a \in \operatorname{LEADING}(B) a ∈ L E A D I N G ( B ) to a ∈ LEADING ( A ) a \in \operatorname{LEADING}(A) a ∈ L E A D I N G ( A ) .
Dla wszystkich terminali wykonujemy powyższe podpunkty do momentu, kiedy nic się nie zmienia.
Analogicznie dla TRAILING ( A ) \operatorname{TRAILING}(A) T R A I L I N G ( A ) (ostatnie terminale wyprowadzane z A A A ).
Obliczanie relacji ⋖ \lessdot ⋖ , ≐ \doteq ≐ oraz ⋗ \gtrdot ⋗
Standardowy algorytm:
Dla każdej produkcji A → x 1 … x k A \to x_1 \dots x_k A → x 1 … x k :
Jeśli x i x_i x i i x i + 1 x_{i+1} x i + 1 są terminalami, to x i ≐ x i + 1 x_i \doteq x_{i+1} x i ≐ x i + 1 .
Jeśli x i x_i x i i x i + 2 x_{i+2} x i + 2 są terminalami a x i + 1 x_{i+1} x i + 1 nieterminalem, to x i ≐ x i + 2 x_i \doteq x_{i+2} x i ≐ x i + 2
Jeśli x i x_i x i jest terminalem a x i + 1 x_{i+1} x i + 1 nieterminalem to dla każdego a ∈ LEADING ( x i + 1 ) a \in \operatorname{LEADING}(x_{i+1}) a ∈ L E A D I N G ( x i + 1 ) mamy x i ⋖ a x_i \lessdot a x i ⋖ a .
Jeśli x i x_i x i jest nieterminalem a x i + 1 x_{i+1} x i + 1 terminalem to dla każdego a ∈ TRAILING ( x i ) a \in \operatorname{TRAILING}(x_i) a ∈ T R A I L I N G ( x i ) mamy a ⋗ x i + 1 a \gtrdot x_{i+1} a ⋗ x i + 1 .
Widać już, że w naszym przypadku krok 3. i 4. będą generować przeciwne sobie reguły, jako, że mamy tylko jeden nieterminal E E E .
Implementacja
W gramatyce jest tylko jeden nieterminal E E E , więc stosując powyższe algorytmy na LEADING \operatorname{LEADING} L E A D I N G oraz TRAILING \operatorname{TRAILING} T R A I L I N G mamy:
LEADING ( E ) = { + , − , ∗ , / , i d } \operatorname{LEADING}(E) = \{+, -, *, /, id\} L E A D I N G ( E ) = { + , − , ∗ , / , i d } ,
TRAILING ( E ) = { + , − , ∗ , / , i d } \operatorname{TRAILING}(E) = \{+, -, *, /, id\} T R A I L I N G ( E ) = { + , − , ∗ , / , i d } .
Brak sprecyzowanego pierwszeństwa prowadzi do konfliktów w tabelce.
Przykład: „+ + + ”:
Mamy produkcję E → E ⏟ x 1 + ⏟ x 2 E ⏟ x 3 E \to \underbrace{E}_{x_1} \underbrace{+}_{x_2} \underbrace{E}_{x_3} E → x 1 E x 2 + x 3 E .
Z punktu 4. algorytmu mamy x 1 x_1 x 1 będący jedynym nieterminalem oraz x 2 x_2 x 2 będący terminalem;
czyli dla każdego elementu ze zbioru TRAILING ( E ) \operatorname{TRAILING}(E) T R A I L I N G ( E ) (dla wszystkich operatorów) zachodzi relacja ⋗ \gtrdot ⋗ względem terminalu „+ + + ”.
Ale jednocześnie z punktu 3. mamy x 2 x_2 x 2 będący terminalem oraz x 3 x_3 x 3 będący jedynym nieterminalem;
czyli dla każdego elementu ze zbioru LEADING ( E ) \operatorname{LEADING}(E) L E A D I N G ( E ) (dla wszystkich operatorów) zachodzi relacja ⋖ \lessdot ⋖ względem terminalu „+ + + ”.
+ + +
⋗ ⋖ \gtrdot \lessdot ⋗ ⋖
⋖ ⋗ \lessdot \gtrdot ⋖ ⋗
⋖ ⋗ \lessdot \gtrdot ⋖ ⋗
⋖ ⋗ \lessdot \gtrdot ⋖ ⋗
⋖ \lessdot ⋖
⋗ \gtrdot ⋗
− - −
⋗ ⋖ \gtrdot \lessdot ⋗ ⋖
⋖ ⋗ \lessdot \gtrdot ⋖ ⋗
⋖ ⋗ \lessdot \gtrdot ⋖ ⋗
⋖ ⋗ \lessdot \gtrdot ⋖ ⋗
⋖ \lessdot ⋖
⋗ \gtrdot ⋗
∗ * ∗
⋗ ⋖ \gtrdot \lessdot ⋗ ⋖
⋖ ⋗ \lessdot \gtrdot ⋖ ⋗
⋖ ⋗ \lessdot \gtrdot ⋖ ⋗
⋖ ⋗ \lessdot \gtrdot ⋖ ⋗
⋖ \lessdot ⋖
⋗ \gtrdot ⋗
/ / /
⋗ ⋖ \gtrdot \lessdot ⋗ ⋖
⋖ ⋗ \lessdot \gtrdot ⋖ ⋗
⋖ ⋗ \lessdot \gtrdot ⋖ ⋗
⋖ ⋗ \lessdot \gtrdot ⋖ ⋗
⋖ \lessdot ⋖
⋗ \gtrdot ⋗
i d id i d
⋗ \gtrdot ⋗
⋗ \gtrdot ⋗
⋗ \gtrdot ⋗
⋗ \gtrdot ⋗
⋗ \gtrdot ⋗
$ \$ $
⋖ \lessdot ⋖
⋖ \lessdot ⋖
⋖ \lessdot ⋖
⋖ \lessdot ⋖
⋖ \lessdot ⋖