Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε

Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε

1 תורת הקומפילציה 236360 הרצאה 6 ניתוח תחבירי (Parsing) של דקדוקי LR(1)

Παρόμοιες παρουσιάσεις


Παρουσίαση με θέμα: "1 תורת הקומפילציה 236360 הרצאה 6 ניתוח תחבירי (Parsing) של דקדוקי LR(1)"— Μεταγράφημα παρουσίασης:

1 1 תורת הקומפילציה הרצאה 6 ניתוח תחבירי (Parsing) של דקדוקי LR(1)

2 2 תזכורת : סוגי הניתוח התחבירי top-down – מהשורש לעלים ( נקרא גם – " ניתוח תחזית " – predictive) bottom-up – מהעלים לשורש – מעבירים למחסנית, או מחליפים צד ימין בסימן מהצד השמאלי של חוק הדקדוק (shift reduce) x y s  s

3 3 גזירה bottom-up מסוג LR(k) נאמר שדקדוק הוא LR(k) אם הוא ניתן לגזירה bottom-up ימנית ביותר תוך כדי סריקת הקלט משמאל לימין. שפה נקראת LR(k) אם אפשר לתאר אותה בעזרת דקדוק LR(k). אלגוריתם LR(k) הוא אלגוריתם : bottom-up, מבוסס טבלאות, סורק את הקלט משמאל (L) לימין, מניב את הגזירה הימנית (R) ביותר, וזקוק ל -lookahead בגודל k. המקרה הפשוט ביותר הוא אלגוריתם LR(0).

4 4 לגזירת LR יש יותר כח, אבל... לגזירה LR(k) יש יותר כוח : כל שפה LL(n) היא גם LR(n) – אבל לא להיפך. כלומר, מחלקת הדקדוקים LR(k) מכילה ממש את המחלקה LL(k). אבל, אנו סופרים lookahead באופן שונה בשני המקרים. בגזירת LL(k) האלגוריתם רואה k תווים מתוך הצד הימני של כלל הגזירה ואז הוא אמור לזהות את הכלל. בגזירת LR(k) האלגוריתם רואה את כל הצד הימני של הגזירה ועוד k תווים. רק אז הוא אמור לזהות את הכלל. בגזירת LL(0) מצפים מהאלגוריתם לזהות כל כלל לאחר קריאת כל החלק הימני שלו, בלי קריאת ההמשך.

5 5 אלגוריתם LR(0) מחסנית Parser קלט פלט טבלת פעולות טבלת goto

6 6 דקדוק לדוגמא, עבורו LR(0) אינו מספיק נשתמש בדקדוק הבא : E → 1 E E → 1 הבעיה בגזירה bottom-up ללא lookahead: לאחר ראיית 1 בקלט, לא ניתן לדעת איזה מהכללים רלוונטי. הדקדוק מורחב וממוספר : (0) S → E (1) E → 1 E (2) E → 1

7 7 ייצור המצבים מצב 0 (התחלתי) clos({S → ∙ E}) = {S → ∙ E, E → ∙ 1 E, E → ∙ 1} מצב 1 clos({E → 1 ∙ E, E → 1 ∙}) = {E → 1 ∙ E, E → 1 ∙, E → ∙ 1 E, E → ∙ 1} 1 מצב 2 clos({S → E ∙}) = {S → E ∙} מצב 3 clos({E → 1 E ∙}) = {E → 1 E ∙} E E E$ (0) S → E (1) E → 1 E (2) E → 1

8 8 בניית טבלאות action ו -goto goto פעולות E$ מתחילים מטבלת המעברים. מוסיפים acc במקום המתאים...

9 9 בניית טבלאות action ו -goto goto פעולות E$ acc2 3 מתחילים מטבלת המעברים. מוסיפים acc במקום המתאים. כל מעבר על - סמך אסימון הופך לפעולת shift...

10 10 בניית טבלאות action ו -goto מתחילים מטבלת המעברים. מוסיפים acc במקום המתאים. כל מעבר על - סמך אסימון הופך לפעולת shift. לכל מצב עם פריט A → α ∙, מוסיפים reduce מתאים לכל השורה... goto פעולות E$1 2s acc2 3

11 11 בניית טבלאות action ו -goto מתחילים מטבלת המעברים. מוסיפים acc במקום המתאים. כל מעבר על - סמך אסימון הופך לפעולת shift. לכל מצב עם פריט A → α ∙ מוסיפים reduce מתאים לכל השורה. מזהים קונפליקט. goto פעולות E$1 2s10 3r2r2/s11 acc2 r1 3

12 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 13 המגבלה של LR(0) LR(0) לא יכול להכריע בין שני המצבים. אבל לנו די פשוט לקבל החלטה : המילים בשפה הן 1 n, והגזירות הם 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. E → 1 E E → 1

