שאלת מבחן בשפות תכנות - האוניברסיטה הפתוחה 2024 - מפרשים
שאלה זו עוסקת בשדרוג של שפת ה־PROC המתוארת בספר הלימוד בפרק 3 (עמודים 74–81).
מאפשרים להרחיב את שפה זו בביטוי חדש בשם
התחביר של הביטוי החדש הוא:
עם ייצוג AST:
כאשר:
הפעולה הכללית של הביטוי החדש:
ביטוי
- משתנה הזמן החוזר עליו הלולאה —
- מרשימת ה-exps שמהווה את הרשימה שמשתנה הלולאה אמור לסקור
- מרשימת ה-guards המורכבת מביטויים שיכולים להיות skip או break (יכולים לחזור על עצמם) — כל סוג guard מורכב מביטוי בוליאני
- הביטוי body שהוא גוף הלולאה
הלולאה עוברת על האיברים של רשימת הלולאה לפי מיקום id, מתחילה מהאיבר הראשון, ולכל אחד מהם בודקת תחילה אם מתקיים אחד מה-guards (בודקים לפי סדר הגדרתם). במידה ונמצא guard אחד שמתקיים, לא יבוצע גוף הלולאה עבור אותו איבר. אם הביטוי שהתקיים guard הוא מסוג skip, יש להמשיך את הלולאה ולעבור לאיבר הבא; ואם ה-guard שהתקיים הוא מסוג break, יש להפסיק את הלולאה ולהחזיר את הסכום שהצטבר עד לשלב זה. במידה ולא מצאנו guard אחד שמתקיים, יחשב גוף הלולאה והתוצאה תתווסף לסכום הכולל.
דוגמה 1:
בדוגמה 1, מוגדרת לולאה עם משתנה i ורשימת ערכים. ללולאה זו 3 guards. לכל האיברים: אם האיבר הוא 1 יש לדלג עליו, אם האיבר הוא 5 יש להפסיק, ואם האיבר הוא 3 יש לדלג. לפיכך הלולאה תפעל רק על האיברים 2 ו-20 (הביניהם 3 ו-1 מדולגים), עליהם הלולאה תחשב את ערכן של גוף הלולאה שמחזיר תוספת 5. לכן הסכום הכולל שיצטבר יהיה 32 (= (20+5) + (2+5)) ולכן הניב הסופי הוא (num-val 32).
דוגמה 2:
בדוגמה 2, מוגדרת לולאה עם רשימה ריקה, זה אינו תקין (על פי הרקורסיה המוגדרת) ולכן הורפסה הודעת שגיאה מתאימה.
דוגמה 3:
בדוגמה 3, מוגדרת לולאה שאינה כוללת guards (אפס guards, תקין תחבירית) ולכן הלולאה תפעל על כל האיברים והתוצאה תהיה סכום כל האיברים בתוספת 5 לכל אחד.
עליך לממש את השינויים הדרושים בתוך שפת ה-PROC (שפת ייחסמוריות) בתוך קבצי המפרש, הקפד להסביר בקצרה בקבצי המפרש, ולציין את השורות הדרושות והמתחנות.
הוראות לחלקים הנלמדים:
1. הקפד על כתב ברור, ועל קוד מובן ומסודר.
2. הקפד על פתיחות וסגירות במקומות המתאימות.
3. התוצר אמור לשמור על הגדרת השפה הנדרשת שיוגדר לזה במפרש בשאלה.
4. על מנת לפשט קוד ארוך, כדאי להיעזר בפונקציות עזר (מחוץ value-of).
5. בפרט, הקפד על הבחנה ושימוש מכון בין ביטוי (expression) לבין תוצאת חישוב ביטוי (expval) לבין identifier.
6. ניקוד יורד על אי הבחנה ומימוש מכון של הרקורסיה הנחונה בשאלה, כלומר יש להקפיד על הכון ב-terminals, non-terminals הפעולות של פסיקור ( )* או { }+.
מאפשרים להרחיב את שפה זו בביטוי חדש בשם
forsum-exp המאפשר לגלגל לולאה על רשימת ערכים מספריים, תוך אפשרות לעצירת הלולאה או דילוג על איברים. מרשימת ה-exps מהווה משתנה הלולאה אמור לסקור. מרשימת ה-guards מורכבת מביטויים (guards) יכולים להיות skip או break. הביטוי מחזיר את הסכום של תוצאות הפעולה לכל איבר ברשימה שעליו פעלה הלולאה.התחביר של הביטוי החדש הוא:
Expression ::= for/sum [ identifier ({Expression}*(,)) ]
{ <guard> }*
Expression
for/end
עם ייצוג AST:
forsum-exp (id exps guards body)
כאשר:
guard ::= skip : Expression skip-guard (boolexp) guard ::= break : Expression break-guard (boolexp)
הפעולה הכללית של הביטוי החדש:
ביטוי
forsum-exp מורכב מהמרכיבים הבאים:- משתנה הזמן החוזר עליו הלולאה —
id- מרשימת ה-exps שמהווה את הרשימה שמשתנה הלולאה אמור לסקור
- מרשימת ה-guards המורכבת מביטויים שיכולים להיות skip או break (יכולים לחזור על עצמם) — כל סוג guard מורכב מביטוי בוליאני
- הביטוי body שהוא גוף הלולאה
הלולאה עוברת על האיברים של רשימת הלולאה לפי מיקום id, מתחילה מהאיבר הראשון, ולכל אחד מהם בודקת תחילה אם מתקיים אחד מה-guards (בודקים לפי סדר הגדרתם). במידה ונמצא guard אחד שמתקיים, לא יבוצע גוף הלולאה עבור אותו איבר. אם הביטוי שהתקיים guard הוא מסוג skip, יש להמשיך את הלולאה ולעבור לאיבר הבא; ואם ה-guard שהתקיים הוא מסוג break, יש להפסיק את הלולאה ולהחזיר את הסכום שהצטבר עד לשלב זה. במידה ולא מצאנו guard אחד שמתקיים, יחשב גוף הלולאה והתוצאה תתווסף לסכום הכולל.
דוגמה 1:
(run "for/sum [i (1,2,3,20,5,90)]
<skip: zero?(-(i,1))>
<break: zero? (-(i,5))>
<skip: zero? (-(i,3))>
-(i,-5)
for/end")
=> (num-val 32)
בדוגמה 1, מוגדרת לולאה עם משתנה i ורשימת ערכים. ללולאה זו 3 guards. לכל האיברים: אם האיבר הוא 1 יש לדלג עליו, אם האיבר הוא 5 יש להפסיק, ואם האיבר הוא 3 יש לדלג. לפיכך הלולאה תפעל רק על האיברים 2 ו-20 (הביניהם 3 ו-1 מדולגים), עליהם הלולאה תחשב את ערכן של גוף הלולאה שמחזיר תוספת 5. לכן הסכום הכולל שיצטבר יהיה 32 (= (20+5) + (2+5)) ולכן הניב הסופי הוא (num-val 32).
דוגמה 2:
(run "for/sum [i ()]
<skip: zero?(-(i,1))>
<break: zero? (-(i,5))>
<skip: zero? (-(i,3))>
-(i,-5)
for/end")
=> interp.scm:79:16: forsum-exp: The list for i is empty
בדוגמה 2, מוגדרת לולאה עם רשימה ריקה, זה אינו תקין (על פי הרקורסיה המוגדרת) ולכן הורפסה הודעת שגיאה מתאימה.
דוגמה 3:
(run "for/sum [i (1,2,3,20,5,90)]
-(i,-5)
for/end")
=> (num-val 151)
בדוגמה 3, מוגדרת לולאה שאינה כוללת guards (אפס guards, תקין תחבירית) ולכן הלולאה תפעל על כל האיברים והתוצאה תהיה סכום כל האיברים בתוספת 5 לכל אחד.
עליך לממש את השינויים הדרושים בתוך שפת ה-PROC (שפת ייחסמוריות) בתוך קבצי המפרש, הקפד להסביר בקצרה בקבצי המפרש, ולציין את השורות הדרושות והמתחנות.
הוראות לחלקים הנלמדים:
1. הקפד על כתב ברור, ועל קוד מובן ומסודר.
2. הקפד על פתיחות וסגירות במקומות המתאימות.
3. התוצר אמור לשמור על הגדרת השפה הנדרשת שיוגדר לזה במפרש בשאלה.
4. על מנת לפשט קוד ארוך, כדאי להיעזר בפונקציות עזר (מחוץ value-of).
5. בפרט, הקפד על הבחנה ושימוש מכון בין ביטוי (expression) לבין תוצאת חישוב ביטוי (expval) לבין identifier.
6. ניקוד יורד על אי הבחנה ומימוש מכון של הרקורסיה הנחונה בשאלה, כלומר יש להקפיד על הכון ב-terminals, non-terminals הפעולות של פסיקור ( )* או { }+.
העתק שאלה
שתף שאלה
סמן כחשוב
סמן כבוצע
האוניברסיטה הפתוחהמועד ג2024סמסטר ב
★★★★★
מפרשיםתכנות פונקציונליSchemeמעקב אחר קוד
הוסיפו
forsum-exp כ-datatype חדש עם שדות id, exps, guards, body. ב-value-of, עברו על רשימת הערכים באמצעות לולאת עזר (loop עם accumulator), ולכל איבר בדקו את ה-guards בסדר — skip מדלג, break מחזיר את הסכום הנוכחי, ואם אף guard לא מתקיים חשבו את body והוסיפו לסכום.פתרון שאלה 1 — מימוש `forsum-exp` בשפת PROC
יש להוסיף את הביטוי
1. הגדרת תחביר (grammar / define-datatype):
2. parsing — הוספה ל-`parse-expression`:
וכן parsing של guard:
3. ביצוע — הוספה ל-`value-of`:
עזר — `apply-guards`:
הסבר: עבור כל איבר ברשימה, מרחיבים את הסביבה ב-id, בודקים את ה-guards בסדר. אם guard מסוג skip מתקיים — מדלגים ועוברים לאיבר הבא. אם guard מסוג break מתקיים — מחזירים את הסכום שהצטבר עד כה. אם אף guard לא מתקיים — מחשבים את body ומוסיפים לסכום.
יש להוסיף את הביטוי
forsum-exp למפרש PROC. נדרשים השינויים הבאים:1. הגדרת תחביר (grammar / define-datatype):
2. parsing — הוספה ל-`parse-expression`:
וכן parsing של guard:
3. ביצוע — הוספה ל-`value-of`:
עזר — `apply-guards`:
הסבר: עבור כל איבר ברשימה, מרחיבים את הסביבה ב-id, בודקים את ה-guards בסדר. אם guard מסוג skip מתקיים — מדלגים ועוברים לאיבר הבא. אם guard מסוג break מתקיים — מחזירים את הסכום שהצטבר עד כה. אם אף guard לא מתקיים — מחשבים את body ומוסיפים לסכום.