Κατέβασμα παρουσίασης
Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε
1
ניתוח תחבירי (Parsing) של דקדוקי LR(1)
תורת הקומפילציה הרצאה 6 ניתוח תחבירי (Parsing) של דקדוקי LR(1)
2
תזכורת: סוגי הניתוח התחבירי
top-down – מהשורש לעלים (נקרא גם – "ניתוח תחזית" – predictive) bottom-up – מהעלים לשורש – מעבירים למחסנית, או מחליפים צד ימין בסימן מהצד השמאלי של חוק הדקדוק (shift reduce) s x y s x y
3
גזירהbottom-up מסוג LR(k)
נאמר שדקדוק הוא LR(k) אם הוא ניתן לגזירה bottom-up ימנית ביותר תוך כדי סריקת הקלט משמאל לימין. שפה נקראת LR(k) אם אפשר לתאר אותה בעזרת דקדוק LR(k). אלגוריתם LR(k) הוא אלגוריתם: bottom-up, מבוסס טבלאות, סורק את הקלט משמאל (L) לימין, מניב את הגזירה הימנית (R) ביותר, וזקוק ל-lookahead בגודל k. המקרה הפשוט ביותר הוא אלגוריתם LR(0).
4
לגזירת LR יש יותר כח, אבל... לגזירה LR(k) יש יותר כוח: כל שפה LL(n) היא גם LR(n) – אבל לא להיפך. כלומר, מחלקת הדקדוקים LR(k) מכילה ממש את המחלקה LL(k). אבל, אנו סופרים lookahead באופן שונה בשני המקרים. בגזירת LL(k) האלגוריתם רואה k תווים מתוך הצד הימני של כלל הגזירה ואז הוא אמור לזהות את הכלל. בגזירת LR(k) האלגוריתם רואה את כל הצד הימני של הגזירה ועוד k תווים. רק אז הוא אמור לזהות את הכלל. בגזירת LL(0) מצפים מהאלגוריתם לזהות כל כלל לאחר קריאת כל החלק הימני שלו, בלי קריאת ההמשך.
5
אלגוריתם LR(0) קלט טבלת פעולות Parser מחסנית טבלת goto פלט
6
דקדוק לדוגמא, עבורו LR(0) אינו מספיק
נשתמש בדקדוק הבא: E → 1 E E → 1 הבעיה בגזירה bottom-up ללא lookahead: לאחר ראיית 1 בקלט, לא ניתן לדעת איזה מהכללים רלוונטי. הדקדוק מורחב וממוספר: (0) S → E (1) E → 1 E (2) E → 1
7
ייצור המצבים מצב 0 (התחלתי) מצב 1 clos({S → ∙ E}) = clos({E → 1 ∙ E, 1
מצב 2 clos({S → E ∙}) = {S → E ∙} E $ 1 2 3 מצב 3 clos({E → 1 E ∙}) = {E → 1 E ∙}
8
בניית טבלאות action ו-goto
מתחילים מטבלת המעברים. מוסיפים acc במקום המתאים... goto פעולות E $ 1 2 3
9
בניית טבלאות action ו-goto
מתחילים מטבלת המעברים. מוסיפים acc במקום המתאים. כל מעבר על-סמך אסימון הופך לפעולת shift... goto פעולות E $ 1 2 3 acc
10
בניית טבלאות action ו-goto
מתחילים מטבלת המעברים. מוסיפים acc במקום המתאים. כל מעבר על-סמך אסימון הופך לפעולת shift. לכל מצב עם פריט A → α∙, מוסיפים reduce מתאים לכל השורה... goto פעולות E $ 1 2 s1 3 acc
11
בניית טבלאות action ו-goto
מתחילים מטבלת המעברים. מוסיפים acc במקום המתאים. כל מעבר על-סמך אסימון הופך לפעולת shift. לכל מצב עם פריט A→α∙ מוסיפים reduce מתאים לכל השורה. מזהים קונפליקט. goto פעולות E $ 1 2 s1 3 r2 r2/s1 acc r1
12
ממה נובע הקונפליקט? הקונפליקט קיים כשהמכונה במצב 1 וקיים האסימון 1 בקלט. מצב 1 כולל את הפריטים: E → 1 ∙ E, E → 1 ∙, E → ∙ 1 E, E → ∙ 1 כלל פעולה אפשרי ראשון: אם במצב 1 רואים אסימון 1 בקלט, מבצעים shift ומתקדמים עם הפריטים E→∙1E, E→∙1 למצב הכולל פריטים E→1∙,E→1∙E. (זהו בעצם חזרה למצב 1.) כלל פעולה אפשרי שני: כשאנחנו במצב 1 (בלי שום קשר לקלט) מבצעים reduce לכלל הגזירה E → 1 בגלל הפריט E→1∙.
13
המגבלה של LR(0) E → 1 E E → 1 LR(0) לא יכול להכריע בין שני המצבים.
אבל לנו די פשוט לקבל החלטה: המילים בשפה הן 1n, והגזירות הם E ⇒ 1E ⇒ 11E ⇒ … ⇒ 11…1 . לכן מפעילים את הכלל E→1 רק כשמגלים את ה-1 האחרון בקלט. כלל בחירה ב-lookahead של אות אחת: אם עד עתה ראינו 1, ויש אחריו עוד 1, אז הכלל המתאים הוא E → 1 E, אם אין עוד 1 בקלט, הכלל המתאים הוא E → 1. ניסוח בעזרת follow שיתאים לפעולה אוטומטית: אין שום תבנית פסוקית שניתן לגזור שבה אחרי E בא האסימון 1. 1 ∉ follow(E). לכן, אם יש 1 בהמשך הקלט, לא גוזרים לפי E → 1, כדי לא ליצור תבנית שכוללת את "E1”. כלומר, מבצעים shift ולא reduce.
14
תיקון פשוט ל-LR(0) נתקן את LR(0) כך: צעד ה-reduce המקורי בבניית הטבלה:
לכל מצב עם פריט ∙A → α , מוסיפים reduce מתאים לכל השורה. הופך להיות: לכל מצב עם פריט ∙A → α , מוסיפים reduce מתאים בשורה זו, לכל עמודה שהאסימון שבראשה שייך ל-follow(A). האלגוריתם המשופר נקרא Simple LR(1) בקיצור: SLR(1), ועוד יותר בקיצור: SLR. יכול לזהות יותר שפות מ-LR(0) ללא קונפליקטים. ... אבל עדיין לא מספיק חזק עבור מרבית שפות התכנות.
15
דוגמא אותה SLR לא פותר נתבונן בדקדוק (החד-משמעי) הבא: (0) S’ → S
(2) S → R (3) L → * R (4) L → id (5) R → L (ניתן לחשוב עליו כעל דקדוק להשמות בשפת C, כאשר L ו-R הם l-value ו-r-value, בהתאמה. הוסיפו R→EXPR להשלמת התמונה).
16
מכונת המצבים מצב 3 S → R ∙ R מצב 0 S’ → ∙ S S → ∙ L = R S → ∙ R
L → ∙ id R → ∙ L S מצב 9 S → L = R ∙ מצב 1 S’ → S ∙ L מצב 2 S → L ∙ = R R → L ∙ = R * id מצב 5 L → id ∙ מצב 6 S → L = ∙ R R → ∙ L L → ∙ * R L → ∙ id מצב 4 L → * ∙ R R → ∙ L L → ∙ * R L → ∙ id * R * id L L id מצב 7 L → * R ∙ מצב 8 R → L ∙
17
הקונפליקט מצב 2 S → L ∙ = R R → L ∙ = נתבונן במצב 2:
אם יש = בקלט, ניתן לבצע shift 6. לעבור מפריט S → L ∙ = R לפריט S → L = ∙ R. אבל ניתן גם לבצע reduce לפי כלל גזירה 5: ∙ R → L. קונפליקט shift/reduce. האסימון = נמצא ב-follow(R) (כי S ⇒ L = R ⇒ * R = R ), ולכן הקונפליקט קיים גם ב-SLR(1). = מצב 6
18
איך מתגברים על הקונפליקט?
SLR מתייחס רק ל-follow של המשתנה A שיתקבל לאחר ה-reduce. אבל לפני A יש תבנית פסוקית שלמה שכבר ראינו (ונמצאת במחסנית). אם בראש המחסנית נמצאת המחרוזת α, וקיים כלל A→α, SLR בודק את follow(A) מול האסימון שבקלט. ("ראש המחסנית" בדיון זה מתייחס לסמלים שבמחסנית ומתעלם מהמצבים שבה). אבל אולי בהמשך המחסנית, מעבר ל-α, נמצאים סמלים שעומדים בסתירה לאסימון שבקלט? למשל, אם התבנית שכרגע בראש המחסנית היא βα, ואסימון הקלט לא שייך ל-follow(βA), אז לא נרצה לבצע reduce לפי הכלל A→α. שימו לב שמתחשבים ביותר מידע, ובפרט, follow(βA) follow(A)
19
איך מתגברים על הקונפליקט?
בדוגמא שלנו, אפשר להגיע למצב 2 רק ישירות ממצב 0: כלומר ההקשר לביצוע reduce לפי R→L במצב 2, הוא הגזירות S → R → L; אבל בסדרת הגזירות האלו נצפה לראות אחרי כן $ בקלט, לא =. )אין תבנית המתחילה ב = R; אם נבצע reduce נתקע עם =.) זאת בהשוואה לביצוע reduce לפי R→L במצב 8, הנובע מהגזירות S → L = R →…, שאז נצפה גם ל-$ וגם ל- =. מצב 0 מצב 2 S → L ∙ = R R → L ∙ L
20
אלגוריתם Canonical LR (CLR)
הרעיון: לפרק את המצבים של LR(0) למצבים "עדינים" יותר, המכילים יותר מידע, ובפרט lookahead. לשם כך נגדיר מהו פריט LR(1), ונגדיר את פונקצית הסגור עבור פריטי LR(1). מעבר לכך, שאר האלגוריתם נותר ללא שינוי.
21
פריט LR(1) הגדרה: פריט LR(1) מורכב מזוג סדור: פריט LR(0) ואסימון (או סימן סוף הקלט, $). מכלל גזירה עם n רכיבים מצד ימין, בדקדוק בו קיימים t אסימונים, ניתן לקבל (n+1)·(t+1) פריטי LR(1). למשל מהכלל L → id מהדקדוק הקודם נקבל 8 פריטי LR(1): [L → ● id, *] [L → ● id, =] [L → ● id, id] [L → ● id, $] [L → id ●, *] [L → id ●, =] [L → id ●, id] [L → id ●, $]
22
מה משמעותו של פריט LR(1)? גם הפעם, פריט מסמל את מצבו של ה-parser.
משמעותו: זיהינו את מה שנמצא משמאל לנקודה; אנו מצפים כעת למצוא את מה שנמצא מימין לה, ולאחר מכאן את האסימון המצורף לפריט. למשל, הפריט: [S→ L ● = R, id] פירושו: פגשנו L, אנו מצפים ל- = ולאחר מכן ל- R (כלומר, סדרה הנגזרת מ-R), ואח"כ ל- id.
23
סגור של פריטי LR(1) הגדרה: קבוצת הסגור של קבוצת פריטי LR(1): קבוצת פריטי LR(1) שבה, עבור כל פריט LR(1) מהצורה [A → α ● Bβ , a] בקבוצת הסגור, ועבור כל כלל מהצורה B→δ וכל אסימון b בדקדוק (כולל $), כך ש- b FIRST(βa) , גם הפריט [B → ● δ , b] נמצא בקבוצת הסגור. המצב הראשון מתקבל מסגור של הפריט [S’→ ● S , $]
24
בניית הטבלאות כמו ב-SLR, מתחילים מטבלת המעברים של האוטומט.
הופכים כל מעבר בעמודה של אסימון לפעולת shift. עמודות המשתנים הן טבלת ה-goto. ה-acc מושם בעמודת $, בשורה של כללים המכילים את הפריט [S’ → S●, $]. עבור כל מצב המכיל פריט מהצורה [A → β●,a], וכלל A→β שמספרו m (m>0), שמים reduce m בשורה של מצב זה, בעמודה של אסימון a.
25
מכונת המצבים מצב 3 (S → R ∙ , $) מצב 0 (S’ → ∙ S , $)
(S → ∙ L = R , $) (S → ∙ R , $) (L → ∙ * R , = ) (L → ∙ id , = ) (R → ∙ L , $ ) (L → ∙ id , $ ) (L → ∙ * R , $ ) מכונת המצבים R (0) S’ → S (1) S → L = R (2) S → R (3) L → * R (4) L → id (5) R → L S מצב 1 (S’ → S ∙ , $) מצב 2 (S → L ∙ = R , $) (R → L ∙ , $) L = * מצב 6 (S → L = ∙ R , $) (R → ∙ L , $) (L → ∙ * R , $) (L → ∙ id , $) מצב 4 (L → * ∙ R , =) (R → ∙ L , =) (L → ∙ * R , =) (L → ∙ id , =) (L → * ∙ R , $) (R → ∙ L , $) (L → ∙ * R , $) (L → ∙ id , $) id מצב 5 (L → id ∙ , $) (L → id ∙ , =) * id L מצב 7 (L → * R ∙ , =) (L → * R ∙ , $) מצב 8 (R → L ∙ , =) (R → L ∙ , $) R
26
מכונת המצבים מצב 3 (S → R ∙ , $) מצב 0 (S’ → ∙ S , $)
(S → ∙ L = R , $) (S → ∙ R , $) (L → ∙ * R , = ) (L → ∙ id , = ) (R → ∙ L , $ ) (L → ∙ id , $ ) (L → ∙ * R , $ ) מכונת המצבים R מצב 9 (S → L = R ∙ , $) S מצב 1 (S’ → S ∙ , $) מצב 2 (S → L ∙ = R , $) (R → L ∙ , $) L = R * מצב 6 (S → L = ∙ R , $) (R → ∙ L , $) (L → ∙ * R , $) (L → ∙ id , $) מצב 4 (L → * ∙ R , =) (R → ∙ L , =) (L → ∙ * R , =) (L → ∙ id , =) (L → * ∙ R , $) (R → ∙ L , $) (L → ∙ * R , $) (L → ∙ id , $) id מצב 5 (L → id ∙ , $) (L → id ∙ , =) מצב 12 L * id מצב 10 * id L מצב 11 מצב 7 (L → * R ∙ , =) (L → * R ∙ , $) מצב 8 (R → L ∙ , =) (R → L ∙ , $) R
27
מכונת המצבים מצב 3 (S → R ∙ , $) R מצב 9 (S → L = R ∙ , $) מצב 11
(L → id ∙ , $) S מצב 1 (S’ → S ∙ , $) id R מצב 2 (S → L ∙ = R , $) (R → L ∙ , $) L = מצב 12 (R → L ∙ , $) id מצב 6 (S → L = ∙ R , $) (R → ∙ L , $) (L → ∙ * R , $) (L → ∙ id , $) L id מצב 5 (L → id ∙ , $) (L → id ∙ , =) מצב 10 (L → * ∙ R , $) (R → ∙ L , $) (L → ∙ * R , $) (L → ∙ id , $) L * * R id L R מצב 8 (R → L ∙ , =) (R → L ∙ , $) id מצב 7 (L → * R ∙ , =) (L → * R ∙ , $) מצב 13 (S → L = R ∙ , $)
28
נחזור למצב 2: האם יודעים לבחור בין shift ל-reduce?
(S → L ∙ = R , $) (R → L ∙ , $) = מצב 6 (S → L = ∙ R , $) (R → ∙ L , $) (L → ∙ * R , $) (L → ∙ id , $)
29
בניית הטבלה טבלת goto טבלת הפעולות L R S $ = * id 2 3 1 s4 s5 acc r5
acc r5 s6 r2 8 7 4 r4 5 9 12 s10 s11 6 r3 13 10 11 r1
30
שאלות מדוע יש יותר מצבים ב-CLR לעומת SLR? איך נראה CLR(k) עבור k>1?
Παρόμοιες παρουσιάσεις
© 2024 SlidePlayer.gr Inc.
All rights reserved.