14 14 תיקון פשוט ל -LR(0) נתקן את LR(0) כך : צעד ה -reduce המקורי בבניית הטבלה : לכל מצב עם פריט ∙A → α, מוסיפים reduce מתאים לכל השורה. הופך להיות : לכל מצב עם פריט ∙A → α, מוסיפים reduce מתאים בשורה זו, לכל עמודה שהאסימון שבראשה שייך ל -follow(A). האלגוריתם המשופר נקרא Simple LR(1) בקיצור : SLR(1), ועוד יותר בקיצור : SLR. יכול לזהות יותר שפות מ -LR(0) ללא קונפליקטים.... אבל עדיין לא מספיק חזק עבור מרבית שפות התכנות.

15 15 דוגמא אותה SLR לא פותר נתבונן בדקדוק ( החד - משמעי ) הבא : (0) S’ → S (1) S → L = R (2) S → R (3) L → * R (4) L → id (5) R → L ( ניתן לחשוב עליו כעל דקדוק להשמות בשפת C, כאשר L ו -R הם l-value ו - r-value, בהתאמה. הוסיפו R → EXPR להשלמת התמונה ).

16 16 מכונת המצבים מצב 0 S’ → ∙ S S → ∙ L = R S → ∙ R L → ∙ * R L → ∙ id R → ∙ L מצב 1 S’ → S ∙ מצב 2 S → L ∙ = R R → L ∙ מצב 3 S → R ∙ מצב 4 L → * ∙ R R → ∙ L L → ∙ * R L → ∙ id מצב 5 L → id ∙ מצב 6 S → L = ∙ R R → ∙ L L → ∙ * R L → ∙ id מצב 7 L → * R ∙ מצב 8 R → L ∙ מצב 9 S → L = R ∙ S L R id * = R * R L * L

17 17 הקונפליקט נתבונן במצב 2: אם יש = בקלט, ניתן לבצע shift 6. לעבור מפריט S → L ∙ = R לפריט S → L = ∙ R. אבל ניתן גם לבצע reduce לפי כלל גזירה 5: ∙ R → L. קונפליקט shift/reduce. האסימון = נמצא ב -follow(R) ( כי S ⇒ L = R ⇒ * R = R ), ולכן הקונפליקט קיים גם ב -SLR(1). מצב 2 S → L ∙ = R R → L ∙ מצב 6 =

18 18 איך מתגברים על הקונפליקט ? SLR מתייחס רק ל -follow של המשתנה A שיתקבל לאחר ה -reduce. אבל לפני A יש תבנית פסוקית שלמה שכבר ראינו ( ונמצאת במחסנית ). אם בראש המחסנית נמצאת המחרוזת α, וקיים כלל A → α, SLR בודק את follow(A) מול האסימון שבקלט.  (" ראש המחסנית " בדיון זה מתייחס לסמלים שבמחסנית ומתעלם מהמצבים שבה ). אבל אולי בהמשך המחסנית, מעבר ל -α, נמצאים סמלים שעומדים בסתירה לאסימון שבקלט ? למשל, אם התבנית שכרגע בראש המחסנית היא βα, ואסימון הקלט לא שייך ל -follow(βA), אז לא נרצה לבצע reduce לפי הכלל A → α. שימו לב שמתחשבים ביותר מידע, ובפרט, follow(βA)  follow(A)

19 19 איך מתגברים על הקונפליקט ? בדוגמא שלנו, אפשר להגיע למצב 2 רק ישירות ממצב 0: כלומר ההקשר לביצוע reduce לפי R → L במצב 2, הוא הגזירות S → R → L; אבל בסדרת הגזירות האלו נצפה לראות אחרי כן $ בקלט, לא =. ) אין תבנית המתחילה ב -... = R; אם נבצע reduce נתקע עם =.) זאת בהשוואה לביצוע reduce לפי R → L במצב 8, הנובע מהגזירות S → L = R → …, שאז נצפה גם ל -$ וגם ל - =. מצב 2 S → L ∙ = R R → L ∙ L מצב 0

20 20 אלגוריתם Canonical LR (CLR) הרעיון : לפרק את המצבים של LR(0) למצבים " עדינים " יותר, המכילים יותר מידע, ובפרט lookahead. לשם כך נגדיר מהו פריט LR(1), ונגדיר את פונקצית הסגור עבור פריטי LR(1). מעבר לכך, שאר האלגוריתם נותר ללא שינוי.

21 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 22 מה משמעותו של פריט LR(1)? גם הפעם, פריט מסמל את מצבו של ה -parser. משמעותו : זיהינו את מה שנמצא משמאל לנקודה ; אנו מצפים כעת למצוא את מה שנמצא מימין לה, ולאחר מכאן את האסימון המצורף לפריט. למשל, הפריט : [S → L ● = R, id] פירושו : פגשנו L, אנו מצפים ל - = ולאחר מכן ל - R ( כלומר, סדרה הנגזרת מ - R), ואח " כ ל - id.

23 23 סגור של פריטי LR(1) הגדרה : קבוצת הסגור של קבוצת פריטי LR(1): קבוצת פריטי LR(1) שבה, עבור כל פריט LR(1) מהצורה [A → α ● Bβ, a] בקבוצת הסגור, ועבור כל כלל מהצורה B → δ וכל אסימון b בדקדוק ( כולל $), כך ש - b  FIRST(βa), גם הפריט [B → ● δ, b] נמצא בקבוצת הסגור. המצב הראשון מתקבל מסגור של הפריט [S’ → ● S, $]

