370 likes | 550 Views
ניתוח תחבירי ( Parsing ) - המשך. תזכורת: סוגי הניתוח התחבירי. top-down – מהשורש לעלים (נקרא גם – "ניתוח תחזית" – predictive ) bottom-up – מהעלים לשורש – מעבירים למחסנית, או מחליפים צד ימין בסימן מהצד השמאלי של חוק הדקדוק (shift reduce). s. . x y. s. x y.
E N D
תזכורת: סוגי הניתוח התחבירי • top-down – מהשורש לעלים (נקרא גם – "ניתוח תחזית" – predictive) • bottom-up – מהעלים לשורש – מעבירים למחסנית, או מחליפים צד ימין בסימן מהצד השמאלי של חוק הדקדוק (shift reduce) s x y s x y
אלגוריתם LR(k) • אלגוריתם LR(k) הוא אלגוריתם: • bottom-up, • מבוסס טבלאות, • סורק את הקלט משמאל (L) לימין, • מניב את הגזירה הימנית (R) ביותר, • וזקוק ל-lookahead בגודל k. • המקרה הפשוט ביותר הוא אלגוריתם LR(0).
שפות LL(k) • שפה נקראת LR(k) אם אפשר לגזור אותה בעזרת LR(k) parser. • כל שפה LL(n) היא גם LR(n) – אבל לא להיפך. • כלומר, LR מכיל ממש את LL.
אלגוריתם LR(0) קלט טבלת פעולות Parser מחסנית טבלת goto פלט
דקדוק פשוט לדוגמא... • נשתמש בדקדוק הבא לצורך הדגמה: E → E * B | E + B | B B → 0 | 1 • ממוספר, בצורה מסודרת: (1) E → E * B (2) E → E + B (3) E → B (4) B → 0 (5) B → 1
המחסנית • המחסנית ב-LR מכילה מצבים (מזוהים על-ידי מספר). • לצורך קריאות, נכלול במחסנית גם משתנים ואסימונים. למעשה, אין בכך צורך אמיתי מבחינת האלגוריתם. • למעט מצב "0" שנמצא בתחתית המחסנית, כל שאר המחסנית תהיה מורכבת מזוגות של מצב+משתנה או מצב+אסימון. • המחסנית ההתחלתית מכילה רק את מצב "0".
טבלת הפעולות • טבלה זו מכתיבה את הפעולה לביצוע בכל שלב. • שורות הטבלה: מצבים (על-פי מספרים). • עמודות הטבלה: אסימונים אפשריים בקלט. • תוכן הטבלה: הוראות ביצוע.
הוראות ביצוע • הוראות הביצוע בטבלת הפעולות יכולות להיות: • shift n • מסומנת sn (למשל s1, s2 וכו') • פירושה: העברת תו הקלט הבא למחסנית, ומעבר למצב n • reduce m • מסומנת rm (למשל r1, r2 וכו') • פירושה: זיהינו כלל גזירה מס' m • accept • מסומנת acc • פירושה: הקלט נגזר בהצלחה. • תאים ריקים – שגיאה בקלט.
טבלת Goto • טבלת העזר השנייה משמשת במקרים בהם זיהינו גזירה של כלל. • שורות הטבלה: מצבים • עמודות הטבלה: משתנים • תוכן הטבלה: מצבים. • היות שלשתי הטבלאות אותן שורות, מקובל להציג אותן זו-לצד-זו.
למשל... (1) E → E * B (2) E → E + B (3) E → B (4) B → 0 (5) B → 1
שאלה... • עבור כל כלל rm, מדובר בכלל גזירה m • אבל מה מסמנים המספרים עבור כללי sn? • מהו טווח הערכים של n?
האלגוריתם • אתחול המחסנית: "0" • מצא את action[t, i] (t ראש המחסנית, i אסימון הקלט הבא): • אם מצאת shift n: • הסר את האסימון i מהקלט, • הוסף את i ואח"כ את n למחסנית. • אם מצאת reduce m: • יהי w מספר התווים בצד ימין של כלל הגזירה מספר m. הסר 2w ערכים מהמחסנית. • יהי M המשתנה שגוזר כלל m. הוסף את M למחסנית. • מצא את goto[t, M] (t ראש המחסנית החדש) והוסף אותו למחסנית. • אם מצאת acc: סיום בהצלחה. • אחרת: סיום בשגיאה. • המשך עד לעצירה.
בניית הטבלה • ... למרבה הצער, הפעם לא בתרגול אלא בהרצאה. • ראשית, כמה הגדרות.
פריטי LR(0) • הגדרה:פריט LR(0) (או בקיצור פריט, ובעברית item) הוא כלל גזירה עם "נקודה" מיוחדת בתוכו. • מכלל גזירה עם n רכיבים מצד ימין ניתן לקבל n+1 פריטים. • למשל, עבור הכלל E → E + B (3 רכיבים מימין)נקבל את 4 הפריטים הבאים: E → ∙ E + B E → E ∙ + B E → E + ∙ B E → E + B ∙ • כלל ε נחשב לכלל באורך 0, לכן מהכלל A → ε ניתן לקבל רק את הפריט: A → ∙
מה משמעותו של פריט? • פריט אינו באמת כלל גזירה (בכללים האמיתיים אין את הנקודה). • פריט מסמל את מצבו של ה-parser. • משמעותו: זיהינו את מה שנמצא לפני הנקודה; אנו מצפים כעת למצוא את מה שנמצא אחריה. • למשל, הפריט: E → E ∙ + B מסמן כי ה-parser זיהה מחרוזת המתאימה ל-E בקלט, והוא כעת מצפה למצוא "+" ואחר-כך מחרוזת התמאימה ל-B.
קבוצות של פריטים • למרבה הצער, בדרך-כלל לא ניתן לתאר את מצב ה-parser בעזרת פריט יחיד. • למשל, אם זיהינו מחרוזת המתאימה ל-E, אנו עשויים להיות במצב E → E ∙ + B • ... אבל מצד שני, אולי אנו במצב E → E ∙* B • לכן מציינים את מצבו של ה-parser בעזרת קבוצה של פריטים. • למשל, {E → E ∙ + B , E → E ∙* B}
סגור של קבוצת פריטים • אם קבוצת הפריטים הנוכחית כוללת מצב שבו הנקודה נמצאת לפני משתנה, קשה לדעת מה צריך להיות הפריט הבא בקלט. • לשם כך בונים את קבוצת הסגור של קבוצת הפריטים. • הגדרה:קבוצת הסגור של קבוצת פריטים: קבוצת פריטים שבה, עבור כל פריט מהצורה A → α∙ B β בקבוצת הסגור, ועבור כל כלל מהצורה B → δ בדקדוק, גם הפריט B → ∙δ נמצא בקבוצת הסגור. • בניית קבוצת הסגור היא איטרטיבית, משום שגם δ עשוי להתחיל במשתנה.
סגור של קבוצת פריטים – דוגמא • למשל, עבור קבוצת הפריטים: C = { E → E + ∙ B } • ובהנתן הדקדוק מהדוגמאות הקודמות, • קבוצת הסגור היא: clos(C) = { E → E + ∙ B , B → ∙ 0 , B → ∙ 1 }
דקדוק מורחב • הגדרה:דקדוק מורחב הוא דקדוק שהוסיפו לו כלל יחיד, המבטיח שהגזירה האחרונה היא חד-משמעית בהיותה אחרונה. • הרחבת הדקדוק מתבצעת על-ידי הוספת כלל גזירה S → G, כאשר: • S משתנה שלא היה קיים בדקדוק לפני-כן, והוא כעת המשתנה הראשון, • G המשתנה הראשון המקורי של הדקדוק. • נהוג למספר את הכלל החדש "0". (0) S → E (1) E → E * B (2) E → E + B (3) E → B (4) B → 0 (5) B → 1
מכונת המצבים והמצב ההתחלתי • בבניית הטבלאות, אנו בונים למעשה מכונת מצבים דטרמיניסטית שכל מצב שלה מסומן על-ידי קבוצת סגור כלשהי של פריטים. • המצב ההתחלתי הוא הסגור של הפריט הראשון מהכלל שהוספנו בבניית הדקדוק המורחב: S → ∙ G. • S → ∙ E בדוגמא שלנו. • המצב ההתחלתי בדוגמא שלנו הוא: clos({S → ∙ E }) = {S → ∙ E , E → ∙ E * B , E → ∙ E + B , E → ∙ B , B → ∙ 0 , B → ∙ 1} • זוהי "קבוצת פריטים 0".
המצבים הבאים • איך מוצאים לאילו מצבים ניתן להגיע ממצב נתון? • א. מצא את כל הפריטים במצב הנוכחי, שבהם הנקודה נמצאת לפני סימן נתון כלשהו x. • x יכול להיות אסימון או משתנה. • נסמן קבוצת פריטים זו S (תת-קבוצה של המצב הנוכחי). • ב. הזז את הנקודה צעד אחד ימינה עבור כל הפריטים ב-S. • ג. מצא את הסגור של הקבוצה שהתקבלה. • כל clos(S) שנמצא בעזרת הכללים הללו הוא מצב חדש שניתן להגיע אליו מהמצב הנוכחי.
למשל: מצבים שניתן להגיע אליהם ממצב 0 בדוגמא מצב 2: x = 1 S2 = { B → ∙ 1 } S2 = { B → 1 ∙ } clos(S2) = { B → 1 ∙ } מצב 1: x = 0 S1 = { B → ∙ 0 } S1 = { B → 0 ∙ } clos(S1) = { B → 0 ∙ } מצב 4: x = B S4 = { E → ∙ B } S4 = { E → B ∙ } clos(S4) = { E → B ∙ } מצב 3: x = E S3 = { S → ∙ E , E → ∙ E * B , E → ∙ E + B } S3 = { S → E ∙ , E → E ∙ * B , E → E ∙ + B } clos(S3) = {S → E ∙ , E → E ∙ * B , E → E ∙ + B }
ממשיכים... • ממשיכים למצוא את כל המצבים שניתן להגיע אליהם מכל אחד מהמצבים שמצאנו עד כה. • ממצבים 1, 2 ו-4 בדוגמאות עד כה אין מצבי המשך (משום שהנקודה תמיד נמצאת בסוף כל פריט בקבוצת הסגור). • ממצב 3 ניתן להגיע למצבים חדשים: מצב 5: x = * S5 = { E → E ∙ * B } S5 = { E → E * ∙ B } clos(S5) = { E → E * ∙ B , B → ∙ 0 , B → ∙ 1 } מצב 6: clos(S6) = { E → E + ∙ B , B → ∙ 0 , B → ∙ 1 }
וממשיכים... • ממצב 5 ניתן להתקדם בעזרת הסימנים 0, 1 ו-B (כערכים עבור x). • אבל עבור x = 0 ועבור x = 1 נגיע שוב למצבים 1 ו-2, בהתאמה. • עבור x=B: • באופן דומה, ממצב 6, עבור x=B, נקבל את: • למצבים אלה אין מצבי המשך (מדוע?) מצב 7: clos(S7) = { E → E * B ∙ } מצב 8: clos(S7) = { E → E + B ∙ }
בניית הטבלאות: טבלת המעברים הראשונית • שורה עבור כל מצב. • מתייחסים לטבלאות כאל טבלת מעברים של האוטומט. • בשורה של מצב a, בעמודה שהיא ה-x ששימש לבניית מצב b, רושמים את b.
בניית הטבלאות: מצבי הסיום • מוסיפים acc בעמודה $ עבור כל מצב, שקבוצת הפריטים שלו כוללת את הפריט S → E ∙
בניית הטבלאות: פעולות shift • כל ערך מספרי n בטבלת הפעולות הופך להוראת sn.
בניית הטבלאות: פעולות reduce • עבור כל מצב, שקבוצת הפריטים שלו כוללת את A → α ∙ כך שקיים בדקדוק כלל A → α שמספרו m (m>0): ממלאים את השורה של מצב זה (בטבלת הפעולות) בערך rm.
מחסנית האלגוריתם • אמרנו שמחסנית ה-parser מכילה מספרי מצב וסמלים לסירוגין. • סמל = אסימון או משתנה. • אמרנו גם שלמעשה, האלגוריתם זקוק רק למספרי המצב שבמחסנית. • הסמלים במחסנית מאפשרים לנו לקרוא את המחסנית כמסלול באוטומט של האלגוריתם. • הסמלים שבין המצבים מסמנים את הקשתות דרכן עברנו.
מחסנית האלגוריתם • למשל, אם המחסנית ברגע נתון היא: 2 1 6 + 3 E 0 E 2 0 3 1 + 6
סוגי LR • הטבלה שבנינו היא טבלה עבור LR(0). • זאת משום שכללי reduce נוצרו רק על-ידי הפיכת שורה שלמה לשורה של הוראות reduce. • כלומר, מבצעים reduce ללא תלות באסימון שבקלט – או במילים אחרות, אפס lookahead. • ישנם שיפורים לאלגוריתם הבנייה... • אלגוריתם CLR (Cannonic LR) או LR(1) – חזק אבל "כבד" • אלגוריתם LALR (Look Ahead LR) – פשרה סבירה.
קונפליקטים בטבלאות • כשמוסיפים הוראות reduce לשורה בטבלת הפעולות, לא מוחקים מה שכבר קיים בשורה זו. • לכן ייתכן שבתאים מסוימים בטבלה יש שני ערכים (או יותר). • מקרים כאלה נקראים קונפליקטים.
קונפליקט reduce/reduce • קונפליקט reduce/reduce נוצר כשבתא אחד יש כמה אפשרויות שונות ל-reduce. • למשל, נסו ליצור את הטבלה עבור הדקדוק הבא: E → A 1 E → B 1 A → 1 B → 1
קונפליקט shift/reduce • כשבתא אחד יש גם הוראת reduce וגם הוראת shift, מקבלים קונפליקט shift/reduce. • למשל, עבור הדקדוק הבא: E → 1 E E → 1
קונפליקטים • מה הפירוש הסמנטי של קונפליקט המתקבל בדקדוק? • כיצד ניתן להתגבר על קונפליקטים?