Download presentation
Presentation is loading. Please wait.
1
פרק 4 ניתוח התחביר תורת הקומפילציה איתן אביאור
2
ניתוח התחביר ניתוח (analysis) חיבור (synthesis)
מנתח תחביר syntax analyser מנתח משמעות semantic analyser מייצר קוד ביניים intermediate code generator מייעל קוד code optimizer מייצר קוד code generator מנתח לקסיקאלי lexical analyser מנתח תחביר syntax analyser תורת הקומפילציה איתן אביאור
3
תחביר (Syntax) של שפות מחשב
נוח לתאר את התחביר של שפת מחשב בעזרת דקדוק חסר הקשר דקדוק נותן מפרט תחבירי מדויק וקל להבנה של השפה מתוך דקדוקים בעלי תכונות מסוימות ניתן לבנות באופן אוטומטי פורסים יעילים בתהליך הבניה ניתן לגלות מצבים של רב-משמעות תחבירית דקדוק מתוכנן היטב מאפשר כתיבת תוכניות בעלות מבנה טוב המאפשר תרגומן לקוד מכונה נכון ויעיל דקדוק מסודר מאפשר לעדכן את הגדרת השפה עם הזמן באופן נוח תורת הקומפילציה איתן אביאור
4
היררכיה בהגדרת התחביר של שפה
הגדרת תמניות באמצעות ביטויים רגולרים ע"מ לפשט את הגדרת השפה ובנית המהדר הגדרת התחביר באמצעות דקדוק חסר הקשר הוספת כללים שאינם ניתנים להבעה ע"י דקדוק חסר הקשר כגון: "אין להשתמש במזהה לפני שהוצהר עליו" או הצורך בהתאמה בין הארגומנטים והפרמטרים של פונקציה (ראה דיון ב-ASU עמ' 179−181) תורת הקומפילציה איתן אביאור
5
ניתוח התחביר ─ מטרה קבלת זרם התמניות מהמנתח הלקסיקאלי
ניתוח זרם התמניות ע"פ כללי הגזירה ויצירת עץ הפריסה מציאת שגיאות תחביר והיחלצות מהן עדכון טבלת הסמלים תורת הקומפילציה איתן אביאור
6
ניתוח החיבור ─ השיטה תיאור הפסוקים בשפה באמצעות דקדוק חסר הקשר
ניתוח זרם התמניות ע"י הפעלת אלגוריתמים לפריסה stmt expr args if id relop num ( ) ; stmt if ( expr ) stmt | if ( expr ) stmt else stmt | while ( expr ) stmt מנתח התחביר if (id relop num) id(); תורת הקומפילציה איתן אביאור
7
יחס גומלין של מנתח התחביר
לקסיקאלי תחביר טבלת סמלים תמנית דרישה לתמנית הבאה שאר חלקי הצד הקדמי עץ הפריסה קוד ביניים תוכנית המקור תורת הקומפילציה איתן אביאור
8
שיטות לביצוע פריסה קיימות שיטות לפריסה אוניברסלית של כל דקדוק נתון
אינן יעילות לבנית מהדרים בפועל קיימות שיטות לפריסה של דקדוקים בעלי תכונות מיוחדות פריסה מלמעלה למטה (top-down) למשל עבור דקדוקי LL שימושית לבניה ידנית של פורס פריסה מלמטה למעלה (bottom-up) למשל עבור דקדוקי LR שימושית לבניה אוטומטית של פורס תורת הקומפילציה איתן אביאור
9
משימות נוספות המתבצעות תוך כדי הפריסה
הפורס מפעיל את הסורק ע"מ לייצר עבורו את זרם התמניות מפעיל את "שאר חלקי הצד הקדמי" ניתוח המשמעות עדכון טבלת הסמלים יצירת קוד ביניים תורת הקומפילציה איתן אביאור
10
טיפול בשגיאות סוגי השגיאות יעדי מטפל השגיאות שיטות לטיפול בשגיאות
תורת הקומפילציה איתן אביאור
11
סוגי שגיאות לקסיקאליות ─ למשל: איות לא נכון של מזהה, מלת מפתח או אופרטור תחביריות ─ למשל: חוסר איזון של סוגריים בביטוי אריתמטי משמעות ─ למשל: אופרטור המופעל על אופרנד בלתי-מתאים לוגיות ─ למשל: רקורסיה אינסופית חלק ניכר מהשגיאות המתגלות הן שגיאות תחביר: הרבה שגיאות הן אכן שגיאות תחביר ניתן לגלות בקלות שגיאות תחביר ואף לתקן חלק מהן קשה לגלות ולתקן שגיאות משמעות ושגיאות לוגיות תורת הקומפילציה איתן אביאור
12
יעדי מטפל השגיאות דיווח על הימצאות שגיאה במקום מסוים בבירור ובדייקנות
התאוששות מהשגיאה מהר ככל הניתן ע"מ לגלות שגיאות נוספות אסור שיאיט באופן משמעותי עיבוד של תוכניות נכונות תורת הקומפילציה איתן אביאור
13
שיטות לטיפול בשגיאות מצב פניקה (panic mode) רמת הביטוי (phrase level)
כללי גזירה לשגיאות (error productions) תיקון גלובלי (global correction) תורת הקומפילציה איתן אביאור
14
התאוששות ממצב פניקה (Panic Mode Recovery)
בעת שהפורס מגלה שגיאת תחביר הוא נכנס ל"מצב פניקה", ומדלג על כל התמניות עד שהוא מגיע לתמנית סינכרון תמנית סינכרון (synchronization token) ─ תמנית הבאה בסוף מבנה (משפט, סדרת משפטים) והמציינת את סופו דוגמאות: נקודה-פסיק ; סוגר מסולסל ימני { מלת מפתח end שיטה טובה בהנחה שמשפט מכיל לרוב רק שגיאת תחביר אחת מונעת כניסה ללולאה אינסופית של הפורס תורת הקומפילציה איתן אביאור
15
התאוששות ברמת הביטוי (Phrase Level Recovery)
בעת שהפורס מגלה שגיאה הוא מנסה לתקן אותה ע"י החלפת הרישא של המשך הקלט במחרוזת אחרת דוגמאות: החלפת פסיק בנקודה-פסיק מחיקת תו מיותר הוספת סימן חסר יש להיזהר לא להגיע למצב של לולאה אינסופית (למשל אם הטיפול בשגיאה הוא תמיד הוספת תו לפני שאר הקלט) תורת הקומפילציה איתן אביאור
16
התאוששות ע"י כללי גזירה לשגיאות (Error Production Recovery)
הדקדוק יכיל מראש כללי גזירה לשגיאות נפוצות בכללים האלה תשולבנה מראש הפעולות לביצוע בעת גילוי שגיאות אלה דוגמה: stmt if ( expr ) then stmt else stmt שימוש בכלל הגזירה הזה מעיד על הימצאות then מיותר תורת הקומפילציה איתן אביאור
17
תיקון גלובלי (Global Correction)
מציאת התוכנית הנכונה הקרובה ביותר לתוכנית המקורית יש להגדיר מטריקה בין תוכניות, למשל ע"י מספר השינויים הבסיסים שיש לבצע במעבר מתוכנית לתוכנית שינוי בסיסי: החלפת תו, מחיקת תו, הוספת תו, היפוך תווים טכניקה יקרה מאוד ליישום באופן גלובלי על כל התוכנית עשויה להיות שימושית כטכניקה מקומית בשיטת ההתאוששות ברמת הביטוי תורת הקומפילציה איתן אביאור
18
דקדוק (Grammar) ושפה (Language)
G ─ דקדוק (grammar) ─ G = T, N, P, S T ─ קבוצת טרמינלים (terminals) ─ האלף-בית N ─ קבוצת נונטרמינלים (nonterminals) ─ T N = P ─ כללי גזירה (productions) ─ מהצורה כאשר ו- הן מחרוזות של טרמינלים ו/או נונטרמינלים, או ש- הוא ε (המסמן את המחרוזת הריקה) S ─ סמל ההתחלה (start symbol) ─ S N L(G) ─ שפה (language) ─ אוסף כל המחרוזות מעל האלף-בית הניתנות ליצור ע"י הדקדוק (בהמשך הגדרה יותר מדוייקת) תורת הקומפילציה איתן אביאור
19
חוסר הקשר (Context Freedom)
דקדוק חסר הקשר (context free grammar) ― דקדוק בו כל כללי הגזירה הם מהצורה A כאשר A הינו נונטרמינל יחיד ( כמו קודם) שפה חסרת הקשר (context free language) ― שפה שעבורה קיים דקדוק חסר הקשר המייצר אותה דקדוק חסר הקשר ניתן להכרה ע"י אוטומט מחסנית רוב המבנים של שפות התכנות הקיימות ניתנים לתיאור באמצעות דקדוק חסר הקשר תורת הקומפילציה איתן אביאור
20
פורס (Parser) כלי המנתח את תוכניות המקור ע"פ דקדוק השפה
הטרמינלים ─ התמניות הנוצרות ע"י הסורק (scanner) הנונטרמינלים ─ משתנים המתארים צורות שונות של פסוקים ומבנים בשפה דוגמה: expr expr op expr expr ( expr ) expr - expr expr id op + op - op op / op טרמינלים: id / ( ) נונטרמינלים: expr op תורת הקומפילציה איתן אביאור
21
קונבנציות סימון טרמינלים א. אותיות קטנות מתחילת האלף-בית הלטיני
א. אותיות קטנות מתחילת האלף-בית הלטיני a b c ב. סמלי פעולה + - / ג. סמלי פיסוק ( ) , ; ד. הספרות ה. מחרוזות בגופן בולט id if תורת הקומפילציה איתן אביאור
22
המשך סימון נונטרמינלים
א. אותיות גדולות מתחילת האלף-בית הלטיני A B C ב. האות S המסמנת את סמל ההתחלה S ג. מחרוזות של אותיות קטנות נוטות stmt expr op מטה-משתנים א. אותיות גדולות מסוף האלף-בית הלטיני X Y Z מסמנות סמלי דקדוק (כלומר טרמינלים או נונטרמינלים) ב. אותיות קטנות מסוף האלף-בית הלטיני u v z מסמנות מחרוזות של טרמינלים ג. אותיות קטנות מתחילת האלף-בית היווני מסמנות מחרוזות של סמלי דקדוק תורת הקומפילציה איתן אביאור
23
המשך סימון אלטרנטיבה הסימן | המשמש לקיצור A 1
A 1 | 2 | | k A A k סמל ההתחלה סמל ההתחלה הינו הצד השמאלי של כלל הגזירה הראשון (אלא אם ציון אחרת) דוגמה E E A E | ( E ) | - E | id A | | | / | תורת הקומפילציה איתן אביאור
24
גזירה (Derivation) סדרה של צעדים על מחרוזת המורכבת מטרמינלים ונונטרמינלים בה בכל צעד מוחלף סמל X המופיע במחרוזת בתת-מחרוזת , תוך שימוש בכלל גזירה X נסמן: צעד גזירה סדרת צעדי גזירה סדרה לא ריקה של צעדי גזירה דוגמה: -(E) -(E A E) -(E + E) -(E + id) -(id + id) -(E) (id + id) + תורת הקומפילציה איתן אביאור
25
שפה (Language) שפה L(G) הנוצרת ע"י דקדוק G היא אוסף כל המחרוזות של טרמינלים הנגזרות מסמל ההתחלה של דקדוק L(G) = { w | S w } המחרוזת w נקראת משפט (sentence) בשפה דקדוקים שקולים (equivalent) ─ שני דקדוקים המייצרים אותה שפה sentential ─ מחרוזת של סמלי דקדוק הנגזרת מסמל ההתחלה S משפט (sentence) הוא sentential המורכב מטרמינלים בלבד + תורת הקומפילציה איתן אביאור
26
גזירה משמאל (Leftmost) וגזירה מימין (Rightmost)
בכל צעד גזירה יש לקבל שתי החלטות: איזה נונטרמינל לגזור באיזה כלל גזירה (מבין כללי הגזירה של אותו נונטרמינל) נשתמש כאשר בשלב 1 בוחרים את הנונטרמינל השמאלי ביותר במחרוזת הגזירה נקראת גזירה שמאלית (leftmost) ומסומנת ע"י A : w A w ( w T* ) כאשר בשלב 1 בוחרים את הנונטרמינל הימני ביותר במחרוזת הגזירה נקראת גזירה ימנית (rightmost) ומסומנת ע"י A : A u u ( u T* ) lm lm rm rm תורת הקומפילציה איתן אביאור
27
גזירה משמאל ומימין ─ המשך
הסימון מדגיש כי נגזרת מ- בסדרה של צעדי גזירה שמאליים הסימון מדגיש כי נגזרת מ- בסדרה של צעדי גזירה ימניים דוגמאות: - ( E + E ) - ( id + E ) - ( E + E ) - ( E + id ) lm rm lm rm תורת הקומפילציה איתן אביאור
28
צעד הגזירה: - ( E ) - ( E + E )
גזירה ועץ פריסה בנית עץ פריסה שקולה לגזירה כלל הגזירה: B צעד הגזירה: B מתבטא בעץ: ביצירת בנים לצומת המסומן ב-B אם ε אזי מספר הבנים הוא באורך והסדר שלהם הוא כסדרם ב- אם = ε נוצר בן יחיד המסומן ב-ε E − ( ) עדכון עץ הפריסה: כלל הגזירה: E E + E + E צעד הגזירה: ( E ) - ( E + E ) תורת הקומפילציה איתן אביאור
29
רב-משמעות (Ambiguity)
דקדוק רב-משמעי (ambigous) ─ דקדוק המייצר יותר מעץ פריסה יחיד למחרוזת כלשהי הרב-משמעות עשויה לנבוע מהבחירה של צעד 1 (איזה נונטרמינל לגזור) אבל גם אם מחליטים על גזירה שמאלית (או ימנית) היא עשויה לנבוע מצעד 2 (באיזה כלל גזירה להשתמש) דוגמה: E E + E E E E id + E E + E E id + E E id + E E id + id E id + id E id + id id id + id id תורת הקומפילציה איתן אביאור
30
רב-משמעות ─ המשך E + id E + id דקדוק רב-משמעי עשוי להטעות אותנו במציאת המשמעות של המשפט ולכן רצוי להימנע מדקדוק רב-משמעות לחילופין ניתן לנסח כללי חדות (disambiguating rules) הבוררים את עץ הפריסה הרצוי מתוך העצים הפורסים האפשריים תורת הקומפילציה איתן אביאור
31
רב משמעות ─ דוגמה בעית ה-else המתנדנד (dangling else): דקדוק
stmt if expr then stmt | if expr then stmt else stmt | other המשפט if E1 then S1 else if E2 then S2 else S3 נפרס ע"י עץ פריסה stmt E1 S1 E2 S2 S3 if expr then else תורת הקומפילציה איתן אביאור
32
רב משמעות ─ המשך דוגמה אולם המשפט if E1 then if E2 then S1 else S2
נפרס ע"י שני עצים אפשריים: stmt E1 S2 if expr then else E2 S1 stmt E1 E2 S1 S2 if expr then else תורת הקומפילציה איתן אביאור
33
סילוק רב-משמעות שפות התכנות שבהם משפטי תנאי כנ"ל מעדיפות את עץ הפריסה השמאלי כלומר, ה-else צריך להיות משויך ל-then הקרוב אליו ביותר כלומר, לא ייתכן שבין then ו-else המשויך לו יהיה then אשר אין לו else משויך הדקדוק הבא מאפשר היווצרות של העץ השמאלי בלבד stmt matched_stmt | unmatched_stmt matched_stmt if expr then matched_stmt else matched_stmt | other unmatched_stmt if expr then stmt | if expr then matched_stmt else unmatched_stmt תורת הקומפילציה איתן אביאור
34
רקורסיה שמאלית (Left Recursion)
כאשר דקדוק מאפשר גזירה: A A נאמר כי קיימת בו רקורסיה שמאלית (left recursion) פורסים העובדים מלמעלה למטה מתקשים להתמודד עם מצב כזה, ועלולים להיכנס לרקורסיה אינסופית רקורסיה שמאלית פשוטה A A : A A | ניתנת לסילוק ע"י החלפת הכלל בצמד כללים: A A’ A’ A’ | ε + תורת הקומפילציה איתן אביאור
35
דוגמה לסילוק רקורסיה שמאלית פשוטה
הדקדוק: E E + T | T T T F | F F ( E ) | id ניתן לכתיבה מחדש כך: E T E’ E’ + T E’ | ε T F T’ T’ F T’ | ε F ( E ) | id תורת הקומפילציה איתן אביאור
36
רקורסיה שמאלית מיידית הכלל: A A1 | A2 | . . . | Am
| 1 | 2 | | n כאשר שום i לא מתחיל ב-A וכל i שונה מ-ε ניתן להחלפה ע"י הכללים: A 1A’ | 2 A’ | | nA’ A’ 1A’ | 2A’ | | mA’ | ε תורת הקומפילציה איתן אביאור
37
סילוק רקורסיה שמאלית כללית
נניח כי G חסר מעגלים (לא מתקיים A A) וכי אין בו כללי ε (אין כללים מהצורה A ε ) (ניתן לסלק את אלה מראש, ראה ASU תרג' 4.20 ו-4.22) האלגוריתם הבא מסלק רקורסיה שמאלית כללית סדר את הנונטרמינלים בסדר כלשהו A1, A2, , An עבור כל Ai i [1 .. n] ועבור כל Aj j [1 .. i-1] אם קיים כלל P מהצורה Ai Aj וכן קיימים כללים Aj 1 | 2 | | k החלף את P בכלל Ai 1 | 2 | | n סלק רקורסיה שמאלית מכללי Ai + תורת הקומפילציה איתן אביאור
38
פירוק שמאלי (Left Factoring)
הדקדוק stmt if expr then stmt else stmt | if expr then stmt מותיר במבוכה פורס מנבא מפני שכאשר הפורס רואה את התמנית if איננו יודע באיזה משני כללי הגזירה להשתמש באופן כללי אם קיים כלל: A 1 | 2 נחליף אותו בצמד הכללים: A A’ A’ 1 | 2 כלומר נדחה את ההכרעה בין 1 ו-2 לשלב מאוחר יותר בפריסה תורת הקומפילציה איתן אביאור
39
פירוק שמאלי ─ המשך ובאופן כללי: לכל נונטרמינל A:
אם ε אזי קיימת רישא משותפת אמיתית כלל A נראה מהצורה A 1 | 2 | | n | 1 | 2 | | m כאשר איננה רישא של אף i החלף את כלל הנ"ל בכללים הבאים: A A’ | 1 | 2 | | m A’ 1 | 2 | | n חזור על צעדים אלה עד שלא תהיה יותר רישא משותפת אמיתית לאלטרנטיבות של A תורת הקומפילציה איתן אביאור
40
פריסה מלמעלה למטה Top Down Parsing
שיטה לפריסה המתאימה לבניה ידנית של פורסים תשתמש בגזירה שמאלית תורת הקומפילציה איתן אביאור
41
ירידה רקורסיבית (Recursive Descent)
אתחול המקום הנוכחי בקלט: בהתחלה בנה עץ פריסה ריק הכנס את S כשורש העץ פרוס את S ודא שהגעת לסוף הקלט תורת הקומפילציה איתן אביאור
42
ירידה רקורסיבית המשך פריסה רקורסיבית הצומת לפריסה הוא V
סמן את המקום הנוכחי בקלט: P עבור כל הכללים V בצע: חזור בקלט למקום P בטל כל הבנים של V (אם יש) הוסף ל-V בנים לפי לכל בן של V (משמאל לימין): אם הבן הוא נונטרמינל פרוס אותו אחרת (טרמינל) אם הוא זהה לקלט הבא התקדם בקלט אחרת (נסיגה) חזור לצעד 3 V נפרס היטב חזור מהרקורסיה תורת הקומפילציה איתן אביאור
43
ירידה רקורסיבית דוגמה
cad S A c d cad S A c d הדקדוק: S cAd A ab a הקלט: cad cad S cad S A c d a b cad S A c d a cad S A c d a b cad S A c d a cad S A c d a cad S A c d תורת הקומפילציה איתן אביאור
44
נסיגה (Backtracking) הפורס בחר כלל גזירה שגוי, ונאלץ לחזור אחורה:
לבטל צמתים בעץ לחזור אחורה בקלט ישנם דקדוקים חסרי הקשר שלא ניתן לפרוס אותם מלמעלה למטה ללא נסיגות ישנן שפות חסרות הקשר שעבורן אין דקדוק שניתן לפריסה מלמעלה למטה ללא נסיגות ישנן שפות שעבורן ניתן לכתוב דקדוק הניתן לפריסה מלמעלה למטה ללא נסיגות תורת הקומפילציה איתן אביאור
45
פורס מנבא (Predictive Parser)
מתאים בד"כ להוראות הבקרה של רוב שפות התכנות stmt if expr then stmt else stmt while expr do stmt begin stmt_list end stmt_list stmt stmt_list ע"פ הקלט הבא ניתן תמיד לבחור באופן חד-משמעי את כלל הגזירה המתאים, ועל כן אין צורך בנסיגות תורת הקומפילציה איתן אביאור
46
דיאגרמת מעבר (Transition Diagrams) לפורסים מנבאים
דיאגרמה אחת לכל נונטרמינל תוויות הקשתות הן טרמינלים ונונטרמינלים הפריסה מתחילים בדיאגרמה של סמל ההתחלה מעבר ע"פ קשת טרמינל ניתן לעבור בקשת זו אם הקלט הבא הוא התמנית המתאימה מעבר ע"פ קשת נונטרמינל קריאה לנוהל שיפרוס את הנונטרמינל ע"פ הדיאגרמה שלו תורת הקומפילציה איתן אביאור
47
בנית דיאגרמת מעבר סלק רקורסיה שמאלית מהדקדוק בצע פירוק שמאלי של הדקדוק
לכל נונטרמינל A: ייצר מצב התחלה ומצב סיום (חזרה) לכל כלל A x1x2…xn ייצר מסלול ממצב ההתחלה למצב הסיום כך שהקשתות על המסלול מסומנות: x1, x2, … xn תורת הקומפילציה איתן אביאור
48
דיאגרמת מעבר לפריסה דוגמה
1 2 T E’ E : הדקדוק: הדיאגרמות: E T E’ E’ + T E’ | ε T F T’ T’ F T’ | ε F’ ( E ) | id 3 4 + T E’ : 5 6 E’ 7 8 9 F T’ T : T’ : 10 11 F 12 13 T’ F : 14 15 ( E 16 17 ) id תורת הקומפילציה איתן אביאור
49
פישוט דיאגרמות מעבר לפריסה
3 4 + T E’ : 5 6 E’ 3 4 + T E’ : 5 6 3 4 + T E’ : 6 1 2 T E’ E : 3 + T E : 6 3 + T E : 5 6 תורת הקומפילציה איתן אביאור
50
פריסה מנבאת לא-רקורסיבית
קלט a + b $ מחסנית X תוכנית פריסה מנבאת פלט Y Z טבלת פריסה M $ טבלת הפריסה שורה לכל נונטרמינל עמודה לכל טרמינל ועמודה ל-$ הכניסה M[X,a] מכילה את כלל(י) הגזירה שניתן ליישם כאשר יש לגזור את X והקלט הבא הוא a כיצד בונים ? בינתיים תעלומה תורת הקומפילציה איתן אביאור
51
אלגוריתם לפריסה מנבאת לא-רקורסיבית
append $ to w ; push ( $ ); push ( S ); i = 0; do { X = top () ; a = wi ; if ( X is terminal or $ ) { if ( X == a ) { pop () ; i ++ ; } else error () ; } else /* X is nonterminal */ if ( M[X, a] == “X Y1Y2…Yk” ) { push ( Yk, Yk-1, ... Y1 ) ; output “X Y1 Y2 … Yk ” ; } while ( X != $ ) ; קלט: מחרוזת w וטבלת פריסה M עבור הדקדוק G פלט: אם w L(G) גזירה שמאלית של w; אחרת שגיאה תורת הקומפילציה איתן אביאור
52
רב-משמעות בטבלת מעברים
אם כניסה בטבלה מכילה יותר מאשר כלל אחד נוצרת רב-משמעות, והאלגוריתם הופך לאי-דטרמיניסטי ניתן לקבוע כללים צדדים ליישוב רב-משמעות, כגון: יש להעדיף כלל X ( ≠ ) על פני כלל X תורת הקומפילציה איתן אביאור
53
טבלת מעברים דוגמה Input Symbol Non-terminal $ ( ) + id E T E’ E
T F T’ T T’ T’ F T’ T’ T’ F ( E ) F id F STACK INPUT OUTPUT STACK INPUT OUTPUT $E id + id id$ $E’ T’ id id id$ F id $E’ T id + id id$ E T E’ $E’ T’ id$ $E’ T’ F id + id id$ T F T’ $E’ T F id$ T’ F T’ $E’ T’ id id + id id$ F id $E’ T’ F id$ $E’ T’ + id id$ $E’ T’ id id$ F id $E’ + id id$ T’ $E’ T’ $ $E’ T + + id id$ E’ + T E’ $E’ $ T’ $E’ T id id$ $ E’ $E’ T’ F id id$ T F T’ END תורת הקומפילציה איתן אביאור
54
First ו-Follow First() — קבוצת הטרמינלים שמתחילים מחרוזות הנגזרות מ-
Follow(A) — קבוצת הטרמינלים שיכולים להופיע בצמוד ל-A מימין בנגזרת כלשהי, כלומר: a Follow(A) אם S Aa אם S A אז גם $ Follow(A) שים לב S Aa ε S Aa a Follow(A) S A ε S A $ Follow(A) תורת הקומפילציה איתן אביאור
55
אלגוריתם לחישוב First של טרמינלים ונונטרמינלים
for each terminal t First (t) = { t }; while ( ! done ) { if ( “X ” is a production ) First (X) = { } ; if ( “X Y1 Y2 … Yk“ is a production ) { First (X) = First (Y1) - { }; for ( i=1; i < k; i ++ ) if ( First (Yi) ) First (X) = First (Yi+1) - { }; else break ; if ( i == k First (Yk)) First (X) = { } ; } כל ביצוע = המשנה את קבוצת ה-First גורם ל- done = 0 בהתחלת הלולאה (מיד לאחר הבדיקה) מציבים באופטימיות done = 1 תורת הקומפילציה איתן אביאור
56
חישוב First של סדרת הסמלים
X1 X Xn First () = First (X1) { } ; for ( i = 1; i < n; i ++ ) { if ( First (Xi) ) First () = First (Xi+1) { } else break ; if ( i == n First (Xn) ) First () = { } ; תורת הקומפילציה איתן אביאור
57
אלגוריתם לחישוב Follow
done משתנה כמו קודם Follow (S) = { $ } ; while ( !done ) { if ( “A B” is a production ) Follow (B) = First () { } ; if ( “A B” is a production ( “A B” is a production First () ) ) Follow (B) = Follow (A); } β תורת הקומפילציה איתן אביאור
58
דוגמה הדקדוק E T E’ E’ + T E’ | ε T F T’ T’ F T’ | ε
F ( E ) | id First First ( E ) = { ( , id } First (E’ ) = { + , ε } First ( T ) = { ( , id } First (T’ ) = { , ε } First ( F ) = { ( , id } Follow Follow ( E ) = { ) , $ } Follow (E’ ) = { ) , $ } Follow ( T ) = { , ) , $ } Follow (T’ ) = { , ) , $ } Follow ( F ) = { + , , ) , $ } תורת הקומפילציה איתן אביאור
59
אלגוריתם לבנית טבלת פריסה
foreach ( production “A ” ) { foreach ( terminal a First () ) M [A, a] += “A ” ; if ( First () ) { foreach ( terminal b Follow (A) M [A, b] += “A ” ; if ( $ Follow (A) ) M[A, $] += “A ” ; } תורת הקומפילציה איתן אביאור
60
רב משמעות בטבלה דקדוק רקורסיבי שמאלי או דקדוק רב-משמעי
הדקדוק: S i E t S S’ | a S’ e S | ε E b הטבלה: פתרון הרב-משמעות אפשרי במקרה זה ע"י העדפת הכלל S’ eS על הכלל S’ ε בהתאם למוסכמה ש-else משוייך ל-then הקרוב אליו ביותר בחירת הכלל S’ ε תגרום לכך שהסמל e לעולם לא יוכנס למחסנית ולא יוצא מהקלט דקדוק רקורסיבי שמאלי או דקדוק רב-משמעי מייצרים לפחות כניסה אחת רב-משמעית בטבלה Input Symbol Non terminal $ t i e b a S i E t S S’ S a S S’ S’ ε S’ eS S’ E b E תורת הקומפילציה איתן אביאור
61
דקדוקי LL(1) דקדוק הניתן לפריסה בתנאים הבאים נקרא LL(1):
L קריאת הקלט משמאל לימין ( Left to right scan ) L גזירה שמאלית ( Left most derivation ) 1 ראית סמל אחד קדימה בלבד ( 1 lookahead symbol ) משפט לדקדוק LL(1) ניתן לבנות טבלת פריסה ללא כניסות רב-משמעותיות משפט דקדוק הוא LL(1) אם"ם לכל שני כללים A A a T : a β a ( ) if ( a ) then a Follow (A) לצערנו לא כל דקדוק ניתן להבאה למצב LL(1) לא תמיד ניתן למצוא כללי העדפה חיצוניים תורת הקומפילציה איתן אביאור
62
פריסה מלמטה למעלה (Bottom-Up Parsing)
שיטה לפריסה המתאימה לבניה אוטומטית של פורסים תשתמש בגזירה ימנית תורת הקומפילציה איתן אביאור
63
דוגמה לגזירה מלמטה למעלה
הדקדוק S a A B e A A b c b B d משפט הקלט a b b c d e נגזר ע"י a A b c d e a A d e a A B e S’ rm rm rm rm תורת הקומפילציה איתן אביאור
64
מטפל (Handler) מטפל (handler) של נגזרת ימנית הוא כלל A β
ע"מ לייצר את הנגזרת הקודמת ל- בגזירה ימנית של כלומר, אם S αAw αβw אזי A β במקום שאחרי α הוא מטפל של המחרוזת αβw (w מכילה רק טרמינלים מפני שמדובר בגזירה ימנית) נאמר מטפל ולא ה-מטפל מפני שבדקדוק רב-משמעי עשויות להיות שתי גזירות ימניות S αβw בדקדוק חד-משמעי לכל נגזרת ימנית יש רק מטפל אחד לא תמיד ה-β השמאלית ביותר בנגזרת מתאימה להחלפה מפני שהחלפת אותה β ב-A עשויה להביא למשהו שלא ניתן לגזור מסמל ההתחלה (מזכיר לנו את בעיית הנסיגות בגזירה יורדת) rm rm rm תורת הקומפילציה איתן אביאור
65
דוגמה ל"מטפל" שגוי הדקדוק S a A B e A A b c b B d משפט הקלט
a b b c d e נגזר ע"י a A b c d e a A A c d e a A A c B e rm rm rm rm ERROR תורת הקומפילציה איתן אביאור
66
דוגמה לפריסה מלמטה למעלה
הקלט id1 + id2 id3 הדקדוק E E + E E E E E ( E ) E id כלל הגזירה טיפול נגזרת ימנית E id id1 id1 + id2 id3 id2 E + id2 id3 id3 E + E id3 E E E E E E + E E E E + E E + E E תורת הקומפילציה איתן אביאור
67
דוגמה לפריסה מלמטה למעלה המשך
הקלט id1 + id2 id3 הדקדוק E E + E E E E E ( E ) E id כלל הגזירה טיפול נגזרת ימנית E id id1 id1 + id2 id3 id2 E + id2 id3 E E + E E + E E + E id3 id3 E id3 E E E E E E E E מאחר והדקדוק רב-משמעי ניתן לגזור גם באופן זה: תורת הקומפילציה איתן אביאור
68
פריסת "הזזה ורדוקציה" (Shift-Reduce)
לרשות הפורס נתונה מחסנית שלתוכה ניתן להכניס סמלי דקדוק הפורס פועל באמצעות 4 הפעולות: shift סמל הקלט מוזז ונדחף למחסנית reduce החלפת תת-מחרוזת (של סמלי הדקדוק) שבראש המחסנית במטפל שלה accept עצירה במצב מקבל error גילוי שגיאות תחביר קלט מחסנית אתחול w$ $ סיום מוצלח $ $S תורת הקומפילציה איתן אביאור
69
דוגמה להפעלת שיטת Shift-Reduce
מחסנית קלט פעולה $ id1 + id2 id3$ shift (1) $id1 + id2 id3$ reduce by E id (2) $E shift + id2 id3$ (3) $E + shift id2 id3$ (4) $E + id2 reduce by E id id3$ (5) $E + E shift id3$ (6) $E + E shift id3$ (7) $E + E id3 reduce by E id $ (8) $E + E E reduce by E E E $ (9) $E + E reduce by E E + E $ (10) $E accept $ (11) תורת הקומפילציה איתן אביאור
70
דקדוק שנוצרים בו קונפליקטים איננו LR(k) (יוגדר בהמשך)
קונפליקט shift/reduce הפורס מתלבט מה לעשות בצעד הבא פעולת shift או פעולת reduce קונפליקט reduce/reduce הפורס מתלבט באיזה רדוקציה כדאי לו לבחור בצעד הבא דקדוק שנוצרים בו קונפליקטים איננו LR(k) (יוגדר בהמשך) תורת הקומפילציה איתן אביאור
71
דוגמה לקונפליקט Shift/Reduce
דקדוק רב-משמעי איננו יכול להיות LR הדקדוק stmt if expr then stmt if expr then stmt else stmt other המצב קלט מחסנית if expr then stmt else $ זהו קונפליקט shift/reduce האם לבצע רדוקציה ע"פ הכלל הראשון או הזזה פעמיים ואח"כ רדוקציה לפי הכלל השני במקרה זה ניתן לפתור את הקונפליקט ע"י כלל צדדי הקובע כי במצב כזה יש להעדיף את פעולת ה-shift ע"מ לשייך את ה-else ל-then הקרוב אליו לא תמיד ניתן למצוא כללים כאלה תורת הקומפילציה איתן אביאור
72
דוגמה לקונפליקט Reduce/Reduce
נניח כי קריאה לשגרה וכן פניה למערך נכתבים בתחביר דומה תוך שימוש בסוגריים ופסיקים: FUNC (A, B) וכן ARR (I, J) הסורק מייצר תמנית id לכל מזהה הדקדוק stmt id ( parameter_list ) (1) stmt expr := expr (2) parameter_list parameter_list , parameter (3) parameter_list parameter (4) parameter id (5) expr id ( expr_list ) (6) expr id (7) expr_list expr_list , expr (8) expr_list expr (9) תורת הקומפילציה איתן אביאור
73
דוגמה המשך אם הקלט הוא: A(I, J) זרם התמניות יהיה: id ( id , id )
במצב קלט מחסנית id ( id , id ) . . . לא ברור באיזה כלל צריך להשתמש לצורך הרדוקציה ( 5 או 7) פתרון אפשרי הסורק יבדיל בין שמות שגרות ומערכים תוך שימוש בטבלת סמלים וייצר תמנית שונה לכל מקרה תורת הקומפילציה איתן אביאור
74
רישא בת-קימא (Viable Prefix)
כלומר: רישא של נגזרת ימנית שאיננה ממשיכה מעבר למטפל הימני ביותר בנגזרת מכאן תמיד ניתן להוסיף טרמינלים לסופה של רישא בת-קימא ע"מ לקבל נגזרת ימנית שלמה תורת הקומפילציה איתן אביאור
75
פורס LR פורס LR(k): L קריאת הקלט משמאל לימין ( Left to right scan )
R גזירה ימנית ( Rightmost derivation ) k ראית k סמלים קדימה ( k lookahead symbol ) כאשר משמיטים את k הכוונה ל-LR(1) תורת הקומפילציה איתן אביאור
76
יתרונות פורסי LR ניתן לזהות באמצעותם כמעט את כל המבנים של שפות תכנות הניתנים לתיאור באמצעות דקדוק חסר הקשר השיטה המוכרת הכללית ביותר לפריסה בהזזה ורדוקציה ללא נסיגות ואשר ניתנת למימוש יעיל אוסף הדקדוקים הניתנים לפריסה בשיטה זו מכיל ממש את אוסף הדקדוקים הניתנים לפריסה ע"י פורס מנבא פורס LR יכול למצוא שגיאות תחביר מוקדם ככל שניתן בזמן סריקה של הקלט משמאל לימין תורת הקומפילציה איתן אביאור
77
חסרון שיטת LR השיטה מסובכת מדי כדי לבנות פורס באופן ידני
יש להשתמש בכלי מיוחד לבנית פורס תורת הקומפילציה איתן אביאור
78
מודל פורס LR LR a1 . . . ai an $ קלט sm Xm sm-1 Xm-1 . . . s0 מחסנית
תוכנית פריסה LR פלט action goto תורת הקומפילציה איתן אביאור
79
תוכנית הפריסה בשיטת LR לרשות תוכניות הפריסה: קלט זרם התמניות
קלט זרם התמניות פלט כללי הגזירה בסדר הפוך לגזירה (מלמטה למעלה) מחסנית המכילה סמלי דקדוק ומצבים טבלאות פריסה action ו-goto תורת הקומפילציה איתן אביאור
80
תוכנית הפריסה בשיטת LR המשך
המחסנית במחסנית קיימים לסירוגין סמלי דקדוק ומצבים המצב שנמצא בראש המחסנית הוא המצב בו נמצאת התוכנית כרגע ניתן לבנות אוטומט שע"פ תוכן הסמלים במחסנית (המכילה רק סמלים) יוכל להציע באיזה מטפל יש להשתמש ברדוקציה הבאה המצב בראש המחסנית מסמל את מצבו של אותו אוטומט עקרונית, ניתן לוותר על הכנסת הסמלים למחסנית, ולהסתפק במצבים תצורה (configuration) זוג הסדרות המייצגות את תוכן המחסנית והקלט שנותר s0X1s1X2s Xms m , aiai an$ תורת הקומפילציה איתן אביאור
81
טבלאות הפריסה בשיטת LR טבלת action
כאשר המצב בראש המחסנית הינו sm וסמל הקלט הבא הינו ai, הכניסה action [sm, ai] יכולה להכיל אחד מארבעה ערכים: הזז s (s הינו שם המצב) shift s בצע רדוקציה ע"פ כלל A α A α reduce קבל accept שגיאה error טבלת goto כניסה goto [s, A] בטבלה זו מכילה מצב (או שהיא ריקה) s הינו מצב ו-A הוא נונטרמינל תורת הקומפילציה איתן אביאור
82
אלגוריתם הפריסה בשיטת LR
input is w$ ; i = 1; while ( 1 ) { } t = top ( ); a = wi; if ( action [ t, a ] == “shift s” ) { push ( a ) ; push ( s ); i ++ ; } elseif ( action [ t, a ] == “reduce A β“) { pop ( 2 * | β | ) ; t = top ( ) ; push ( A ) ; push ( goto [ t, A ]) ; output “A β” ; } elseif ( action [ t, a ] == “accept” ) { return ; } else error ( ) ; תורת הקומפילציה איתן אביאור
83
דוגמה לפריסה בשיטת LR הדקדוק הערות א. si פירושו הזז למחסנית מצב i
(1) E E + T (2) E T (3) T T F (4) T F (5) F ( E ) (6) F id טבלת הפריסה E T 9 2 10 3 F $ ) ( + id r5 r3 s7 r6 r4 r1 s6 r2 s5 acc s4 5 8 4 1 s11 7 6 11 goto action מצב הערות א. si פירושו הזז למחסנית מצב i ב. rj פירושו רדוקציה לפי כלל גזירה j ג. acc פירושו לקבל ד. כניסה ריקה היא שגיאה תורת הקומפילציה איתן אביאור
84
המשך דוגמה תצורת הפורס עד לקבלה הקלט id id + id מחסנית קלט פעולה
id id + id $ shift (1) 0 id 5 id + id $ reduce by F id (2) 0 F 3 reduce by T F id + id $ (3) 0 T 2 shift id + id $ (4) 0 T 2 7 shift id + id $ (5) 0 T 2 7 id 5 reduce by F id + id $ (6) הקלט id id + id 0 T 2 7 F 10 reduce by T T F + id $ (7) 0 T 2 reduce by E T + id $ (8) 0 E 1 shift + id $ (9) 0 E 1 + 6 shift id $ (10) 0 E id 5 reduce by F id $ (11) 0 E F 3 reduce by T F $ (12) 0 E T 9 E E + F $ (13) 0 E 1 accept $ (14) תורת הקומפילציה איתן אביאור
85
בנית טבלת הפריסה LR שלוש שיטות מוכרות:
SLR פשוטה למימוש אבל פחות חזקה LR קאנוני הכי חזקה אבל גם הכי יקרה LALR באמצע מבחינת המחיר והחוזק, מתאימה לרוב שפות התכנות תורת הקומפילציה איתן אביאור
86
פריט (Item) פריט LR(0) (LR(0) item) כלל גזירה שנעוצה בו נקודה במקום כלשהו בצידו הימני דוגמה הכלל: A x y z הפריטים: A · x y z A x · y z A x y · z A x y z · הכלל A מייצר רק פריט אחד: A · תורת הקומפילציה איתן אביאור
87
פריט – המשך ניתן לייצג פריט ע"י שני מספרים: א. כלל הגזירה
ב. מקום הנקודה משמעות הפריט: ראינו עד עתה קלט המתאים לגזירת הרישא שמאלה לנקודה ואנו מקווים לראות בהמשך קלט המתאים לסיפא שמימין לנקודה הפריטים הם מצבים אפשריים של אוטומט NFA המזהה רישאות בנות-קיימא. קבוצות פריטים הן מצבי אוטומט DFA שנוצר ע"י אלגוריתם "בנית תת-קבוצות" תורת הקומפילציה איתן אביאור
88
SLR הגדרות דקדוק מורחב (augmented) דקדוק שהוסף לו כלל S’ S
התכלית לוודא שיש רק כלל גזירה אחד פשוט שכאשר משתמשים בו יודעים שהגזירה מלמטה למעלה הצליחה פעולת סגור (closure) תוגדר להלן פעולת goto תוגדר להלן תורת הקומפילציה איתן אביאור
89
SLR פעולת סגור (Closure)
G’ דקדוק חסר הקשר מורחב I קבוצת פריטים של G’ closure ( I ) קבוצת הפריטים המכילה את: א. כל מה שקיים ב-I עצמה ב. אם A α · B β closure ( I ) ואם B הוא כלל גזירה אזי גם B · closure ( I ) המשמעות כאשר ראינו בקלט α ואנו מצפים עתה לראות B β ניתן גם לומר כי אנו מצפים לראות עתה בקלט (ואח"כ β) תורת הקומפילציה איתן אביאור
90
SLR סגור דוגמה הדקדוק E’ E E E + T | T T T F | F
F ( E ) | id E’ · E E · E + T E · T T · T F T · F F · ( E ) F · id closure { [ E’ · E ] } כולל: תורת הקומפילציה איתן אביאור
91
SLR סגור המשך הפריטים בתוך סגור מתחלקים לשני תת-קבוצות:
פריטי גרעין (kernel) כוללים את: פריט ההתחלה S’ · S כל הפריטים בהם הנקודה איננה בצד שמאל לגמרי פריטי חוץ (nonkernel) כוללים את כל הפריטים בהם הנקודה בצד שמאל לגמרי, מלבד פריט ההתחלה מאחר וכאשר מוסיפים פריט חוץ B · לקבוצה מוסיפים בעצם את כל פריטי החוץ הנוצרים מכללי B, אין למעשה צורך לשמור בקבוצה את כל הפריטים עצמם, אלא רק את רשימת הנונטרמינלים שמכללי הגזירה שלהם נוצרים הפריטים המעניינים אותנו תורת הקומפילציה איתן אביאור
92
SLR פעולת goto I קבוצת הפריטים X סמל דקדוק
goto ( I , X ) הסגור של קבוצת כל הפריטים מהצורה [ A α X · β ] וזאת עבור כל הפריטים מהצורה [ A α · X β ] השייכים ל-I דוגמה I = { [ E’ E · ] , [ E’ E · + T ] } goto ( I , + ) מכיל את: E E + · T T · T F T · F F · ( E ) F · id תורת הקומפילציה איתן אביאור
93
SLR בנית קבוצות פריטים
void items ( G ) { C = { closure ( { [ S’ · S ] } ) } ; /* אוסף של קבוצות פריטים */ done = 1; do foreach set I C foreach X T N /* סמל דקדוק */ if ( goto ( I , X ) != ) C += goto ( I, X ); /* עשוי להשתנות done */ while ( !done ) ; } תורת הקומפילציה איתן אביאור
94
דוגמה לבנית קבוצות פריטים
הפריטים הדקדוק E’ E E E + T | T T T F | F F ( E ) | id I0 I4 E’ · E E · E + T E · T T · T F T · F F · ( E ) F · id F ( · E ) E · E + T E · T T · T F T · F F · ( E ) F · id I5 I1 F id · E’ E · E E · + T I7 T T · F F · ( E ) F · id I9 E E + T · T T · F I6 E E + · T T · T F T · F F · ( E ) F · id I2 E T · T T · F I10 T T F · I8 F ( E · ) E E · + T I3 I11 T F · F ( E · ) תורת הקומפילציה איתן אביאור
95
E + T המשך הדוגמה I0 I1 I6 I9 to I7 F to I3 ( id to I4 to I5 T F I2 I7 I10 ( הפריטים מייצגים את המצבים של NFA המכיר את הרישות בנות-הקיימא של הדקדוק קשת מעבר מפריט A α · X β לפריט A α X · β מסומנת ע"י X קשת המעבר מפריט A α · B β לפריט B · מסומנת ע"י קבוצות הפריטים מייצגות את מצבי ה-DFA הנוצר מה-NFA to I4 F id to I5 I3 ( ( ) I4 I8 I11 E + to I6 id T to I4 id F to I5 I3 תורת הקומפילציה איתן אביאור
96
SLR פריטים תקפים פריט תקף (valid) פריט A β1 · β2 תקף עבור רישא בת-קיימא αβ1 אם קיימת גזירה S’ Aw β1β2w פריט עשוי להיות תקף להרבה רישות אם A β1 · β2 תקף עבור רישא αβ1 הנמצאת על המחסנית אזי: אם β2 ≠ הפריט מציע שלא ראינו עדיין את כל המטפל, ועלינו לבצע פעולת הזזה אם β2 = הפריט מציע שראינו מטפל שלם במחסנית וניתן לבצע פעולת רדוקציה פריטים שונים עלולים להציע רדוקציות שונות ולייצר קונפליקטים אם משתמשים בשיטה זו לדקדוק חסר הקשר כלשהו חלק מהקונפליקטים ניתן לפתור ע"י הסתכלות בסמל הקלט הבא rm rm תורת הקומפילציה איתן אביאור
97
SLR פריטים תקפים המשך
משפט אוסף הפריטים התקפים עבור רישא בת-קיימא הוא בדיוק קבוצת הפריטים אליהם ניתן להגיע מהמצב התחלתי לאורך מסלול המסומן ע"י באוטומט DFA הנוצר מהבניה הקאנונית של קבוצות פריטים עם מעברים המוגדרים ע"י פעולת ה-goto. תורת הקומפילציה איתן אביאור
98
דוגמה הדקדוק ופעולת ה-goto על פי הדוגמה דלעיל
המחרוזת E + T היא רישא בת-קיימא האוטומט הנ"ל נמצא במצב I7 אחרי שהוא קורא E + T מצב I7 כולל את הפריטים: T T · F F · ( E ) F · id הפריטים מתאימים כל אחד לגזירות הבאות: T T · F E’ E E + T E + T F F · ( E ) E’ E E + T E + T F E + T ( E ) F · id E’ E E + T E + T F E + T id תורת הקומפילציה איתן אביאור
99
בנית טבלת פריסה SLR א. מרחיבים את הדקדוק ע"י כלל S’ S
ב. מייצרים את האוסף הקאנוני של קבוצות פריטים C לדקדוק המורחב ג. מחשבים את Follow(A) לכל נונטרמינל המשך .... תורת הקומפילציה איתן אביאור
100
המשך בנית טבלת פריסה SLR
ד. בונים את טבלת action באופן הבא: C = { I0, I1, In } היא אוסף קבוצות הפריטים LR(0) מצב i נוצר מקבוצה Ii ― הפעולות למצב i נקבעות כדלקמן: אם [ A α · a β ] Ii וכן goto(Ii , a) = Ij אזי action[ i , a ] = “shift j” (a חייב להיות טרמינל) אם [ A α ·] Ii אזי action[ i, a ] = “reduce A α” לכל a ב-Follow(A) (A הוא כל נונטרמינל מלבד S’) אם [ S’ S · ] Ii אזי action[ i, $ ] = “accept” המשך .... אם נוצרו קונפליקטים הדקדוק איננו SLR ( 1 ) תורת הקומפילציה איתן אביאור
101
המשך בנית טבלת פריסה SLR
ה. בונים את טבלת goto באופן הבא: אם goto(Ii, A) = Ij אזי goto [ i, A ] = j ו. כל הכניסות שלא הוגדרו בטבלאות action ו-goto מסומנות ע"י error ז. מצב ההתחלה של הפורס הוא זה שנבנה מתוך קבוצת הפריטים המכילה את הפריט [ S’ · S ] תורת הקומפילציה איתן אביאור
102
הגדרות טבלת SLR(1) עבור דקדוק G טבלאות action ו-goto שנבנו כנ"ל
פורס SLR(1) פורס המשתמש בטבלאות SLR(1) דקדוק SLR(1) דקדוק שניתן לבנות עבורו טבלאות SLR(1) בדרך כלל משמיטים את ה-(1) ואומרים SLR מפני שלרוב מדובר בהסתכלות קדימה רק על סמל קלט אחד בלבד תורת הקומפילציה איתן אביאור
103
חסרונות SLR ניתן להראות דוגמה של דקדוק חד-משמעי שעבורו שיטת SLR מייצרת קונפליקטים קונפליקטים אלה נובעים מכך ששיטה זו אינה "זוכרת" מספיק הקשר שמאלי ע"מ להחליט באיזה פעולה לנקוט שיטות LR קאנוני ו-LALR מתאימות למגוון רחב יותר של דקדוקים מאשר SLR ישנם דקדוקים שאינם LR כלל ולכן גם שיטות אלה נכשלות בהם למרבית שפות התכנות מתאימה שיטת הביניים LALR תורת הקומפילציה איתן אביאור
104
הדקדוק וקבוצות הפריטים שהוגדרו קודם
דוגמה לבנית טבלת SLR הדקדוק וקבוצות הפריטים שהוגדרו קודם הקבוצה I1 E’ E · : action [1, $] = “accept” E E · + T : action [1, +] = “shift 6” הקבוצה I0 E’ · E // E · E + T // E · T // T · T F // T · F // F · ( E ) : action [0, ( ] = “shift 4” F · id : action [0, id] = “shift 5” הקבוצה I2 E T · T T · F Follow( E ) = { $ , + , ) } ולכן action [2, $] = action [2, +] = action [2, ] = “shift 7” תורת הקומפילציה איתן אביאור
105
דוגמה 2 לבנית טבלת SLR דקדוק
S R L R L id R L זהו דקדוק המפריד בין r-value (ערכים) ובין l-value (מקומות אחסון) לצורך הגדרת פעולת ההצבה תורת הקומפילציה איתן אביאור
106
אוסף הפריטים LR(0) הקנוני של הדקדוק
המשך דוגמה 2 הדקדוק S L = R S R L R L id R L אוסף הפריטים LR(0) הקנוני של הדקדוק I0 S’ · S S · L = R S · R L · R L · id R · L I4 L · R R · L L · R L · id I5 I1 L id · I7 L R · S’ S · I6 I8 I2 S L = · R R · L L · R F · id R L · S L · = R R L · I9 S L = R · T T · F I3 S R · תורת הקומפילציה איתן אביאור
107
המשך דוגמה 2 נתבונן בקבוצה I2
הפריט הראשון גורם לכניסה action[ 2, = ] להיות "shift 6” מאחר וקבוצת Follow( R ) מכילה את הטרמינל = ( S L = R R = R ) הפריט השני גורם לכניסה action[ 2, = ] להיות “reduce R L” הדקדוק הוא חד-משמעי אבל טבלת הפריסה רב-משמעית מכילה קונפליקט הטבלה איננה זוכרת את ההקשר שבו התגלה הסמל L ולא יודעת האם מותר לעשות לו רדוקציה לסמל R I2 S L · = R R L · תורת הקומפילציה איתן אביאור
108
המשך דוגמה 2 מצב 2 מייצג את הרישא L
מאחר ואין שום נגזרת המתחילה ברישא R = במצב 2 כאשר רואים בקלט את הסימן = אסור לבצע את הרדוקציה מ-L ל-R (אסור להשתמש בכלל R L) לכן במצב 2 עם סימן קלט = יש לבצע פעולת הזזה ע"פ ההצעה של הפריט הראשון תורת הקומפילציה איתן אביאור
109
החולשה של שיטת SLR באופן כללי בשיטת SLR מצב i עם סמל קלט a מציע את הרדוקציה A כאשר: קבוצת הפריטים Ii מכילה את הפריט [ A · ] סמל הקלט a שייך ל-Follow(A) אולם, ייתכן כי מצב i מופיע במחסנית שבה קיימת רישא בת-קיימא β ואילו β איננו מופיעה לפני a בשום נגזרת ימנית, ועל כן הרדוקציה A איננה תקיפה כשהקלט הבא הוא a תורת הקומפילציה איתן אביאור
110
LR קאנוני הרעיון המרכזי הוא לפצל את המצבים (קבוצת הפריטים) ע"פ סימן הקלט הבא, וכך לאפשר פתרון הקונפליקטים הנוצרים בשל קוצר הראות של שיטת SLR פריט LR(1) [ A α · β , a ] זוג המורכב מ: כלל גזירה שבצידו הימני נעוצה במקום מסוים נקודה מטרמינל (או סימן סוף הקלט $) הציון (1) מסמן שמדובר בהסתכלות קדימה על סמל 1 בקלט כאשר [ A α · β , a ] וכן β ≠ אין חשיבות ל-a כאשר [ A α · , a ] ניתן לבצע רדוקציה בעזרת A רק אם סמל הקלט הבא הוא a כלומר ניתן לבצע רדוקציה A רק אם סמל הקלט הבא הוא a וקיים פריט [A α · , a ] בתוך המצב שבראש המחסנית תורת הקומפילציה איתן אביאור
111
LR קאנוני המשך קבוצת כל הסמלים a העומדים בתנאי זה הינה תת-קבוצה (ולעיתים תת-קבוצה ממש) של Follow(A) הגדרה פורמלית פריט LR(1) [ A α · β , a ] הוא תקף (valid) לרישא בת-קיימא אם ישנה נגזרת S Aw βw כאשר = או ש-a הינו הסמל הראשון של w או ש- a = $ w = rm rm תורת הקומפילציה איתן אביאור
112
דוגמה דקדוק S BB B a B | b מאחר וקיים S aaBab aaaBab
על כן הפריט [ B a · B , a ] תקף עבור הרישא = aaa ( = aa, A = B, w = ab, = a, β = B בהגדרה דלעיל) כמו כן קיים S BaB BaaB ועל כן הפריט [ B a · B , $ ] תקף עבור הרישא Baa rm rm rm rm תורת הקומפילציה איתן אביאור
113
ניתוח מחדש של סגור נניח כי קיים פריט [A α · B β , a ] בקבוצת הפריטים של רישא בת-קיימא על כן קיימת גזירה S Aax Bβax כאשר = נניח כי מתוך βax נגזרת מחרוזת הטרמינלים by לכן, לכל כלל גזירה מהצורה B (עבור כלשהו) קיימת הגזירה S Bby by ומכאן ש- [ B · , b ] תקף עבור b יכול להיווצר מתוך β, או אם β נגזרת ל- אזי b = a באופן כללי b יכול להיות טרמינל כלשהו מתוך First(βax) rm rm rm rm תורת הקומפילציה איתן אביאור
114
בנית פריטי LR(1) סגור set closure ( I ) { done = 1; do
foreach item [ A α · B β , a ] in I foreach production “B ” in G foreach terminal b in First (βa) I += [ B · , b ] ; /* => done = 0 */ while ( ! done ) ; return I; } תורת הקומפילציה איתן אביאור
115
בנית פריטי LR(1) goto set goto (I, X) { set J;
foreach item [ A α · X β , a ] in I J += [ A α X · β , a ] ; return closure ( J ) ; } תורת הקומפילציה איתן אביאור
116
בנית פריטי LR(1) void items ( G ) {
C = { closure ( { [ S’ · S , $ ] } ) }; done = 1; do foreach set I in C foreach grammar symbol X if ( goto ( I, X ) != ) C += goto (I, X); /* => done = 0 */ while ( !done) ; } תורת הקומפילציה איתן אביאור
117
בנית טבלת פריסה LR קנונית
א. הרחב את הדקדוק ע"י הכלל S’ S ב. בנה את C קבוצת כל קבוצות הפריטים LR(1) ע"פ האלג' דלעיל ג. בנה טבלת action כדלקמן: C = { I0, I1, In } מצב i של הפורס מיוצר מתוך Ii, והפעולות של מצב זה נקבעות כדלקמן: אם goto(Ii, a) = Ij [ A α · a β , b ] Ii אזי action[ i, a ] = “shift j” (a חייב להיות טרמינל) אם A ≠ S’ [ A α · , a ] Ii אזי action[ i, a ] = “reduce A ” אם [ S S · , $ ] Ii אזי action[ i , $ ] = accept אם נוצר קונפליקט הדקדוק איננו LR(1) והאלגוריתם נכשל תורת הקומפילציה איתן אביאור
118
המשך בנית הטבלה ד. בנה טבלת goto כדלקמן: אם goto ( Ii, A ) = Ij אזי goto[ i , A ] = j ה. כל הכניסות הריקות בטבלת action ובטבלת goto מסומנות ב-error ו. המצב ההתחלתי של הפורס הוא זה שנבנה מתוך הקבוצה המכילה את הפריט [ S’ · S , $ ] תורת הקומפילציה איתן אביאור
119
טבלת פריסה LR(1) קאנונית
פורס LR המשתמש בטבלה זאת נקרא פורס LR(1) קאנוני אם הטבלה איננה מכילה קונפליקטים הדקדוק נקרא דקדוק LR(1) לעיתים משמיטים את ה-(1) ואומרים דקדוק LR אבחנה: כל דקדוק SLR(1) הוא דקדוק LR(1) אבל בהחלט לא להפך תורת הקומפילציה איתן אביאור
120
תום פרק 4 תורת הקומפילציה איתן אביאור
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.