LL ve LR ayrıştırma arasındaki fark nedir?


Yanıtlar:


484

Yüksek düzeyde, LL ayrıştırma ve LR ayrıştırma arasındaki fark, LL ayrıştırıcılarının başlangıç ​​sembolünde başlaması ve hedef dizgeye ulaşmak için üretimleri uygulamaya çalışmasıdır, oysa LR ayrıştırıcıları hedef dizgide başlar ve başlangıçta geri gelmeye çalışır. sembolü.

LL ayrıştırma soldan sağa, en soldaki bir türevdir. Yani, giriş sembollerini soldan sağa doğru düşünüyoruz ve en soldaki bir türev oluşturmaya çalışıyoruz. Bu, başlangıç ​​sembolünden başlayarak ve hedef dizgeye gelene kadar en soldaki terminal olmayanı tekrar tekrar genişleterek yapılır. LR ayrıştırma soldan sağa, en sağdaki bir türevdir, yani soldan sağa tarama yaparız ve en sağdaki bir türev oluşturmaya çalışırız. Ayrıştırıcı, sürekli olarak girdinin bir alt dizesini alır ve onu bir terminal olmayana geri döndürmeye çalışır.

LL ayrıştırma sırasında, ayrıştırıcı sürekli olarak iki eylem arasında seçim yapar:

  1. Tahmin : En soldaki nonterminal ve bazı ileriye doğru belirteçlere dayanarak, giriş dizesine yaklaşmak için hangi üretimin uygulanması gerektiğini seçin.
  2. Eşleştir : En soldaki tahmin edilen terminal sembolünü, en soldaki tüketilmemiş giriş simgesiyle eşleştirin.

Örnek olarak, bu dilbilgisi göz önüne alındığında:

  • S → E
  • E → T + E
  • E → T
  • T → int

Daha sonra dize verildiğinde int + int + int, bir LL (2) ayrıştırıcısı (iki ileriye doğru göz işareti kullanır) dizeyi aşağıdaki gibi ayrıştırır:

Production       Input              Action
---------------------------------------------------------
S                int + int + int    Predict S -> E
E                int + int + int    Predict E -> T + E
T + E            int + int + int    Predict T -> int
int + E          int + int + int    Match int
+ E              + int + int        Match +
E                int + int          Predict E -> T + E
T + E            int + int          Predict T -> int
int + E          int + int          Match int
+ E              + int              Match +
E                int                Predict E -> T
T                int                Predict T -> int
int              int                Match int
                                    Accept

Her adımda üretimimizdeki en soldaki sembole baktığımıza dikkat edin. Eğer bir terminal ise, onu eşleştiriyoruz ve eğer bir terminal olmayan ise, kurallardan birini seçerek bunun ne olacağını tahmin ediyoruz.

Bir LR ayrıştırıcısında iki eylem vardır:

  1. Shift : Değerlendirilmek üzere bir ara belleğe girişin bir sonraki belirtecini ekleyin.
  2. Azalt : Bir üretimi tersine çevirerek bu arabellekteki terminaller ve terminal olmayan bir koleksiyonu bir miktar terminal olmayana geri azaltın.

Örnek olarak, bir LR (1) ayrıştırıcısı (bir belirteç gözüyle) aynı dizeyi aşağıdaki gibi ayrıştırabilir:

Workspace        Input              Action
---------------------------------------------------------
                 int + int + int    Shift
int              + int + int        Reduce T -> int
T                + int + int        Shift
T +              int + int          Shift
T + int          + int              Reduce T -> int
T + T            + int              Shift
T + T +          int                Shift
T + T + int                         Reduce T -> int
T + T + T                           Reduce E -> T
T + T + E                           Reduce E -> T + E
T + E                               Reduce E -> T + E
E                                   Reduce S -> E
S                                   Accept

Bahsettiğiniz iki ayrıştırma algoritmasının (LL ve LR) farklı özellikleri olduğu bilinmektedir. LL ayrıştırıcıları elle yazmak daha kolay olma eğilimindedir, ancak LR ayrıştırıcılarından daha az güçlüdür ve LR ayrıştırıcılarından çok daha küçük gramer kümesini kabul eder. LR ayrıştırıcılar birçok aromada gelir (LR (0), SLR (1), LALR (1), LR (1), IELR (1), GLR (0), vb.) Ve çok daha güçlüdür. Ayrıca çok daha karmaşık olma eğilimindedirler ve neredeyse her zaman yaccveya gibi araçlar tarafından üretilirler bison. LL ayrıştırıcıları aynı zamanda birçok tat ile gelirler ( ANTLRalet tarafından kullanılan LL (*) dahil ), ancak pratikte LL (1) en yaygın olarak kullanılır.

Utanmaz bir fiş olarak, LL ve LR ayrıştırma hakkında daha fazla bilgi edinmek istiyorsanız, bir derleyici kursu öğretmeyi bitirdim ve kurs web sitesinde ayrıştırma hakkında bazı el notları ve ders slaytları aldım . Yararlı olduğunu düşünüyorsanız, bunlardan herhangi birini ayrıntılandırmaktan memnuniyet duyarım.


40
Ders slaytlarınız olağanüstü, kolayca gördüğüm en eğlenceli açıklama :) Bu gerçekten ilgi çeken bir şey.
kizzx2

1
Ben de slaytlar üzerinde yorum yapmak zorunda! Şimdi hepsini gözden geçiriyorum. Çok yardımcı olur! Teşekkürler!
kornfridge

