תורת הקומפילציה 236360 הרצאה 1 מבוא; ניתוח לקסיקלי.

Slides:



Advertisements
Similar presentations
Spring Compilers Software Eng. Dept. – Ort Braude Compilers Lecturer: Esti Stein brd4.braude.ac.il/~esti2.
Advertisements

מבוא למדעי המחשב לתעשייה וניהול
מבוסס על הרצאות של יורם זינגר, האוניברסיטה העברית י"ם
טבלאות סמלים נכתב ע"י אלכס קוגן סמסטר חורף, תשס"ח.
ניתוח לקסיקלי וכלי Lex.
מכונת מצבים תרגול מס' 4 Moshe Malka.
מתמטיקה בדידה תרגול 3.
מסדי נתונים תשס " ג 1 תכנון סכמות (Design Theory) מסדי נתונים.
חורף - תשס " ג DBMS, Design1 שימור תלויות אינטואיציה : כל תלות פונקציונלית שהתקיימה בסכמה המקורית מתקיימת גם בסכמה המפורקת. מטרה : כאשר מעדכנים.
מה החומר למבחן ? כל החומר שנלמד בהרצאות ובתרגולים. לגבי backtracking: לא תידרשו לממש אלגוריתם, אך כן להבין או להשלים מימוש נתון. אחת משאלות המבחן מבוססת.
1 תורת הקומפילציה מרצה –פרופ"ח ארז פטרנק שעת קבלה – יום שני 13:30-14:30 טאוב 528 מתרגלים –קירה רדינסקי, מתרגלת אחראית –חגי טולדנו.
ניתוח תחבירי (Parsing) Wilhelm, and Maurer – Chapter 8 Aho, Sethi, and Ullman – Chapter 4 Cooper and Torczon – Chapter 3.
אוטומט מחסנית הפקולטה למדעי המחשב אוטומטים ושפות פורמליות ( ) תרגיל מספר 11.
מבוא לשפת C חידות ונקודות חשובות נכתב על-ידי יורי פקלני. © כל הזכויות שמורות לטכניון – מכון טכנולוגי לישראל.
חורף - תשס " ג DBMS, צורות נורמליות 1 צורה נורמלית שלישית - 3NF הגדרה : תהי R סכמה רלציונית ותהי F קבוצת תלויות פונקציונליות מעל R. R היא ב -3NF.
הכלה ושקילות בין ביטויי XPath. הביטויים מכילים את האופרטורים הבאים [ ] פיצול // צאצא – קו כפול * - ג'וקר תווית דוגמה a[a][*//b] עבור כל ביטוי P ישנו עץ.
מרצה: פרופסור דורון פלד
* הידור, למהדרין. שקפי הקורס מבוססים על שקפים מאת פרופ' מיכאל רודה.
א " ב, מילים, ושפות הפקולטה למדעי המחשב אוטומטים ושפות פורמליות ( ) תרגיל מספר 1.
א " ב, מילים, ושפות הפקולטה למדעי המחשב אוטומטים ושפות פורמליות ( ) תרגיל מספר 1.
תורת הקבוצות חלק ב'. קבוצה בת מניה הגדרה: קבוצה אינסופית X היא ניתנת למניה אם יש התאמה חד-חד ערכית בין X לבין .
תכנות תרגול 6 שבוע : תרגיל שורש של מספר מחושב לפי הסדרה הבאה : root 0 = 1 root n = root n-1 + a / root n-1 2 כאשר האיבר ה n של הסדרה הוא קירוב.
Backpatching 1. תזכורת מתרגול קודם קוד ביניים - שפת הרביעיות שיטות לייצור קוד ביניים –שימוש בתכונת code –כתיבה ישירה ל-buffer של פקודות שיטות לתרגום מבני.
א " ב, מילים, ושפות הפקולטה למדעי המחשב אוטומטים ושפות פורמליות ( ) תרגיל מספר 1.
תהליכים  מהו תהליך ?  מבני הנתונים לניהול תהליכים.  החלפת הקשר.  ניהול תהליכים ע " י מערכת ההפעלה.
ערכים עצמיים בשיטות נומריות. משוואה אופינית X מציין וקטור עצמי מציינת ערך עצמי תואם לוקטור.
תורת הקומפילציה * * הידור, למהדרין. שקפי הקורס מבוססים על שקפים מאת פרופ' מיכאל רודה.
הפקולטה למדעי המחשב אוטומטים ושפות פורמליות (236353)
The Cyclic Multi-peg Tower of Hanoi מעגלי חד-כווני סבוכיות הפתרון בגרסאות עם יותר מ-3 עמודים.
תורת הקומפילציה מרצה –ד"ר שירלי גינסברג שעת קבלה – יום שני 9:30-10:30 טאוב 318 מתרגלים –רותם אושמן, מתרגלת אחראית –סיוון ברקוביץ.
1 ניתוח לקסיקלי Wilhelm, and Maurer – Chapter 7 Aho, Sethi, and Ullman – Chapter 3 Cooper and Torczon – Chapter 2.
1 Data Structures, CS, TAU, Perfect Hashing בעיה: נתונה קבוצה S של n מפתחות מתחום U השוואה ל- Hash : * טבלה קבועה (Hash רגיל - דינאמי) * רוצים זמן קבוע.
מערכים עד היום כדי לייצג 20 סטודנטים נאלצנו להגדיר עד היום כדי לייצג 20 סטודנטים נאלצנו להגדיר int grade1, grade2, …, grade20; int grade1, grade2, …, grade20;
עקרון ההכלה וההדחה.
יחס סדר חלקי.
תורת הקומפילציה * * הידור, מהדיר, למהדרין. שקפי הקורס מבוססים על שקפים מאת פרופ' מיכאל רודה.
מבוא למדעי המחשב תרגול 3 שעת קבלה : יום שני 11:00-12:00 דוא " ל :
מבוא למדעי המחשב, סמסטר א ', תשע " א תרגול מס ' 1 נושאים  הכרת הקורס  פסאודו - קוד / אלגוריתם 1.
תורת הקומפילציה הרצאה 2 ניתוח לקסיקלי Wilhelm, and Maurer – Chapter 7 Aho, Sethi, and Ullman – Chapter 3 Cooper and Torczon – Chapter 2.
מתמטיקה בדידה תרגול 2.
1 מבוא למדעי המחשב סיבוכיות. 2 סיבוכיות - מוטיבציה סידרת פיבונאצ'י: long fibonacci (int n) { if (n == 1 || n == 2) return 1; else return (fibonacci(n-1)
1 Formal Specifications for Complex Systems (236368) Tutorial #3 Z introduction and notation (contd.); Birthday book example (Chapter 1 in the book)
Text to speech In Mobile Phones איתי לוי. הקדמה שימוש בהודעות טקסט על המכשירים הסלולארים היא דרך תקשורת מאוד פופולארית בימינו אשר משתמשים בה למטרות רבות,
11 Introduction to Programming in C - Fall 2010 – Erez Sharvit, Amir Menczel 1 Introduction to Programming in C תרגול
ניתוח לקסיקלי Wilhelm, and Maurer – Chapter 7 Aho, Sethi, and Ullman – Chapter 3 Cooper and Torczon – Chapter 2.
- אמיר רובינשטיין מיונים - Sorting משפט : חסם תחתון על מיון ( המבוסס על השוואות בלבד ) של n מפתחות הינו Ω(nlogn) במקרה הגרוע ובממוצע. ניתן לפעמים.
פיתוח מערכות מידע Class diagrams Aggregation, Composition and Generalization.
1 המרכז להוראת המדעים © האוניברסיטה העברית בירושלים עוברים לג ' אווה.
מבוא למדעי המחשב לתעשייה וניהול הרצאה 7. סברוטינות subroutines.
שיאון שחוריMilOSS-il מוטיבציה  python זה קל ו C זה מהיר. למה לא לשלב?  יש כבר קוד קיים ב C. אנחנו רוצים להשתמש בו, ולבסס מעליו קוד חדש ב python.
מבוא למדעי המחשב לתעשייה וניהול הרצאה 6. מפעל השעווה – לולאות  עד עכשיו  טיפלנו בייצור נרות מסוג אחד, במחיר אחיד  למדנו להתמודד עם טיפול במקרים שונים.
אביב תשס " ה JCT תיכון תוכנה ד " ר ר ' גלנט / י ' לויאןכל הזכויות שמורות 1 פרק 5 תרשימי מצבים Statecharts למחלקות תגובתיות Reactive Classes הקדמה ודוגמא.
מספרים אקראיים ניתן לייצר מספרים אקראיים ע"י הפונקציה int rand(void);
PRINCIPLES OF COMPILER DESIGN
Tirgul 12 Trees 1.
מבוא למדעי המחשב סיבוכיות.
Introduction to Compiler Construction
SQL בסיסי – הגדרה אינדוקטיבית
הפקולטה למדעי המחשב אוטומטים ושפות פורמליות (236353)
עבודה עם נתונים באמצעות ADO.NET
בעיות נוספות ב-NPC.
תזכורת מתרגולים אחרונים
Shell Scripts בסביבת UNIX
תוכנה 1 תרגול 13 – סיכום.
עקרונות בסיסיים בתכנות Visual Basic
Computer Programming תרגול 3 Summer 2016
Engineering Programming A
Computer Architecture and Assembly Language
Introduction to Compiler Construction
Introduction to Compiler Construction
Presentation transcript:

