Presentation is loading. Please wait.

Presentation is loading. Please wait.

תורת הקומפילציה 236360 הרצאה 2 ניתוח לקסיקלי Wilhelm, and Maurer – Chapter 7 Aho, Sethi, and Ullman – Chapter 3 Cooper and Torczon – Chapter 2.

Similar presentations


Presentation on theme: "תורת הקומפילציה 236360 הרצאה 2 ניתוח לקסיקלי Wilhelm, and Maurer – Chapter 7 Aho, Sethi, and Ullman – Chapter 3 Cooper and Torczon – Chapter 2."— Presentation transcript:

1 תורת הקומפילציה 236360 הרצאה 2 ניתוח לקסיקלי Wilhelm, and Maurer – Chapter 7 Aho, Sethi, and Ullman – Chapter 3 Cooper and Torczon – Chapter 2

2 front-end שלב הניתוח בקומפיילרים רבים השלבים בכל מסגרת משולבים זה בזה בקומפיילרים רבים ייצוג הביניים הוא decorated syntax tree תוכנית מקור Back end scanning screening syntax analysis semantic analysis symbol string token string syntax tree decorated syntax tree symbol table error messages lexical analysis

3 תוכנית מקור scanner screener parser symbol token get next symbol get next token מנתח לקסיקלי – אינטרקציה עם ה-parser error message manager lexical analysis

4 פישוט הניתוח הלקסיקלי (והגדרת השפה) ופישוט הניתוח הסינטקטי מודולריות שימוש חוזר יעילות – ההפרדה מקלה לממש אלגוריתמים יעודיים יעילים. מדוע מפרידים ניתוח לקסיקלי?