24 24 בניית הטבלאות כמו ב -SLR, מתחילים מטבלת המעברים של האוטומט. הופכים כל מעבר בעמודה של אסימון לפעולת shift. עמודות המשתנים הן טבלת ה -goto. ה -acc מושם בעמודת $, בשורה של כללים המכילים את הפריט [S’ → S ●, $]. עבור כל מצב המכיל פריט מהצורה [A → β ●, a ], וכלל A → β שמספרו m (m>0), שמים reduce m בשורה של מצב זה, בעמודה של אסימון a.

25 25 מכונת המצבים מצב 0 (S’ → ∙ S, $) (S → ∙ L = R, $) (S → ∙ R, $) (L → ∙ * R, = ) (L → ∙ id, = ) (R → ∙ L, $ ) (L → ∙ id, $ ) (L → ∙ * R, $ ) מצב 1 (S’ → S ∙, $) מצב 2 (S → L ∙ = R, $) (R → L ∙, $) מצב 3 (S → R ∙, $) מצב 4 (L → * ∙ R, =) (R → ∙ L, =) (L → ∙ * R, =) (L → ∙ id, =) (L → * ∙ R, $) (R → ∙ L, $) (L → ∙ * R, $) (L → ∙ id, $) מצב 5 (L → id ∙, $) (L → id ∙, =) מצב 6 (S → L = ∙ R, $) (R → ∙ L, $) (L → ∙ * R, $) (L → ∙ id, $) מצב 7 (L → * R ∙, =) (L → * R ∙, $) מצב 8 (R → L ∙, =) (R → L ∙, $) S L R id * = R * L (0) S’ → S (1) S → L = R (2) S → R (3) L → * R (4) L → id (5) R → L

26 26 מכונת המצבים מצב 0 (S’ → ∙ S, $) (S → ∙ L = R, $) (S → ∙ R, $) (L → ∙ * R, = ) (L → ∙ id, = ) (R → ∙ L, $ ) (L → ∙ id, $ ) (L → ∙ * R, $ ) מצב 1 (S’ → S ∙, $) מצב 2 (S → L ∙ = R, $) (R → L ∙, $) מצב 3 (S → R ∙, $) מצב 4 (L → * ∙ R, =) (R → ∙ L, =) (L → ∙ * R, =) (L → ∙ id, =) (L → * ∙ R, $) (R → ∙ L, $) (L → ∙ * R, $) (L → ∙ id, $) מצב 5 (L → id ∙, $) (L → id ∙, =) מצב 6 (S → L = ∙ R, $) (R → ∙ L, $) (L → ∙ * R, $) (L → ∙ id, $) מצב 7 (L → * R ∙, =) (L → * R ∙, $) מצב 8 (R → L ∙, =) (R → L ∙, $) מצב 9 (S → L = R ∙, $) S L R id * = R * R L * L מצב 11 מצב 12 מצב 10

27 27 מכונת המצבים מצב 1 (S’ → S ∙, $) מצב 2 (S → L ∙ = R, $) (R → L ∙, $) מצב 3 (S → R ∙, $) מצב 5 (L → id ∙, $) (L → id ∙, =) מצב 6 (S → L = ∙ R, $) (R → ∙ L, $) (L → ∙ * R, $) (L → ∙ id, $) מצב 7 (L → * R ∙, =) (L → * R ∙, $) מצב 8 (R → L ∙, =) (R → L ∙, $) מצב 9 (S → L = R ∙, $) S L R id = R R L * L מצב 10 (L → * ∙ R, $) (R → ∙ L, $) (L → ∙ * R, $) (L → ∙ id, $) מצב 11 (L → id ∙, $) מצב 12 (R → L ∙, $) מצב 13 (S → L = R ∙, $) id R L *

28 28 נחזור למצב 2: האם יודעים לבחור בין shift ל -reduce? מצב 2 (S → L ∙ = R, $) (R → L ∙, $) מצב 6 (S → L = ∙ R, $) (R → ∙ L, $) (L → ∙ * R, $) (L → ∙ id, $) =

29 29 בניית הטבלה טבלת goto טבלת הפעולות LRS$=*id 231s4s50 acc1 r5s62 r23 87s4s54 r s10s116 r3 7 r s10s1110 r411 r112 r313

30 30 שאלות מדוע יש יותר מצבים ב -CLR לעומת SLR? איך נראה CLR(k) עבור k>1? האם כל דקדוק חד - משמעי חסר - הקשר ניתן לניתוח ע " י מנתח CLR(k)?


Κατέβασμα ppt "1 תורת הקומפילציה 236360 הרצאה 6 ניתוח תחבירי (Parsing) של דקדוקי LR(1)"

Παρόμοιες παρουσιάσεις


Διαφημίσεις Google