תורת הקומפילציה 236360 הרצאה 1 מבוא; ניתוח לקסיקלי

תורת הקומפילציה 236360 מרצה: ד"ר שירלי גינסברג מתרגלים shirleyh@cs שעת קבלה – יום שני 9:30-10:30 בתיאום מראש, טאוב 318 מתרגלים קירה רדינסקי, מתרגלת אחראית גלעד קותיאל רן צמח

אדמיניסטרציה אתר: http://webcourse.cs.technion.ac.il/236360 25% - תרגילי בית 5% תרגילים "יבשים", רשות (מגן) 20% תרגילים "רטובים", חובה 75% - מבחן סוף הקורס ציון נכשל במבחן גורר כשלון בקורס, ללא קשר לציון התרגילים. קדם: אוטומטים ושפות פורמליות 236353 מועד ג' למילואימניקים (בלבד). העתקות...

ספרות ספר עיקרי ספר משני A.V. Aho, M. S. Lam, R. Sethi, and J.D. Ullman – “Compilers – Principles, Techniques, and Tools”, Addison-Wesley, 2007 ספר משני R. Wilhelm, and D. Maurer – “Compiler Design”, Addison-Wesley, 1995

ספרות-המשך ספר נוסף K.D.Cooper and L.Torczon “Engineering A Compiler”, Morgan Kaufmann, 2004