5 מושגים בסיסיים lexeme = לקסמה (לפעמים נקרא גם symbol): סדרת אותיות המופרדת משאר התוכנית באופן מוסכם (למשל ע"י רווח או נקודה). לדוגמא:counter. Pattern: כלל המגדיר אוסף של מחרוזות. (לדוגמא: כל המחרוזות שמתחילות באות וממשיכות באות או מספר). token = אסימון: זוג של שם ותכונות. למשל: (identifier, {name=counter,code_location=3}). שם ה-token נקבע עפ"י ה-pattern שהלקסמה מקיימת.

6 תפקידי ה- scanner קריאת הקלט הפרדת הקלט ליחידות לקסיקליות (לקסמות) דוגמאות: integer, real, boolean, string, שמות משתנים, הערות, סימנים מיוחדים (למשל =<). לפעמים ה-scanner מממש גם preprocessing, כלומר, טיפול ב- include files ו- macros. ספירת מספר שורות (למה?)

7 ה- screener לעיתים – משולב עם ה-scanner (LEX) תפקידו העיקרי של ה-screener – זיהוי ה-patterns, מיונם ויצירת tokens עם שמות ותכונות. וכמובן דיווח על שגיאות: symbols לא חוקיים. טיפול ב- keywords -- מילות מפתח שאינן שמורות, זיהוי reserved words, הדפסת פלט (התוכנית בשילוב הודעות שגיאה), עשוי לכלול pretty printing. –(יש לעקוב אחרי מספרי השורות והעמודות בהם מופיעים ה- tokens)

8 Typical Tokens (Patterns) Token אחד לכל מילה שמורה בשפה (למשל if, else, וכיו"ב) Token אחד לכל אופרטור. לפעמים הם ארוזים במשפחות. למשל משפחת ההשוואות: comparisons = or = or == or !=. Token אחד המייצג את כל שמות המשתנים (identifier). למשל: counter, score, employee. Token אחד או יותר המייצגים קבועים (בד"כ מספרים ומחרוזות). למשל: 35, 27.34, 23e5, “Billie Holiday”. Token אחד לכל סימן פיסוק. למשל: ( ), ; { }.

9 משפחות של סמלים (Patterns) symbol classתוכנית המשתמש IDfoo n_14 last NUM73 00 517 082 REAL66.1.5 10. 1e67 5.5e-10 IFif COMMA, NOTEQ!= LPAREN( RPAREN)

10 טיפול מיוחד במחרוזות שאינן סמלים תוכנית המשתמש comment/* ignored */ preprocessor directive#include macro#define NUMS 5, 6 white space\t \n

11 תכונות תכונות של token ישמשו לשלבים הבאים של הקומפילציה או להודעות שגיאה. ה-token נפוץ לדוגמא הוא שם משתנה (identifier). תכונות סטנדרטיות שנרצה לשמור עבורו יכללו: –שם המשתנה (הלקסמה) –מיקום המשתנה בתוכנית (עבור הודעות שגיאה) –טיפוס המשתנה התכונות האלו נשמרות בד"כ בטבלת הסמלים, ולכן ב-token מספיק לרשום את מספר הכניסה בטבלה.

12 דוגמא עבור הביטוי e = m * c ** 2 :, נעביר את ה-tokens הבאים:

13 הקושי ב-lexical analysis – דוגמאות בשפת פסקל Const pi = 3.1416 ; ב-Fortran הרווחים אינם נחשבים. לכן ההחלטה על סיום לקסמה יותר מורכבת. למשל, do 5 I = 1.2 אבל: do 5 I = 1, 2 כאן מודגש הצורך ב- lookahead (שפות מודרניות מתוכננות כך שלא תיווצרנה בעיות כאלו.) ב-Pascal ו- Ada 1. ו- 10. אינם נחשבים שברים, כי זה מקשה את הזיהוי של 1..10.

14 ניסוח הtokens- המותרים בשפה נרצה דרך סטנדרטית להכריז מהם הסימבולים החוקיים בשפה. לשם כך נשתמש בביטויים רגולריים. אוטומטים המבטאים את הביטויים הרגולריים ישימשו לסריקת הקלט וזיהוי ה-tokens. תזכורת לתיאוריה...

15 אלפבית, מילים, וכו'  – אלפבית (דוגמא :  ={i,m,b,a} ) מילה מעל  היא מחרוזת סופית של אותיות מ - . אורך המילה הוא מספר האותיות בה. דוגמאות: abba, aba, ima, abbabbabba המילה ריקה תסומן ב -  0  – אוסף המילים באורך אפס  n – אוסף המילים באורך n  *– אוסף כל המילים (הסגור של Kleene)  + – אוסף המילים באורך 1 או יותר x.y – מילה המהווה שרשור של x ו- y (בד"כ משמיטים את אופרטור השרשור וכותבים x y) suffix, prefix, substring

16 שפות מעל  שפה – תת קבוצה של  * דוגמא: L1={ima, aba, bamba} או L2 היא "כל המילים שמכילות את האות a". יהיו L, L 1, L 2 שפות –L 1  L 2 – איחוד שפות –L 1 L 2 = {x 1 x 2 | x 1  L 1, x 2  L 2 } – שרשור שפות –L – המשלים של L (המילים ב - *  שאינן ב- L) –L n – שרשור של L לעצמו n פעמים –L* – הסגור של L – שרשור L לעצמו מספר כלשהו של פעמים

17 שפות מעל  דוגמא: תהי L קבוצת כל האותיות וגם הסימן _. תהי D קבוצת כל הספרות. אז ניתן לתאר את השמות החוקיים של משתנים בשפת C כ - L(L  D)*. עבור תיאור ה-patterns, הביטויים החשובים הם: איחוד, שרשור, וסגור. על-מנת לציין את המחרוזות האפשריות המתקבלות המציאו את מושג הביטויים הרגולריים.

18 ביטויים רגולריים, שפות רגולריות  הוא ביטוי רגולרי מעל  המתאר את השפה הריקה  הוא ביטוי רגולרי מעל  המתאר את השפה L(  ) = {  } לכל a  , a הוא ביטוי רגולרי המתאר את השפה L(a) = { a } אם pו- q הם ביטויים רגולריים המתארים את השפות הרגולריות P ו- Q, אזי: – p | qהוא ביטוי רגולרי המתאר את השפה הרגולרית P U Q – p q הוא ביטוי רגולרי המתאר את השפה P Q – p* הוא ביטוי רגולרי המתאר את P* –( p ) הוא ביטוי רגולרי שהשפה שלו P (כלומר, מותר לשים סוגריים). הערה: על מנת לפשט את הסימונים, * הוא בעל הקדימות הגבוהה ביותר, אח"כ שרשור, אח"כ סימן האיחוד. ( a | bc* ) כל שפה הניתנת לכתיבה כביטוי רגולרי היא שפה רגולרית.

19 תרגיל תהי Σ={a,b}. L(a|b) = ? L( (a|b) (a|b) ) = ? L( (a|b)* ) = ?

20 דוגמא תהי Σ={a,b}. L(a|b) = {a,b} L( (a|b) (a|b) ) = {aa,ab,ba,bb} L( (a|b)* ) = {ε, a, b, aa, ab, ba, bb, aaa, aab, aba, …}

21 תיאור symbols באמצאות ביטויים רגולריים דוגמא: מספר שלם או שבור ( 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 ) ( 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 )* (  |. ( 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 ) ( 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 )* (  | E ( 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 ) ( 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 )* ) ) שיטת תיאור זאת קשה לשימוש. לכן נשתמש בשמות של קבוצות.

22 תיאור symbols בעזרת שמות ותחומים על-מנת לקצר את התיאור נשתמש בשמות לביטויים ונשתמש בהם כאילו היו משתנים רגילים. למשל: letter = a | b | … | z | A | B | … | Z letter_ = letter | _ digit = 0 | 1 | 2 | … | 9 id = letter_ ( letter_ | digit )* נשתמש גם במקף לציין תחום ברור. לדוגמא: letter = a-z | A-Z digit = 0-9 ונשתמש ב- + במקום כוכבית לציין שהסגור מכיל לפחות מופע אחד: binary-number = (0|1) +

23 דוגמאות digit = 0-9 digits = digit + number = digits (Є |.digits (Є | e (Є|+|-) digits ) ) letter = a-z | A-Z id = letter (letter | digit)* if = if then = then else = else relop = | = | = | <> ws = ( blank | tab | newline ) - את זה לא נעביר לשלב הבא אלא נתעלם

24 מעבר מלקסמות ל-tokens

25 זיהוי ביטויים רגולריים – על ידי אוטומט סופי אוטומט – , Q, δ, q 0, F ) M = (  – א"ב Q– קבוצה סופית של מצבים q 0  Q – מצב התחלתי F  Q – קבוצת המצבים הסופיים δ : Q    Q פונקצית המעברים state control קלט

26 אוטומט דטרמיניסטי ואי-דטרמיניסטי , Q, δ, q 0, F ) M = ( הוא אוטומט דטרמיניסטי (סופי) אם: Q   → Q : δ היא פונקציה חלקית עבורה: –אין מעברי  –לכל מצב q ואות a   יש לכל היותר מעבר למצב יחיד כלומר: לכל מילה w, האוטומט יגיע למצב מסוים יחיד, או ייתקע. קבלה: אם המצב שאליו מגיעים סופי, הקלט "מתקבל". , Q, δ, q 0, F ) M = ( הוא אוטומט אי-דטרמיניסטי (סופי) אם: Q  (   {  }) → 2 Q : δ היא פונקציה חלקית. (ייתכנו מעברי - , ויותר ממעבר אפשרי אחד לאות ומצב נתונים.) לכל מילה w, האוטומט יכול להגיע למספר כלשהו של מצבים או להיתקע. אם אחד מהם סופי, הקלט מתקבל.

27 שיטת העבודה נהפוך את הביטויים הרגולריים לאוטומט אי-דטרמיניסטי נהפוך את האוטומט האי-דטרמיניסטי לדטרמיניסטי (למה?) –משפט: לכל אוטומט לא דטרמיניסטי קיים אוטומט דטרמיניסטי שקול –במקרה הגרוע גודל האוטומט המתקבל אקספוננציאלי בגודל האוטומט המקורי. אך בפועל (עבור זיהוי לקסמות) מתקבל אוטומט סביר. נריץ את האוטומט הדטרמיניסטי על הקלט לזיהוי הביטוי המתאים. באוטומטים למדנו על אוטומטים שרק מזהים קלט (כן או לא)... אבל כשתוכנית מריצה אוטומט על קלט אין סיבה שלא תאסוף מידע בדרך (בפרט, אותיות הקלט שנסקרו עד עתה, מספר השורה בקוד וכיו"ב).

28 מביטויים רגולריים לאוטומט לא דטרמיניסטי שלב 1: הצב (את סימני הקבוצות כגון 0-9) וקבל סדרת ביטויים רגולריים טהורים R 1, R 2, …, R m. שלב 2: בנה אוטומט לא דטרמיניסטי M i לכל ביטוי רגולרי R i שלב 3: בנה אוטומט משולב M אוטומט זה מזהה את כל הביטויים הרגולריים לתשומת לב: ייתכן שישנם כמה דרכים לזהות את הלקסמה הבאה בתור, אנו נעדיף בד"כ את הארוכה ביותר. –למשל thenutcracker כשם משתנה עדיף על then המילה השמורה. –אבל באותו אורך, then כמילה השמורה עדיף על then כשם משתנה.

29 סימונים

30 מביטוי רגולרי לאוטומט אי-דטרמיניסטי שקול

31 המצבים ההתחלתיים והמקבלים במכונות המקוריות הופכים למצבים רגילים לאחר הבניה.

32

33

34 בהינתן אוטומט לכל pattern, איך נבצע את הניתוח הלקסיקלי ?

35 נרכיב את כל האוטומטים שהתקבלו לאוטומט אחד גדול עם מצב סופי ייחודי לכל pattern אפשרי:

36 שיטה נאיבית: ננסה כל אחד מהאוטומטים.

37 שיטה יותר יעילה היא שילוב כל האוטומטים לאחד, מעבר לאוטומט דטרמיניסטי, והרצה ארוכה ככל האפשר עד שנתקעים. כשנתקעים, זוכרים את המקום האחרון שבו התקבלה מחרוזת ואותו מחזירים. דוגמא:

38 מעבר לאוטומט דטרמיניסטי:

39 Lookahead הבעיה: לעיתים צריך לסרוק מספר אותיות קדימה על מנת להחליט מהו ה- symbol אותו נחזיר. דוגמא: המילה השמורה IF ב- FORTRAN יכולה להיות גם שם של משתנה. “if(i,j)=3” שונה מ-"if (condition) then …”. תאור lookahead עבור המנתח: אות מיוחדת (למשל - /) המציינת את מקום תחילת ה-lookahead. לזיהוי if נוכל לציין שאנו מצפים ל- "if ( * ) then” אבל רוצים שרק ה-if יוחזר. ונרשום “if / ( * ) then”. הערה: בפסקל ו-ADA מספיק lookahead של 2 אותיות. 012345 6 IF)(  start letter any

40 scanner generator symbol specification Input program scanner token stream scanning table ה-lexical analyzer: מפורמליזם לתוכנה יתרונות –המפרט – קצר יחסית –אפשר לוודא שהמפרט תקין (לא אוטומטית!) –התוכנה קלה לתחזוקה לשיטת ה- generation שימושים נוספים בקומפילציה ובשטחים נוספים scanner scanning table driver

41 ה-lexical analyzer: מפורמליזם לתוכנה תאור ה- token - ביטויים רגולריים מבנה ה- scanner – אוטומט סופי –ה-driver הוא תוכנית המריצה אוטומט לפי טבלת המעברים והקלט. –ה- scanning table היא טבלת המעברים.

42 טיפול בשגיאות בשלב הניתוח הלקסיקלי יש שגיאות רבות שלא ניתן לגלות. למשל: עבור הביטוי fi ( a == f(x) ) …, קשה לדעת אם fi הוא שיבוש של if, או שם רוטינה. –בשלב יותר מאוחר של האנליזה נגלה זאת. –בשלב זה פשוט נעביר token עבור identifier. אבל לפעמים יש שגיאה ברורה כבר בשלב זה – כאשר לא ניתן לשייך את הלקסמה שהתגלתה לשום pattern. מה עושים? השיטה הקלה ביותר: לסלק אותיות מהקלט עד שמתגלה התחלה של לקסמה חוקית. אפשרויות נוספות: לסלק אות אחת, להוסיף אות אחת, להחליף אות אחת, להחליף סדר של שתי אותיות סמוכות. המטרה: לאפשר המשך הקומפילציה עם מינימום הפרעה. הקושי – התפשטות השגיאות.

43 סיכום לרוב השפות ניתן לכתוב ביטויים רגולריים לכל הלקסמות הרלוונטיות. משלבים את כל הביטויים לאוטומט אי-דטרמיניסטי יחיד הופכים את האוטומט לדטרמיניסטי מריצים לגילוי לקסמה אחר לקסמה, אוספים מידע בדרך (למשל שם המשתנה) מודיעים על שגיאות ומנסים לתקן. לרוב שפות התכנות ניתן לבנות מנתח לקסיקלי בקלות. יוצאי דופן: Fortran, PL/1. ישנם כלים שבונים מנתח לקסיקלי בהינתן ביטויים רגולריים. יש להם שימושים גם מחוץ לתחום הקומפיילרים, במקומות בהם דרוש ניתוח אוטומטי של קלטים, למשל, מערכות שאילתות. בתרגולים ובתרגיל הבית תכירו כלי אחד כזה: Lex


Download ppt "תורת הקומפילציה 236360 הרצאה 2 ניתוח לקסיקלי Wilhelm, and Maurer – Chapter 7 Aho, Sethi, and Ullman – Chapter 3 Cooper and Torczon – Chapter 2."

Similar presentations


Ads by Google