به نام خدا طراحی کامپایلرها 40-414 4
مشکالت تحلیل نحوی باال به پایین چپ گردی در گرامر مستقل از متن می تواند تحلیلگر نحوی را در حلقه ی نامتناهی بیاندازد مثال برای قاعدهی A A α رویهی زیر را داریم: prcedure A begin if lkahead is in First(Aα) then call prcedure A end راه حل: حذف چپ گردی البته بدون این که زبان متناظر گرامر تغییر کند 1
مواجهه با چپ گردی الگوریتمی برای حذف چپ گردی ایده ی اولیه: A A α β A β R R α R ε مثال: expr term id expr + term expr - term term expr term rest rest + term rest - term rest ε term id 2
حل مشکالت: چپ گردی )1( گرامر دارای چپ گردی قاعده ای دارد که به کمک آن اشتقاقی برای بعضی α ها قابل انجام است مثل A * A α تحلیل نحوی باال به پایین نمی تواند با چنین گرامرهایی کنار بیاید زیرا باید تصمیم ثابتی بگیرد که نتیجتا باعث خاتمه نیافتن A A α β آن خواهد شد A A α A α α A α α α به صورت کلی: A A α β A β A A α R ε گرامر دارای چپ گردی گرامر بدون چپ گردی 3
حل مشکالت: چپ گردی )2( به شکل غیررسمی: ( هب همه ی قواعد مربوط به A را در نظر بگیرید و به این شکل مرتب کنید طوری که هیچ β i با A آغاز نشود(: A A α 1 A α 2 A α m β 1 β 2 β n حاال روشی را که پیش تر گفته شد روی آن ها اعمال کنید: A β 1 A β 2 A β n A A α 1 A α 2 A α m A ε با این حساب در مثال ما: E T F E + T T T * F F ( E ) id E T E E + T E ε T F T T * F T ε 4
حل مشکالت: چپ گردی )3( مشکل: اگر چپگردی دو یا چند مرحله عمق داشته باشد روش گفتهشده کافی نیست S A a b A A c S d ε S A a S d a ورودی: گرامر G که غیرپایانههای آن به صورت A 1, A 2,, A n خروجی: گرامر معادلی که چپگردی ندارد مرتب شده اند 1 غیرپایانهها را به شکل A 1, A 2,, A n مرتب کنید )که A 1 نماد شروع است( 2 برای i از 1 تا n شروع برای j از 1 تا - 1 i شروع هر قاعده به شکل A i A j γ را با قاعدهای به شکل A j δ 1 δ 2 δ k به طوری که A i δ 1 γ δ 2 γ δ k γ قاعدههای فعلی مربوط به A j هستند جایگزین کنید پایان چپگردی مستقیم را از همهی قاعدههای مربوط به A i حذف کنید پایان 5
حل مشکالت: چپ گردی )4( A 1 A 2 a b ε استفاده از الگوریتم در مثال: A 2 A 2 c A 1 d = 1 i در مورد A 1 هیچ چپگردیای وجود ندارد برای j از 1 تا 1 قاعدههای به شکل A 2 A 1 γ را با قاعدههایی به شکل A 1 δ 1 δ 2 δ k به طوری که A 2 δ 1 γ δ 2 γ δ k γ قاعدههای فعلی مربوط به هستند جایگزین میکنیم A 2 A 2 a d b d d تبدیل میشود A 1 بنابراین در مثال A 2 A 1 d به i = 2 A 1 A 2 A 2 a b ε A 2 c A 2 a d b d d آن چه باقی می ماند : آیا کار تمام شده است 6
حل مشکالت: چپ گردی )5( نه کار تمام نشده. هنوز باید چپ گردی را حذف کنیم: A 1 A 2 A 2 a b ε A 2 c A 2 a d b d d باید این قاعده را که پیش تر گفته شد اعمال کنیم: A A α 1 A α 2 A α m β 1 β 2 β n A β 1 A β 2 A β n A A α 1 A α 2 A α m A ε 7
تبدیل می شود به حل مشکالت: فاکتورگیری چپ مشکل: کدام یک از دو قاعده ی زیر باید انتخاب شود stmt if expr then stmt else stmt if expr then stmt حالت کلی چنین مشکلی: A α β 1 α β 2 α if expr then stmt rest در مثال ما β 1 β 2 else stmt ε A α A stmt if expr then stmt rest A β 1 β 2 rest else stmt ε 8
تحلیل نحوی مبتنی بر جدول پویش )1( )تحلیل لغوی( چپ به راست )2( یافتن اشتقاق چپ گرد E T E E + T E ε T id گرامر: خاتمه دهنده $ id id + ورودی: E اشتقاق: )پشته( انباره پردازش 9
گرامرهای LL(1) :L پویش ورودی از چپ به راست L: ساخت اشتقاق چپ گرد 1: برای تصمیمگیری در تحلیل نحوی عالوه بر انباره تنها به کی»» نشانهی پیش رو از ورودی نگاه میکند در جدول تحلیل گرامرهای LL(1) در هیچ خانهای 2 قاعده به چشم نمیخورد ویژگی های گرامرهای :LL(1) مبهم نیستند و چپگردی ندارند برای قاعدههایی به شکل :A α β.1.2.3 هیچ دو رشته از رشتههایی که از α و β مشتق میشوند نباید با نماد یکسان )مثال a( شروع شوند. به عبارت دیگر اشتراک First(α) و First(β) باید تهی باشد. ε حداکثر از یکی از α یا β ممکن است مشتق شود اگر ε از α مشتق می شود آنگاه اشتراک First(β) و Fllw(A) همه ی نمی توان را گرامرها به شکل LL(1) تبدیل کرد باید تهی باشد. 10
روش غیربازگشتی و مبتنی بر جدول $ b a + ورودی )رشتهی اصلی + خاتمهدهنده( رفتار کلی تحلیلگر با توجه به:.1.2 )ورودی فعلی( و )باالی انباره( وقتی $ = a X = کار پایان می یابد و رشته ی ورودی پذیرفته می شود وقتی $ a X X = را از روی انباره برمیداریم نشانهی بعدی را از ورودی.3 میگیریم و به قدم )1( برمیگردیم وقتی X یک غیرپایانه باشد خانهی M[X,a] در جدول بررسی میشود: خروجی مشخص می کند که با توجه به ورودی و انباره تحلیلگر باید چه تصمیمی بگیرد اگر خطا بود رویه ی برخورد با خطا فراخوانی می شود اگر قاعده ای به شکل تحلیلگر نحوی پیش گو جدول تحلیل M[A,a] X Y Z $ نشانه ی انتهای انباره X X U V W بود X را از روی انباره برمیداریم و به a ترتیب V W و U را روی انباره قرار میدهیم )به ورودی کاری نداریم( انباره )غیرپایانه ها و پایانه های گرامر( 11
تحلیل نحوی غیربازگشتی )1( E T E E + T E ε T F T T * F T ε F ( E ) id مثال: جدول M نشانهی ورودی غیرپایانه ها id + * ( ) $ E E T E E T E E E + T E E ε E ε T T F T T F T T T ε T * F T T ε T ε F F id F ( E ) 13
تحلیل نحوی غیربازگشتی )2( مثال روند تحلیل نحوی: گسترش ورودی انباره ورودی خروجی $ E id + id * id $ E T E $ E T id + id * id $ T F T $ E T F id + id * id $ F id $ E T id id + id * id $ $ E T + id * id $ T ε $ E + id * id $ E + T E $ E T + + id * id $ $ E T id * id $ T F T $ E T F id * id $ F id $ E T id id * id $ $ E T * id $ T * F T $ E T F * * id $ $ E T F id $ F id $ E T id id $ $ E T $ T ε $ E $ E ε $ $ 14
تحلیل نحوی غیربازگشتی )3( اشتقاق چپ گرد مثال قبلی: E T E F T E id T E id E id + T E id + F T E id + id T E id + id * F T E id + id * id T E id + id * id E id + id * id 15
1 4 چه چیزی کم داریم جدول تحلیل M هنوز ساخته نشده است! یک مجموعههای First و Fllw را برای گرامر به دست آورید. دو الگوریتم زیر را جهت ساخت جدول تحلیل اعمال کنید: قدمهای )2( و )3( را به ازای هر قاعده به شکل A α تکرار میکنیم: 2 اگر پایانهی a در First(α) باشد A α را در خانهی [a M[A, میگذاریم 3 اگر ε عضو First(α) باشد A α را در تمام خانههای [b M[A, میگذاریم که b عضو Fllw(A) است همهی خانههای باقیماندهی جدول که خالیاند معر ف خطای نحوی هستند. 16
ساخت جدول تحلیل )2( مثال :1 S i E t S S a First(S) = { i, a } Fllw(S) = { e, $ } S e S ε First(S ) = { e, ε } Fllw(S ) = { e, $ } E b First(E) = { b } Fllw(E) = { t } S i E t S S S a E b First(i E t S S ) = { i } First(a) = { a } First(b) = { b } S e S S ε First(e S) = { e } First(ε) = { ε } Fllw(S ) = { e, $ } نشانهی ورودی غیرپایانه ها a b e i t $ S S a S i E t S S S E + T E S ε S e S E E b S ε 18
ساخت جدول تحلیل )3( E T E E + T E ε T F T T * F T ε F ( E ) id E T E First(E, F, T) = { (, id } First(E ) = { +, ε } First(T ) = { *, ε } E + T E مثال :2 Fllw(E, E ) = { ), $ } Fllw(F) = { *, +, ), $ } Fllw(T, T ) = { +, ), $ } E b First(T E ) = First(T) = { (, id } First(+ T E ) = { + } First(b) = { b } E ε First(ε) = { ε } T ε First(ε) = { ε } با توجه به قدم )2( در الگوریتم با توجه به قدم )3( در الگوریتم نشانهی ورودی غیرپایانهها id + * ( ) $ E E T E E T E E E + T E E ε E ε T T F T T F T T T ε T * F T T ε T ε F F id F ( E ) 19
)1( حل مشکالت: گرامرهای مبهم این گرامر را در نظر بگیرید: stmt if expr then stmt if expr then stmt else stmt ther stmt مشکل چیست یک درخت تحلیل ساده: if expr then stmt else stmt E 1 S 1 if expr then stmt else stmt else باید به then قبلی مربوط شود E 2 S 2 S 3 20
)2( حل مشکالت: گرامرهای مبهم stmt درختهای تحلیل مثال: شکل :1 if expr then stmt E 1 if expr then stmt else stmt E 2 S 1 S 2 stmt شکل :2 if expr then stmt else stmt E 1 if expr then stmt S 2 E 2 S 1 اینجا چه مشکلی وجود دارد 21
حذف ابهام )1( اگر این گرامر را در نظر بگیریم: stmt if expr then stmt if expr then stmt else stmt ther S i E t S i E t S e S s E a i a t i a t s e s یا اگر بخواهیم ساده تر بگوییم: رشته ای که مشکل ایجاد می کند: 22
حذف ابهام )2( گرامر را اصالح می کنیم تا ابهام حذف شود: S i E t S i E t S e S a E b S M U E M U i E t M e M a i E t S i E t M e U b گرامر اصالح شده را روی گرامر اصالح شده به صورت خواناتر: i a t i a t s e s می آزماییم stmt matched_stmt unmatched_stmt matched_stmt if expr then matched_stmt else matched_stmt ther unmatched_stmt if expr then stmt if expr then matched_stmt else unmatched_stmt 23
پردازش خطا شناسایی خطاها پیداکردن جایی که خطا در آن رخ داده است )مثال خطی از کد( اطالعرسانی دقیق و روشن مواجهه با )یا عبور از( خطا برای ادامهی کار و یافتن خطاهای احتمالی آینده در کامپایل برنامههای صحیح نباید تغییری ایجاد شود 24
راه بردهای مواجهه با خطا )1( حالت ترس به یک نشانه ی :)Panic Mde(»همگام سازی«دور انداختن نشانه ها )Synchrnizing( تا جایی که بربخوریم نشانههای همگامسازی مثل:»end«و»;«و»{«در زبانهای برنامهسازی بسته به تصمیم طراح کامپایلر کاستی ها: دور انداختن ورودی باعث عدم تعریف صحیح )مثال تعریف متغیرها( و به این ترتیب ایجاد خطاهای بیشتر میشود خطاهای احتمالی در بخشی که دور انداختهایم شناسایی نمیشوند مزایا: سادگی )به ویژه برای حالتی که در هر عبارت «کی سطح عبارت Level( :)Phrase» خطا وجود دارد مناسب است( تصحیح محلی ورودی مثال در برخورد با»,«به جای»;,«حذف و»;«اضافه میشود بسته به تصمیم طراح کامپایلر برای همهی خطاها مناسب نیست می تواند به همراه حالت ترس استفاده میشود تا ورودی کمتری دور انداخته شود 25
راه بردهای مواجهه با خطا )2( قواعد خطا )Errr Prductins( افزودن قواعدی به گرامر به منظور ساخت یا تولید تحلیلگر نحوی مثال قاعدهای برای عالمت =: )انتساب در پاسکال( به گرامر زبان C میافزاییم خطا گزارش داده می شود اما فرآیند کامپایل ادامه می یابد تصحیح داخلی )گرامر( و پیامهای عیبیابی تصحیح سراسری )Glbal Crrectin( افزودن حذف کردن یا جای گزینی نشانه ها نتیجه ای نامشخص دارد و ممکن است به تغییرات زیادی منجر شود الگوریتم هایی وجود دارند که می کوشند این تغییرات را در سطح برنامه به حداقل برسانند 26
اصالح خطا خطا در چه صورتی رخ می دهد یادآوری تحلیلگر نحوی: $ b a + ورودی X Y Z $ خروجی تحلیلگر نحوی پیش گو جدول تحلیل M[A,a] انباره )1( در صورتی که X پایانه باشد و با ورودی انطباق نداشته باشد )2( در صورتی که ]ورودی M]X, خالی باشد دو روش اصالح: حالت ترس سطح عبارت 27
)1( اصالح خطا: روش حالت ترس فرض کنید A یک غیرپایانه در باالی انباره باشد ایده: ورودیها را دور بیاندازیم تا به یکی از نشانههای از مجموعه ی انتخاب اعضای اگر پیش تعریف شده ی مجموعه ی همگام سازی همگام سازی برسیم مهم است مثال : مجموعهی همگامسازی را Fllw(A) در نظر بگیریم و ورودیها را دور بیاندازیم تا به عضوی از این مجموعه برسیم. A را از باالی انباره برداریم و تحلیل نحوی را ادامه دهیم مجموعهی همگامسازی را First(A) در نظر بگیریم و ورودیها را دور بیاندازیم تا به عضوی از این مجموعه برسیم. تحلیل نحوی را از همینجا ادامه دهیم ممکن است بتوان از قاعدههای منتهی به ε هم استفاده کرد پایانه ای روی انباره اضافه کرده ایم باالی انباره باشد که با ورودی نخواند آن را از برمی داریم و در پیغامی می گوییم که آن پایانه را 28
)2( اصالح خطا: روش حالت ترس ایده ی کلی: خانه های خالی جدول تحلیل را تغییر دهیم اگر خانهی M[A,a] خالی و a عضو Fllw(A) بود M[A,a] را برابر sync )همگامسازی( قرار میدهیم بنابراین اگر A عنصر باالی انباره و a ورودی فعلی باشد: اگر A غیرپایانه و M[A,a] خالی بود a را از ورودی دور میاندازیم اگر A غیرپایانه و M[A,a] برابر sync بود A را از روی انباره برمیداریم اگر A پایانه ولی نامساوی a بود A را از روی انباره برمیداریم )در واقع به این معنی است که آن را در ورودی اضافه کردهایم( 29
)3( اصالح خطا: روش حالت ترس مثال جدول تحلیل تغییریافته: نشانهی ورودی غیرپایانه ها id + * ( ) $ E E T E E T E E E + T E E ε E ε T T F T T F T T T ε T * F T T ε T ε F F id F ( E ) همگامسازی.) sync ( بر اساس مجموعهی.Fllw غیرپایانهی باالی انباره را برمی داریم ورودی را دور می اندازیم 30
)4( اصالح خطا: روش حالت ترس مثال روند تغییریافته ی تحلیل نحوی: مالحظات ورودی انباره خطا : دور انداختن + $ id $ E + id * + $ E id * + id $ $ E T id * + id $ $ E T F id * + id $ $ E T id id * + id $ $ E T * + id $ $ E T F * * + id $ خطا : خانهی M[F,+]= sync $ E T F + id $ $ E T + id $ از روی انباره برداشته میشود F $ E + id $ $ E T + + id $ $ E T id $ $ E T F id $ $ E T id id $ $ E T $ $ E $ $ $ پیغام خطای نمونه:»+ به اشتباه واردشده است و دور انداخته میشود«پیغام خطای نمونه:»جمله )Term( پیدا نشد«31
نوشتن پیغام های خطا )1( شمارندهای برای ورودی در نظر میگیریم یادآوری: هر غیرپایانه معر ف یک ساخت انتزاعی زبان است مثالهایی از پیغامهای خطا برای گرامر ما: اگر E معر ف»عبارت«باشد: با فرض این که E روی انباره و + ورودی فعلی است:»خطا در محل i: عبارت نمیتواند با + آغاز شود«یا»خطا در محل i: عبارت نادرست است«به طور مشابه برای E روی انباره و * به عنوان ورودی فعلی اگر E معر ف»انتهای عبارت«باشد: با فرض این که E باالی انباره و ورودی فعلی * یا id است:»خطا: عبارتی که در محل j شروع شده است در محل i ظاهری نادرست دارد«نکته: هر بار E را از روی انباره برمیداریم محل فعلی را جایی ذخیره میکنیم 32
نوشتن پیغام های خطا )2( مثال هایی از پیغام خطا برای خانه ی sync فرض کنید F باالی انباره و + ورودی فعلی است:»خطا در محل i: بر خالف انتظار عملوند جمع یا ضرب پیدا نشد«فرض کنید E باالی انباره و ) ورودی فعلی است:»خطا در محل i: بر خالف انتظار عبارتی پیدا نشد«33
نوشتن پیغام های خطا )3( مثال هایی از حالتی که باالی انباره پایانه ای است که با ورودی نمی خوان د فرض کنید id باالی انباره و + ورودی فعلی است:»خطا در محل i: بر خالف انتظار شناسهای پیدا نشد«فرض کنید ) باالی انباره و ورودی فعلی پایانهای غیر از ) است: هر وقت به یک ( برخوردیم محل آن را در»انبارهی ویژه پرانتز باز«ذخیره می کنیم وقتی که حالت فوق اتفاق افتاد به انبارهی پرانتز باز نگاه میکنیم تا محل آن پرانتز باز را که بسته نشده است بیابیم»خطا در محل i: برای پرانتز بازی که در محل m واقع شده هیچ پرانتز بستهای پیدا نشد«)مثال در صورتی که ورودی $ ) id ( id * + ( id باشد( 34
تجمیع پیغام های خطا با جدول تحلیل با توجه به آن چه گفته شد خانه های خالی جدول تحلیل را می توانیم با روش مناسب صدور پیغام خطا پر کنیم 35
اصالح خطا: سطح عبارت )1( خانه های خالی جدول تحلیل را با روی ه های مدیریت خطا پر می کنیم. این روی ه ها نه تنها خطاها را گزارش می کنند بلکه: نمادهای روی انباره یا ورودی را تغییر می دهند یا درج / حذف می کنند پیغام خطای مناسب را صادر می کنند کاستی ها: هر گونه تغییر انباره باید با احتیاط انجام شود تا مطمئن شویم اشتقاقی که اصوال در زبان ممکن نیست توسط تحلیلگر نحوی انجام نمی شود باید مراقب حلقه های نامتناهی بود در واقع حالت ترس را گسترش می دهیم تا مدیریت خطا به نحو کامل تری انجام شود 36
اصالح خطا: سطح عبارت )2( چه طور پیاده سازی کنیم به هر قاعده در خانه های پر جدول تحلیل و همین طور به حالت sync و خانه های خالی شماره ای یکتا اختصاص می دهیم 37
اصالح خطا: سطح عبارت )3( نشانهی ورودی غیرپایانه ها id + * ( ) $ E 1 18 19 1 9 10 E 20 2 21 22 3 3 T 4 11 23 4 12 13 T 24 6 5 25 6 6 F 8 14 15 7 16 17 1 E T E 2 E + T E 3 E ε 4 T F T 5 T * F T 6 T ε 7 F ( E ) 8 F id 9 تا :17 همگامسازی ) sync ( 18 تا 25: مدیریت خطا 38
حل مشکالت گرامر همه ی ویژگی های یک زبان برنامه سازی را نمی توان با گرامرها )زبان ها( ی مستقل از متن توصیف کرد مثال : تعریف یک شناسه )مثال نام متغیر( پیش از استفاده از آن در ادامهی برنامه رعایت تجانس نوعها در عبارتها )مثال جمع عدد صحیح با عدد صحیح( تطابق پارامترها در زمان تعریف تابع با آرگومان ها در زمان فراخوانی آن این ویژگی ها و نظایر آن ها»حساس به متن«اند و دسته ی دیگری از زبان ها را معرفی می کنند: متن زبان های حساس به زبان های حساس به متن زبان های مستقل از متن زبان های منظم 39
زبان های حساس به متن مثال: تعریف شناسه پیش از استفاده L 1 = { w c w w (a b)* } )c n d m ( تطابق پارامترها ( m )a n b و آرگومان ها L 2 = {a n b m c n d m n 1, m 1 } 40
زبان های مستقل از متن )1( L 3 = { w c w R w (a b)* } مثال: L 4 = {a n b m c m d n n 1, m 1 } L 5 = {a n b n c m d m n 1, m 1 } L 6 = {a n b n n 1 } 41
زبان های مستقل از متن )2( مثال )نمایش به کمک L 3 S = { w c w R w (a b)* } a S a b S b c گرامر(: L 4 = {a n b m c m d n n 1, m 1 } S a S d a A d A b A c b c L 5 = {a n b n c m d m n 1, m 1 } S X Y X a X b a b Y c Y d c d L 6 = {a n b n n 1 } S a S b a b 42