Projekt kompilatora - analizator oddolny

Analiza oddolna rozpoczyna się od węzłów liści drzewa i działa w górę, aż dotrze do węzła głównego. Tutaj zaczynamy od zdania, a następnie stosujemy reguły produkcji w odwrotny sposób, aby dotrzeć do symbolu początku. Poniższy obraz przedstawia dostępne parsery oddolne.

Parsowanie Shift-Reduce

Analiza metodą Shift-Redukcja wykorzystuje dwa unikalne kroki do analizy oddolnej. Te kroki są znane jako krok przesunięcia i krok redukcji.

  • Shift step: Krok przesunięcia odnosi się do przesunięcia wskaźnika wejściowego do następnego symbolu wejściowego, który jest nazywany przesuniętym symbolem. Ten symbol jest kładziony na stosie. Przesunięty symbol jest traktowany jako pojedynczy węzeł drzewa parsowania.

  • Reduce step: Kiedy parser znajduje pełną regułę gramatyczną (RHS) i zastępuje ją (LHS), jest to znane jako krok redukcji. Dzieje się tak, gdy wierzchołek stosu zawiera uchwyt. Aby zmniejszyć, na stosie wykonywana jest funkcja POP, która wyskakuje z uchwytu i zastępuje go symbolem nieterminalowym LHS.

LR Parser

Parser LR jest parserem nierekurencyjnym, redukującym przesunięcie i oddolnym. Wykorzystuje szeroką klasę gramatyki bezkontekstowej, co czyni ją najbardziej wydajną techniką analizy składni. Parsery LR są również znane jako parsery LR (k), gdzie L oznacza skanowanie strumienia wejściowego od lewej do prawej; R oznacza konstrukcję wyprowadzenia położonego najbardziej na prawo w odwrotnej kolejności, a k oznacza liczbę symboli antycypowania do podejmowania decyzji.

Istnieją trzy powszechnie używane algorytmy do konstruowania parsera LR:

  • SLR (1) - Prosty parser LR:
    • Działa na najmniejszej klasie gramatyki
    • Niewielka liczba stanów, stąd bardzo mała tabela
    • Prosta i szybka konstrukcja
  • LR (1) - Parser LR:
    • Działa na pełnym zestawie gramatyki LR (1)
    • Generuje dużą tabelę i dużą liczbę stanów
    • Powolna konstrukcja
  • LALR (1) - Look-Ahead LR Parser:
    • Działa na gramatyce o średniej wielkości
    • Liczba stanów jest taka sama jak w lustrzance (1)

Algorytm analizy LR

Tutaj opisujemy szkieletowy algorytm parsera LR:

token = next_token()

repeat forever
   s = top of stack
   
   if action[s, token] = “shift si” then
      PUSH token
      PUSH si 
      token = next_token()
      
   else if action[s, token] = “reduce A::= β“ then 
      POP 2 * |β| symbols
      s = top of stack
      PUSH A
      PUSH goto[s,A]
      
   else if action[s, token] = “accept” then
      return
      
   else
      error()

LL kontra LR

LL LR
Wykonuje wyprowadzenie skrajnie lewe. Wykonuje prawe wyprowadzenie w odwrotnej kolejności.
Rozpoczyna się nieterminalem głównym na stosie. Kończy się nieterminalem głównym na stosie.
Kończy się, gdy stos jest pusty. Zaczyna się od pustego stosu.
Używa stosu do określenia tego, czego nadal można się spodziewać. Używa stosu do oznaczania tego, co jest już widoczne.
Buduje drzewo analizy od góry do dołu. Buduje drzewo parsowania od dołu do góry.
Ciągle zdejmuje nieterminal ze stosu i odkłada odpowiednią prawą stronę. Próbuje rozpoznać prawą stronę stosu, wyskakuje i odkłada odpowiedni nieterminal.
Rozwija nieterminale. Zmniejsza liczbę nie-terminali.
Odczytuje terminale, gdy zdejmuje jeden ze stosu. Odczytuje terminale, wpychając je na stos.
Zamów przeglądanie drzewa parsowania w przedsprzedaży. Przeglądanie drzewa parsowania po zamówieniu.