Gerçekten slaytlar çok zevk. Proje dosyalarının Windows olmayan sürümünü (ve pp2 için scanner.l dosyasını) yükleyebileceğinizi düşünmüyorum? :)
Erik P.

1
Matt'in mükemmel özet yanıtına katkıda bulunabileceğim tek şey, bir LL (k) ayrıştırıcısı tarafından ayrıştırılabilecek herhangi bir dilbilgisinin (yani, bir sonraki ayrıştırma eylemine karar vermek için "k" terminallerine bakılması) bir LR ( 1) ayrıştırıcı. Bu, LR'nin LL ayrıştırma üzerindeki inanılmaz gücüne bir ipucu verir. Kaynak: LALR () ayrıştırıcılarının yaratıcısı Dr. F. DeRemer tarafından verilen UCSC'de derleyici kursu.
JoGusto

1
Mükemmel kaynak! Slaytlar, çalışma kağıtları, projeler sağladığınız için teşekkür ederiz.
P. Hinker

58

Josh Haberman LL ve LR Ayrıştırma makalesinde Demystified , LL ayrıştırma işleminin doğrudan Polonya Notasyonu ile , LR ise Ters Lehçe Notasyonu ile karşılık geldiğini iddia etmektedir . PN ve RPN arasındaki fark, denklemin ikili ağacını geçme sırasıdır:

bir denklemin ikili ağacı

+ 1 * 2 3  // Polish (prefix) expression; pre-order traversal.
1 2 3 * +  // Reverse Polish (postfix) expression; post-order traversal.

Haberman'a göre, bu LL ve LR ayrıştırıcıları arasındaki temel farkı göstermektedir:

LL ve LR ayrıştırıcılarının nasıl çalıştığı arasındaki temel fark, bir LL ayrıştırıcısının ayrıştırma ağacının bir ön sipariş çapraz geçişini ve bir LR ayrıştırıcı bir sipariş sonrası çapraz geçiş çıkışı vermesidir.

Ayrıntılı açıklama, örnekler ve sonuçlar için Haberman'ın makalesine göz atın .


9

LL yukarıdan aşağıya, LR aşağıdan yukarıya yaklaşımını kullanır.

Programlama dilini ayrıştırırsanız:

  • LL, ifade içeren fonksiyonlar içeren bir kaynak kodu görür.
  • LR, tam kaynağa neden olan işlevlere ait ifadeyi görür.

6

LL ayrıştırma, LR ile karşılaştırıldığında özürlüdür. LL ayrıştırıcı üreteci için bir kabus olan bir gramer:

Goal           -> (FunctionDef | FunctionDecl)* <eof>                  

FunctionDef    -> TypeSpec FuncName '(' [Arg/','+] ')' '{' '}'       

FunctionDecl   -> TypeSpec FuncName '(' [Arg/','+] ')' ';'            

TypeSpec       -> int        
               -> char '*' '*'                
               -> long                 
               -> short                   

FuncName       -> IDENTIFIER                

Arg            -> TypeSpec ArgName         

ArgName        -> IDENTIFIER 

Bir FunctionDef, ';' veya '{' ile karşılaşıldı.

LL ayrıştırıcısı aynı anda iki kuralı işleyemediğinden, FunctionDef veya FunctionDecl seçeneklerinden birini seçmelidir. Ama hangisinin doğru olduğunu bilmek için bir ';' veya '{'. Dilbilgisi analizi zamanında, önden okuma (k) sonsuz gibi görünmektedir. Ayrıştırma zamanında sonludur, ancak büyük olabilir.

Bir LR ayrıştırıcısı ileriye bakmak zorunda değildir, çünkü aynı anda iki kuralı işleyebilir. Böylece LALR (1) ayrıştırıcı jeneratörleri bu dilbilgisini kolaylıkla kullanabilir.

Giriş kodu verildiğinde:

int main (int na, char** arg); 

int main (int na, char** arg) 
{

}

Bir LR ayrıştırıcısı

int main (int na, char** arg)

umursamadan hangi kuralın bir ';' veya bir '{'.

LL ayrıştırıcısı hangi kuralın tanındığını bilmesi gerektiğinden “int” e asılır. Bu nedenle bir ';' veya '{'.

LL ayrıştırıcıları için diğer kabus bir dilbilgisi içinde özyinelemedir. Sol özyineleme gramerlerde normal bir şeydir, bir LR ayrıştırıcı jeneratörü için sorun değil, ancak LL bunu kaldıramaz.

Bu yüzden dilbilgilerinizi LL ile doğal olmayan bir şekilde yazmalısınız.


0

En Soldan Türev Örnek: Bağlamdan bağımsız bir gramer G'nin üretimleri vardır

z → xXY (Kural: 1) X → Ybx (Kural: 2) Y → bY (Kural: 3) Y → c (Kural: 4)

W = 'xcbxbc' dizesini en soldaki türevle hesaplayın.

z ⇒ xXY (Kural: 1) ⇒ xYbxY (Kural: 2) ⇒ xcbxY (Kural: 4) ⇒ xcbxbY (Kural: 3) ⇒ xcbxbc (Kural: 4)


Sağ En türev elde etme Örnek: K → aKK (Kural: 1) A → b (Kural: 2)

W = 'aababbb' dizesini en doğru türev ile hesaplayın.

K ⇒ aKK (Kural: 1) ⇒ aKb (Kural: 2) ⇒ aaKKb (Kural: 1) ⇒ aaKaKKb (Kural: 1) ⇒ aaKaKbb (Kural: 2) ⇒ aaKabbb (Kural: 2) ⇒ aababbb (Kural: 2)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.