פרס טיורינג March 10, 2009: ACM has named Barbara Liskov the recipient of the 2008 ACM A.M. Turing Award for her contributions to practical and theoretical foundations of programming language and system design.

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

קומפילציה (הידור) – מושגי יסוד זמן קומפילציה זמן ריצה compiler source program target program target program input output

אינטרפרטציה )= פרשנות( source program interpreter output input שימושים: שפות סקריפט שבהם כל שורה קוראת לביצוע של משהו מורכב (אין טעם ליעל) שפות מאד גבוהות (APL, Mathlab) שבהן הנתונים מורכבים ואינם ידועים בעת הקומפילציה

דוגמא למבנה מודרני חשוב - Java source program Bytecode is standard, machine-independent Translator (javac) Intermediate program (bytecode) Java Virtual Machine output input Virtual machine- תלוי מכונה. מבצע טוב כפי יכולתו על המכונה הנתונה. Just In Time -- תוך כדי פרשנות התכנית, ה-interpreter מבצע קומפילציה של חלקי תוכנית על מנת שהמשך הביצוע יהיה מהיר יותר.

הידור / אינטרפרטציה – הכללות Source to Source Virtual Machine Pre-processors C ++ program translator C program compiler Java program Java bytecode program with embedded pre-pocessing statements (e.g., #include, macros) preprocessor “pure” program

שימושים של קופיילרים יעד קוד מכונה: SPARC, P690, IA32 שפת אסמבלי קוד עבור אינטרפרטר: Java Virtual Machine, P-Code, … שפות עבוד טקסט: PostScript, TeX, html, RTF, … תוכנה למכשור מעגל חשמלי קלט שפות תכנות:C, Pascal, Assembler,... שפות לעיבוד טקסט: PostScript, TeX, html, RTF,… שפות scripting: C-shell, emacs, perl, Hypercard… שפות שאילתה לעבוד נתונים (SQL) שפות לתיאור חומרה (VHDL) שפות בקרה

כלים נוספים לעיבוד שפה – דוגמא Skeletal source program Preprocessor Source program Target assembly program Assembler Relocateable machine code Loader/Link-editor Absolute machine code איסוף מודולים, פתיחת מקרואים. compiler כתובות יחסיות, הפניות לספריה Library, releasable, object files כתובות יחסיות, לכל התוכנית Link: כתובות אבסולוטיות Load:

קומפילציה – חשיבות התחום לפיתוח שמושים מתקדמים ניצול של כלים לפיתוח קומפיילרים להקלת מאמץ הפיתוח קריאה (ו"הבנה") אוטומטית של קבצי קלט למפתחי תוכנה הבנה של האבחנה בין זמן קומפילציה לזמן ריצה הבנה של מה יעשה קומפיילר עם התוכנה שלכם (שיפור זמן ריצה, התראות של שגיאות) שימוש נכון במבנים שונים של שפות התכנות ניצול נכון של ארכיטקטורת המחשב

קומפילציה – חשיבות התחום לאנשי שפות תכנות תמיכה יעילה בשפה חדשה לאנשי ארכיטקטורה של מחשבים הבנה טובה של האיזון העדין שבין חומרה לתכנה הבנה מעמיקה מה יעשה קומפיילר (כלומר: מה תעשה כל תוכנה) עם החומרה שלכם

תורת הקומפילציה – תוכן הקורס מבוא מבנה הקומפיילר ניתוח מילוני (lexical analysis) ניתוח תחבירי (parsing) ניתוח סמנטי יצירת קוד סביבת זמן הריצה (טיפול ברוטינות, ניהול זיכרון, וכו') נושאים מתקדמים: אופטימיזציות, ניתוח סטטי, Data-flow analysis, לא נדבר על: קומפיילרים Just-In-Time ו-Virtual Machines,

מבנה הקומפיילר – תמונה כללית Wilhelm and Maurer – Chapter 6 Aho, Sethi, and Ullman – Chapter 1 Cooper and Torczon – Chapter 1

קומפיילר – כקופסא שחורה int a, b; a = 2; b = a*2 + 1; מתרגם משפת המקור לשפת היעד תוכנית זהה סמנטית (עושה אותו דבר) כיוון שהתירגום מסובך, חילקו אותו לשלבים מודולריים סטנדרטיים. source code target code SET R1,2 STORE #0,R1 SHIFT R1,1 STORE #1,R1 ADD R1,1 STORE #2,R1

קומפיילר – חלוקה גסה תוכנית מקור analysis Front End יצוג ביניים תוכנית מטרה analysis Front End יצוג ביניים code optimization ייצוג ביניים Back End code generation

מרכיבי הקומפיילר – חלוקה עדינה Character Stream Intermediate Representation Lexical Analyzer Machine-Independent Code Optimization Token Stream Syntax Analyzer Intermediate Representation Syntax Tree Code Generator Semantic Analyzer Target Machine Code Decorated Syntax Tree Machine-Dependent Code Optimization Intermediate Code Generator Target Machine Code

מרכיבי הקומפיילר – Front End Character Stream קל, טיפול בביטויים רגולריים Lexical Analyzer Token Stream יותר מסובך, רקורסיבי, עבודה עם דקדוק חסר הקשר. Syntax Analyzer Syntax Tree יותר מסובך, רקורסיבי, דורש עליה וירידה בעץ של הגזירה. Semantic Analyzer Decorated Syntax Tree השטחת העץ. חלק האופטימיזציות נח לעשות על עץ, וחלק על קוד Intermediate Code Generator

דוגמה לתפקידי החלקים

דוגמה לתפקידי החלקים

טבלת הסמלים מבנה נתונים לכל identifier. שומר את התכונות שלו (attributes) ומאפשר גישה מהירה. לדוגמא: מיקום בזיכרון, טיפוס, scope. הטבלה נבנית במהלך הניתוח. למשל: הניתוח הלקסיקלי לא מגלה מה הטיפוס. רק השלב של ייצור הקוד יודע את מיקום המשתנה בזיכרון, וכיו"ב.

הודעות שגיאה חלק חשוב של תהליך הקומפילציה כל שלב מגלה שגיאות ברמת הניתוח שלו של התוכנית. מודיע על השגיאה ומנסה כמיטב יכולתו להמשיך בקומפילציה

יתרון חשוב של מודולריות ... שפה ב שפה א analysis n analysis 2 analysis 1 machine independent optimization machine dependent optimization code generation machine dependent optimization code generation … מכונה m מכונה 1

שפת ביניים שפה קלה לייצור, שקל לייצר ממנה קוד אמיתי, ונוחה לעבודה לאופטימיזציה. אנו נשתמש בצורה הנקראת three-address code שבה כל תא בזיכרון יכול לשמש פרמטר לכל פעולה. temp1 := inttoreal(60) temp2 := id3 * temp1 temp3 := id2 + temp2 id1 := temp3

שלב האופטימיזציה יצירת קוד הביניים נעשית בצורה אוטומטית. הקוד ניתן לשיפור temp1 := inttoreal(60) temp2 := id3 * temp1 temp3 := id2 + temp2 id1 := temp3 temp1 := id3 * 60.0 id1 := id2 + temp1

machine independent optimization שלב האופטימיזציה Decorated Syntax Tree machine independent optimization דוגמאות constant propogation common subexpressions dead code elimination

אופטימיזציה לא ניתן לייצר קוד אופטימלי (NP-שלם או לא ניתן להכרעה, תלוי מה מנסים לעשות...). לכן משתמשים בהיוריסטיקות. חובה לשמור על נכונות; צריך לשפר (כמעט תמיד); חישוב האופטימיזציה צריך להיות יעיל. שיפורים: מהירות, מקום, אנרגיה, וכו'. החלק שתופס זמן מירבי בתהליך הקומפילציה. השאלה העיקרית: כמה זמן שווה להשקיע באופטימיזציה עבור ייעול תוכנית המטרה. התשובה מאוד משתנה עבור JIT.

אופטימיזציה מודרנית האתגר העיקרי הוא לנצל פלטפורמות מודרניות Multicores פקודות ווקטוריות היררכית זיכרונות האם הקוד מועבר ברשת (Java Bytecode)?

שלב הסינתזה ((back-end decorated syntax tree target program address assignmet code generation peephole optimizer machine dependent optimization

ייצור קוד (Code Generation) שלב אחרון: ייצור קוד של שפת המטרה. משימה חשובה: החלטה על מיקום המשתנים בזיכרון. האתגר העיקרי: לאיזה משתנים יוקצו רגיסטרים באיזה שלב של התוכנית? פעולות על רגיסטרים מהירות משמעותית מפעולות על הזיכרון. השמה אופטימלית למקרה הגרוע ביותר היא קשה (NP-קשה), היוריסטיקות מאד טובות קיימות.

ה- back-end, דוגמא int a, b; a = 2; b = a*2 + 1; (front end) a = 2 temp1 = a*2 b = temp1 + 1 address assignment a0 temp1 1 b2 code generation a = 2 temp1 = a << 1 b = temp1 + 1 machine indep. optimization SET R1,2 STORE #0,R1 LOAD R1,#0 SHIFT R1,1 STORE #1,R1 LOAD R1,#1 ADD R1,1 STORE #2,R1 SET R1,2 STORE #0,R1 SHIFT R1,1 STORE #1,R1 ADD R1,1 STORE #2,R1 machine-dependent optimization

כלים חלק משמעותי מהמאמץ בכתיבת קומפיילרים חוזר על עצמו בין קומפיילרים שונים. כלים מיועדים לחסוך את החלק החוזר. Parser generators: חלקם מתבססים על אלגוריתמים מורכבים. Lexical generator (עבור ניתוח לקסיקאלי) Syntax-directed translation engines מעבר על העץ האבסטרקטי ויצירת קוד ביניים ממנו ע"י ביצוע פעולה על כל צומת. Data Flow Engines עבור אופטימיזציה.

לסיכום קומפיילר מתרגם משפת מקור לשפת יעד (ובדרך מספק בדיקת שגיאות חשובה). על מנת להקטין את הסיבוכיות התירגום מחולק למודולים ברורים ונפרדים. שלב ה-front-end מביא את התוכנית לייצוג ביניים שנוח לעבוד איתו באופן אוטומטי. שלב ה-back-end מבצע אופטימיזציות ומייצר קוד של שפת המטרה. בהמשך – נתחיל בהבנת ה-front-end.

ניתוח לקסיקלי Wilhelm, and Maurer – Chapter 7 Aho, Sethi, and Ullman – Chapter 3 Cooper and Torczon – Chapter 2

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

מנתח לקסיקלי – אינטרקציה עם ה-parser תוכנית מקור Lexical Analyzer error message manager get next token token parser

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

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

תפקידי ה- lexical analyzer קריאת הקלט, והפרדתו ליחידות לקסיקליות (לקסמות) דוגמאות: integer, real, boolean, string , שמות משתנים, הערות, סימנים מיוחדים (למשל =<). זיהוי ה-patterns, מיונם ויצירת tokens עם שמות ותכונות. טיפול ב- keywords -- מילות מפתח שאינן שמורות, זיהוי reserved words, לפעמים מממש גם preprocessing, (include files ו- macros). ספירת מספר שורות (למה?) דיווח על שגיאות: symbols לא חוקיים. הדפסת פלט (התוכנית בשילוב הודעות שגיאה), עשוי לכלול pretty printing. (יש לעקוב אחרי מספרי השורות והעמודות בהם מופיעים ה- tokens)

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

משפחות של סמלים (Patterns) symbol class תוכנית המשתמש ID foo n_14 last NUM 73 00 517 082 REAL 66.1 .5 10. 1e67 5.5e-10 IF if COMMA , NOTEQ != LPAREN ( RPAREN )

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

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

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

דוגמא עבור הביטוי e = m * c ** 2 :, נעביר את ה-tokens הבאים: < id , pointer to symbol table entry for e > < assignment > < id , pointer to symbol table entry for m> < multiplication > < id , pointer to symbol table entry for c> < exponentiation > < number , integer value 2 >

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

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

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

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

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

ביטויים רגולריים, שפות רגולריות  הוא ביטוי רגולרי מעל  המתאר את השפה הריקה  הוא ביטוי רגולרי מעל  המתאר את השפה 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* ) כל שפה הניתנת לכתיבה כביטוי רגולרי היא שפה רגולרית.

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

דוגמא תהי Σ={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, …}

תיאור 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 ) (  | E ( 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 ) ( 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 )* ) ) שיטת תיאור זאת קשה לשימוש. לכן נשתמש בשמות של קבוצות.

תיאור 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)+

דוגמאות 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 ) - את זה לא נעביר לשלב הבא אלא נתעלם

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

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

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

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

סימונים

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

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

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

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

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

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

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

דוגמאות:

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

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

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

תהליך בניית ה-lexical analyzer בניית תיאור ה-tokens האפשריים כביטויים רגולריים. החלטה על תכונות שיישמרו בעת זיהוי token מכל סוג מעבר לאוטומט דטרמניסטי כולל המתאר את כל הביטויים האפשריים (טבלת מעברים) + שמירת תכונות. נעשה באופן אוטומטי ע"י scanner generator. הפלט של ה-scanner generator משמש את ה-driver של הניתוח הלקסיקלי. ה-driver והטבלאות של השפה הופכים להיות החלק הראשון של הקומפיילר.

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

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