0% found this document useful (0 votes)
171 views76 pages

Compiler

Uploaded by

ludwig
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
171 views76 pages

Compiler

Uploaded by

ludwig
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 76

‫اصول طراحی کامپایلر‬

‫دانشگاه آزاد اسالمی واحد بوشهر‬

‫رشته مهندسی کامپیوتر‪ -‬نرم افزار‬

‫تهیه کننده‪ :‬محمد اسفندیاری‬

‫‪1‬‬
‫شناسنامه منبع‬

‫عنوان منبع‪ :‬کامپايلرها‬


‫مترجم‪ :‬دلداري‬
‫انتشارات‪ :‬باغاني (خراسان)‬
‫منبع اصلي‪:‬‬
‫‪Compilers:‬‬
‫‪Principles, Techniques, and Tools‬‬

‫اصول طراحی کامپایلر‬ ‫‪2‬‬


‫تقسیم بندی نمرات‬
‫‪ 10‬نمره پروژه‬
‫‪ 7‬نمره پایان ترم‬
‫‪ 3‬نمره حضور‬

‫اصول طراحی کامپایلر‬ ‫‪3‬‬


‫جايگاه درس در رشته کامپيوتر‬
‫‪ ‬ضرورت اين درس‪:‬‬
‫◦ ضرورت نياز به زبانهای سطح باال‬
‫◦ ضرورت ترجمه برنامه های نوشته شده با زبان سطح باال به برنامه به‬
‫زبان ماشين‬
‫◦ تنوع زبانهای برنامه نويسی سطح باال‬
‫‪ ‬دروس پيش نياز‪ :‬نظريه زبانها و ماشين‪ ،‬طراحی و پياده سازی زبانها‬

‫اصول طراحی کامپایلر‬ ‫‪4‬‬


‫تعريف كامپايلر‬

‫‪ -1‬ترجمه برنامه از زبان مبدا به برنامه معادل دز زبان مياني‬


‫مانند اسمبلي‬

‫‪ -2‬گزارش وجود خطاهارا در برنامه مبدا به كاربر‪.‬‬

‫برنامه مبدأ‬ ‫کامپايلر‬ ‫برنامه مقصد‬

‫پيغام خطا‬

‫اصول طراحی کامپایلر‬ ‫‪5‬‬


‫مراحل کامپایل‬
)Lexical Analysis( ‫تحليل واژه اي‬ .1
) Syntax Analysis ( ‫تحليل نحوي‬ .2
) Semantic Analysis ( ‫تحليل معنايي‬ .3
) Intermediate Code Generation ( ‫توليد كد بينابيني‬ .4
) Code Optimization ( ‫بهينه سازي كد‬ .5

) Code Generation ( ‫توليد كد نهايي‬ .6

‫اصول طراحی کامپایلر‬ 6


‫ای‬
‫واژهای‬
‫تحليلواژه‬
‫تحليل‬

‫نحوي‬
‫تحليلنحوي‬
‫تحليل‬

‫معنايي‬
‫تحليلمعنايي‬
‫تحليل‬

‫خطا‬
‫كنندهخطا‬
‫ادارهكننده‬ ‫مياني‬ ‫نماد‬
‫جدولنماد‬
‫مديرجدول‬
‫مدير‬
‫اداره‬ ‫كدمياني‬
‫توليدكد‬
‫توليد‬

‫كد‬
‫سازكد‬
‫بهينهساز‬
‫بهينه‬

‫نهايي‬
‫كدنهايي‬
‫توليدكد‬
‫توليد‬

‫اصول طراحی کامپایلر‬ ‫‪7‬‬


‫تحلیل واژه ای‬
‫‪‬خواندن کارکتر به کارکتر‪ Y‬برنامه ورودی‬
‫‪‬تشخیص نشانه ها (‪)Token‬‬
‫◦ کلمات کلیدی(‪)Keywords‬‬
‫‪ ‬رزرو شده‬
‫‪ ‬روزرو نشده مانند ‪PL/1‬‬
‫عملگرها(‪)Operators‬‬ ‫◦‬
‫جداکننده ها(‪)Delimeters‬‬ ‫◦‬
‫ثابت ها(‪)literals‬‬ ‫◦‬
‫شناسه ها(‪)Identifiers‬‬ ‫◦‬

‫اصول طراحی کامپایلر‬ ‫‪8‬‬


‫تحلیل نحوی‬
‫‪‬بر‪Y‬رسی برنامه از نظر خطاهای نحوی‬

‫‪‬ایجاد درخت نحو با استفاده از‪ Y‬نشانه های تولید شده در‬
‫مرحله قبل‬

‫اصول طراحی کامپایلر‬ ‫‪9‬‬


‫تحلیل معنایی‬

‫بررسي برنامه مبدا براي يافتن خطاهاي معنايي‬

‫جمع آوري اطالعات مربوط به نوع داده ها‬

‫اصول طراحی کامپایلر‬ ‫‪10‬‬


‫تولید کد میانی‬

‫خواندن برنامه ورودي‬

‫تبديل به برنامه اي در زبان مياني مانند اسمبلي‬

‫برای انتخاب زبان میانی باـید موارد زیررا در نظر داشت‪:‬‬


‫• تولید کد زبان میانی ساده باشد‬
‫• بهینه سازی آن ساده باشد‬
‫• ترجمه آن به زبان مقصد بهراحتی انجام شود‬

‫اصول طراحی کامپایلر‬ ‫‪11‬‬


‫بهینه ساز کد‬

‫بهينه كردن كد مياني ( حذف متغيرهاي مياني غير ضروري)‬

‫سرعت بخشيدن به توليد كد نهايي‬

‫اصول طراحی کامپایلر‬ ‫‪12‬‬


‫تولید کد نهایی‬

‫تبديل كد مياني بهينه به كد جابجاپذير يا اسمبلي‬

‫تعيين مكانهاي حافظه براي متغيرهاي برنامه‬

‫انتساب متغيرها به ثبات هاي ماشين‬

‫اصول طراحی کامپایلر‬ ‫‪13‬‬


‫مدیر جدول نمادها‬
‫‪ ‬تعریف‬
‫ساختمان داده ای شامل رکورد برای شناسه و صفات آن مانند‪:‬‬
‫آدرس حافظه اختصاص داده شده به شناسه‬ ‫◦‬
‫نوع آن‬ ‫◦‬
‫محل تعریف ان‬ ‫◦‬
‫نام‬ ‫◦‬
‫تعداد ارگومان های رویه‬ ‫◦‬
‫‪...‬‬ ‫◦‬

‫‪ ‬هدف‬
‫فراهم کردن شناسایی سریع رکورد شناسه به منظور ذخیره و بازیابی‬
‫صفات آن‬

‫اصول طراحی کامپایلر‬ ‫‪14‬‬


‫اداره کننده خطا‬
‫‪‬هنگامی که در هر مرحله خطایی رخ دهد این بخش فراخوانی‬
‫میشود‬
‫‪‬می بایستی به گونه ای عمل کند تا در فرآیند کامپایل تعداد‬
‫خطاهای بیشتری را کشف کند(با اولین خطا کار کامپایل‬
‫متوقف نشود)‬
‫‪‬بیشتر در پارسر و اسکنر خطاها کشف می شود‪.‬‬

‫اصول طراحی کامپایلر‬ ‫‪15‬‬


Front-end and Back-end
Front-End
)Lexical Analysis( ‫تحليل واژه اي‬ ◦
) Syntax Analysis ( ‫تحليل نحوي‬ ◦
) Semantic Analysis ( ‫تحليل معنايي‬ ◦
) Intermediate Code Generation ( ‫يد كد بينابيني‬Y‫تول‬ ◦
‫بخشی از تولید کد میانی که به زبان مقصد وابسته است‬ ◦
Back-End 
) Code Optimization ( ‫◦ بهينه سازي كد‬
) Code Generation ( ‫◦ توليد كد نهايي‬

‫اصول طراحی کامپایلر‬ 16


‫مثال از مراحل کامپایل‬
‫تحليل گر لغوي‬ ‫وي‬
Area:= Pos + Rate * 50 ‫نح‬
‫گر‬
id1:= id2+ id3 * 50 ‫يل‬
‫حل‬
‫ت‬
tem1:=into
tem1:=intoreal
real50
50
tem2:=id3 * tem1 := :=
tem2:=id3 * tem1 ‫توليد كد مياني‬
tem3:=
tem3:=id2
id2++tem2
tem2
Id1:= tem3 + ‫تحليل معنايي‬ +
Id1:= tem3 id1 id1
‫بهينه ساز‬ id2 * *
id2
tem1:= ‫يي‬ Into real
tem1:=id3
id3**50.0
50.0 ‫ها‬ ‫دن‬ id3 id3
Id1:= id2 + tem1
Id1:= id2 + tem1 ‫دك‬ 50
‫ولي‬ 50
‫ت‬

Mov
Mov id,
id,R2
R2 Mov id2 , R1
Mul
Mul 50.0, ,R2
50.0 R2 Add R2, R1
Mov R1, id1
Mov R1, id1

‫اصول طراحی کامپایلر‬ 17


‫تحلیل واژه ای‬
‫‪‬نخستین مرحله کامپایل‬
‫‪‬نام واحدی از کامپایلر که وظیفه تحلیل واژه ای را بر عهده‬
‫دارد اسکنر است‬
‫‪‬میان رشته ورودی و تحلیل نحوی یا پارسر قرار دارد‬
‫‪‬وظیفه‪:‬‬
‫با خواندن کارکترها توکن ها را تشخیص دهد ‪ .‬برای پارسر‬
‫ارسال کند‪.‬‬

‫اصول طراحی کامپایلر‬ ‫‪18‬‬


‫رابطه اسکنر و پارسر‬

‫اصول طراحی کامپایلر‬ ‫‪19‬‬


‫مثال‬
‫‪A:=B+C‬‬
‫توکن های زیر شناسایی می شود‪:‬‬
‫<‪>id, Addr A‬‬ ‫‪.1‬‬
‫<‪>.ass. , Op‬‬ ‫‪.2‬‬
‫<‪>id, Addr B‬‬ ‫‪.3‬‬
‫<‪>.add , Op‬‬ ‫‪.4‬‬
‫<‪>id, Addr C‬‬ ‫‪.5‬‬

‫‪Lookahead‬‬ ‫به آخرین توکن شناسایی شده عالمت پیش بینی یا‬
‫‪ Symbol‬گفته می شود‪.‬‬

‫اصول طراحی کامپایلر‬ ‫‪20‬‬


‫الگو و واژه‬
‫‪‬الگو‪ :‬به فرم کلی که یک توکن می تواند داشته باشد‬
‫‪‬واژه‪ :‬دنباله ای از نویسه ها که تشکیل یک توکن می دهد‬

‫اصول طراحی کامپایلر‬ ‫‪21‬‬


‫چالش های اسکنر‬
‫‪‬جهت تشخیص توکن‪ ،‬اسکنر می بایستی چند کارکتر بعد را‬
‫بخواند مانند >=‬
‫‪‬در زبان هایی که فضای خالی نادیده گرفته می شود(به جز در‬
‫رشته های کارکتری) مانند فرترن‬
‫‪◦ Do 5 I=1.25‬‬
‫‪◦ Do 5 I=1,25‬‬
‫‪PL/1‬‬ ‫‪‬در زبان هایی که کلمات کلیدی رزرو شده نیستند مانند‬
‫;‪IF Then THEN Then=Else; ELSE Else=Then‬‬
‫تشخیص نهایی بر عهده پارسر می باشد‬

‫اصول طراحی کامپایلر‬ ‫‪22‬‬


‫خطاهای واژه ای‬
‫‪‬انواع خطاهای محدودی توسط اسکنر کشف می شود‬
‫))‪◦ Fi(x==f(x‬‬
‫‪‬اگر اسکنر توکن شناسایی شده را معتبر نداند اداره کننده خطا‬
‫را فراخوانی می کند‪.‬‬

‫اصول طراحی کامپایلر‬ ‫‪23‬‬


‫روش های تصحیح خطا در فاز تحلیل واژه ای‬
‫‪Panic Mode ‬‬
‫◦ حذف کارکتر از رشته ورودی تا شناسایی یک توکن معتبر‬
‫‪‬حذف یک کارکتر غیر مجاز(تبدیل =‪ :$‬به =‪):‬‬
‫‪‬وارد کردن یک کارکتر گم شده(تبدیل ‪ :‬به =‪):‬‬
‫‪‬تعویض کردن یک کارکتر غلط با یک کارکتر درست‬
‫(تبدیل ‪ ::‬به =‪):‬‬
‫‪‬جابه جا کردن دو کارکتر مجاز (تبدیل ‪ =:‬به =‪):‬‬

‫اصول طراحی کامپایلر‬ ‫‪24‬‬


‫دیاگرام انتقال‬
‫‪‬یک گراف جهت دار هر گره آن معرف یک وضعیت‪ ،‬یکی از‬
‫وضعی‪Y‬ت ه‪Y‬ا ب‪Y‬ه عنوان وضعی‪Y‬ت شروع‪ ،‬ی‪Y‬ک ی‪Y‬ا چن‪Y‬د ت‪Y‬ا از انه‪Y‬ا به‬
‫عنوان وضعی‪Y‬ت خاتمه‪ .‬برچس‪Y‬ب های‪Y‬ی بر روی لب‪Y‬ه ه‪Y‬ا قرار می‬
‫گیرن‪Y‬د ک‪Y‬ه شرط عبور از ی‪Y‬ک وضعی‪Y‬ت ب‪Y‬ه وضعی‪Y‬ت دیگر را‬
‫بیان می کنند‪.‬‬

‫‪‬هر دیاگرام انتقال معرف یک زبان و برای مشخص کردن‬


‫اینکه آیا یک رشته متعلق به زبان مورد نظر است یا خیر‬

‫‪‬مورد استفاده ‪ :‬جهت پیاده سازی یک اسکنر‬

‫اصول طراحی کامپایلر‬ ‫‪25‬‬


‫مثال‬
‫‪‬دیاگرام انتقال زیر با عبارت منظم زیر یکسان است‬
‫‪(a|b)* abb‬‬
‫و هر دو بیانگر رشته های متشکل شده از ‪ a‬و ‪ b‬که به ‪abb‬‬
‫ختم می شوند می باشد‬

‫اصول طراحی کامپایلر‬ ‫‪26‬‬


‫دیاگرام غیر قطعی‬
‫‪‬دیاگرامی که یکی از دو مشخصه زیر را داشته باشد غیر‬
‫قطعی است‪:‬‬
‫◦ لبه های خارج شده از بعضی از وضعیت های ان برچسب مشابه‬
‫داشته باشد‪.‬‬
‫◦ لبه هایی از ان دارای برچسب ‪ €‬باشد یعنیبدون توجه به ورودی می‬
‫توان تغییر وضعیت داد‪.‬‬
‫‪:‬دیاگرام اسالید قبل غیر قطعی است نمونه قطعی آن عبارتند از‬

‫اصول طراحی کامپایلر‬ ‫‪27‬‬


‫تحلیل نحوی(‪)Syntax Analysis‬‬
‫‪‬وظیفه‪:‬‬
‫بر‪Y‬رسی متعلق بودن یک جمله به یک گرامر‪Y‬‬
‫‪‬روش‪:‬‬
‫◦ روش های باال به پایین(‪)Top-Down‬‬
‫‪ ‬ایجاد درخت تجزیه از باال به پایین‬
‫◦ روش های پایین به باال(‪)Bottom-Up‬‬
‫‪ ‬ایجاد درخت تجزیه از پایین به باال‬
‫در هر روش جهت حرکت از چپ به راست و در هر مرحله‬
‫‪.‬تنها یک توکن بررسی می شود‬

‫اصول طراحی کامپایلر‬ ‫‪28‬‬


‫مثال‬
1,2: E E+T|T
3,4: T T*F|F
5,6: F(E)|id
Stmt: id+id

‫اصول طراحی کامپایلر‬ 29


‫روش های باال به پایین‬
‫‪‬روش پایینگرد(‪)Recursive Descent‬‬
‫‪‬روش )‪LL(1‬‬
‫◦ اولین ‪ L‬حرکت از سمت چپ‬
‫◦ دومین ‪ L‬یعنی چپ ترین بسط (‪)Left Most Derivation‬‬
‫◦ عدد ‪ 1‬یعنی در هر قدم از تجزیه فقط یک توکن‬

‫اصول طراحی کامپایلر‬ ‫‪30‬‬


‫روش های پایین به باال‬
‫‪‬روش تقدم عملگر(‪)operator Precedence‬‬
‫‪‬روش تقدم ساده(‪)Simple precedence‬‬
‫‪‬روش )‪LR(1‬‬
‫◦ )‪SLR(1‬‬
‫◦ )‪LALR(1‬‬
‫◦ )‪CLR(1‬‬

‫اصول طراحی کامپایلر‬ ‫‪31‬‬


‫عمل پیجویی(‪)Back Tracking‬‬
‫‪S cAd‬‬
‫‪A ab|a‬‬
‫‪Stmt: cad‬‬

‫‪ .1‬بهتر است پارسرها به گونه ای پیاده سازی شوند که نیازی به پیجویی نداشته باشند‬
‫‪ .2‬پارسرهایی که عملیات عقبگردرا انجام نمی دهند پارسرهای پیشگو می گویند‪.‬‬
‫‪ .3‬روش کار پارسرها به صورت حریصانه می باشد یعنی با دریافت هر توکن تا جایی که ممکن است‬
‫رخترا بسط می دهند و هنگامی که ممکن نشد توکن بعدیرا درخواست می کنند‪.‬‬

‫اصول طراحی کامپایلر‬ ‫‪32‬‬


‫مثال از مراحل ایجاد درخت در روش باال به پایین‬
‫‪Type → Simple‬‬
‫‪| ↑ id‬‬
‫‪| array [ Simple ] of Type‬‬
‫‪Simple → integer‬‬
‫‪| char‬‬
‫‪| num dot dot num‬‬

‫در گره ‪ n‬با غیر پایانه ‪ A‬یکی از قواعد گرامر که ‪ A‬در سمت چپ آن قرار دارد را‬ ‫‪.1‬‬
‫انتخاب کرده و سمت راست این قاعده را به عنوان فرزندا‪Y‬ن گره ‪ n‬در درخت پارس‬
‫قرار میدهیم‪.‬‬
‫گره بعدی را که از آنجا یک زیر درخت دیگر باید ایجاد شود را پیدا می کنیم‬ ‫‪.2‬‬

‫اصول طراحی کامپایلر‬ ‫‪33‬‬


‫ادامه مثال‬
Stmt: array [ num dot dot num ] of integer

‫اصول طراحی کامپایلر‬ 34


‫تجزیه پایینگرد‬
‫‪‬پیشگو‬
‫‪‬باال به پایین‬
‫‪‬مجموعه ای از رویه ها رشته ورودی را مورد‬
‫پردازش انجام میدهند که وظایف زیر را دارند‪:‬‬
‫◦ تصمیم گیری در مورد انتخاب قاعده گرامر‬
‫◦ استفاده از قاعده انتخاب شده‬
‫‪‬هر رویه به ازای هر غیر پایانه‬
‫‪‬رویه ای به نام ‪ match‬جهت تطبیق توکن های‬
‫ورودی و پایانه های درخت تجزیه‬
‫اصول طراحی کامپایلر‬ ‫‪35‬‬
‫مثال از تجزیه پایینگرد‬
Procedure match ( t : token );
begin
if Lookahead = t Then
Lookahead := nexttoken
else Error
end;
Procedure Simple ;
begin
if Lookahead = integer Then match ( integer )
else if Lookahead = char Then match ( char )
else if Lookahead = num Then begin
match ( num ) ; match ( dot dot ) ; match ( num )
end
else Error
end ;

‫اصول طراحی کامپایلر‬ 36


‫ادامه مثال‬
Procedure Type ;
begin
if Lookahead is in {integer,char,num} Then Simple
else if Lookahead = array then begin
match ( array ) ;
match ( ' [ ' ) ;
Simple ;
match ( ' ] ' ) ;
match (of) ;
Type
end
else if Lookahead = ' ↑ ' Then Begin
match ( ' ↑ ' ) ;
match( ' id ' )
end
else Error
end ;

‫اصول طراحی کامپایلر‬ 37


‫تابع ‪First‬‬
‫‪‬جهت انتخاب قاعده در پارسر‪Y‬های پیشگو‬
‫‪‬تعریف)‪:First(α‬‬
‫مجموعه ای از پایانه ها که در سمت چپ ترین قسمت از‬
‫‪.‬قرار میگیرد ‪ α‬رشته تولید شده از رشته‬
‫} *)‪First(α) = {a | α ═› aβ , a Є T , β Є (N U T‬‬

‫اصول طراحی کامپایلر‬ ‫‪38‬‬


‫مثال‬
G1:
S → cAd
A → ab | a

First(cAd) = {c}
First(S) = {c}
First(A) = {a}

‫اصول طراحی کامپایلر‬ 39


‫مثال‬
Type Y‫امر‬Y‫برای گر‬
First(Simple) = {integer,char,num}
First(↑ id) = {↑}
First(array[Simple] of Type) = {array}
First(Type) = {↑,array,integer,char,num}

‫اصول طراحی کامپایلر‬ 40


‫نکته‬
‫‪‬در‪Y‬صورتی پارسر‪Y‬های پیشگو در‪Y‬ست عمل می کنند که‬
‫شرط زیر‪ Y‬برقرار باشد‪:‬‬
‫اگر‪:‬‬
‫‪A→α‬‬
‫‪A→β‬‬
‫‪:‬آنگاه‬
‫‪First(α) ∩ First(β) = ф‬‬

‫اصول طراحی کامپایلر‬ ‫‪41‬‬


‫قاعده اپسیلون(‪)A → ε‬‬
‫هر‪Y‬گاه در گرامر قاعده اپسیلون وجود داشت پارسر‪Y‬‬
‫پایینگر‪Y‬د از ان به عنوان قاعده پیش فرض استفاده می‬
‫کند‪.‬‬
‫‪ST → begin STS end‬‬
‫‪STS → STL| ε‬‬
‫‪STL → a‬‬
‫‪stmt: begin end‬‬

‫چون ‪ end‬جز )‪ First(STS‬نیست از قاعده ‪ STS → ε‬استفاده می شود‬

‫اصول طراحی کامپایلر‬ ‫‪42‬‬


‫مشکل چپ گردی(‪)Left Recursion‬‬
‫‪‬گرامر چپ گرد‪:‬‬
‫اگر غیرپایانه سمت چپ یک قاعده به عنوان اولین عالمت‬
‫‪:‬سمت راست آن قاعده ظاهر شود به عبارت دیگر‬

‫‪A → Aα‬‬
‫ر‪Y‬وش های پارس باال به پایین ر‪Y‬ا نمی توان بر‪Y‬ای‬
‫گرامرهای چپ گرد استفاده کرد‪.‬‬
‫دلیل؟(تمرین)‬

‫اصول طراحی کامپایلر‬ ‫‪43‬‬


‫انواع چپ گردی‬
‫‪‬چپ گردی آشکارا (‪Immediate Left‬‬
‫‪)Recursion‬‬
‫‪A → Aα | β‬‬
‫‪‬چپ گردی ضمنی(‪)Implicit Left Recursion‬‬
‫‪S → Aa | b‬‬
‫‪A → Ac | Sd‬‬
‫در ‪ S‬ضمنی و در ‪ A‬آشکارا دلیل‪:‬‬
‫‪S ═› Aa ═› Sda‬‬

‫اصول طراحی کامپایلر‬ ‫‪44‬‬


‫حذف چپ گردی آشکارا‬
‫گرامر زیر ر‪Y‬ا در نظر بگیرید‪:‬‬
‫‪A → Aα1 | Aα2 | … | Aαm | β1 | β2 | … | βn‬‬
‫در قواعد فوق فرض بر این است که‪:‬‬
‫‪ .1‬هیچ ‪ βi‬نباید با ‪ A‬شروع شود‬
‫‪ .2‬هیچ ‪αi‬نباید ‪ ε‬باشد‬

‫گرامر حاصل‪:‬‬
‫'‪A → β1A' | β2A' | … | βnA‬‬
‫‪A' → α1A' | α2A' | … | αmA' | ε‬‬

‫اصول طراحی کامپایلر‬ ‫‪45‬‬


‫حذف چپ گردی ضمنی‬
‫برای این کار الگوریتم ورودی می بایستی شرایط زیر را دارا‬
‫باشند‪:‬‬
‫‪ .1‬هیچ قاعده ‪ ε‬نداشته باشد‬
‫‪ .2‬دور وجود نداشته باشد یعنی‪:‬‬
‫‪For i := 1 to n do begin‬‬
‫‪For j := 1 to i-1 do begin‬‬
‫بجاي هر ‪ Ai → Ajγ‬قواعد ‪ Ai → δ1γ | δ2γ | … | δkγ‬را قرار دهيد كه‬
‫در آن ‪ Aj → δ1 | δ2 | … | δk‬قواعد فعلي ‪ Aj‬هستند‬
‫‪end‬‬
‫حال چپ گردي آشكار قواعد ‪ Ai‬را حذف كنيد‬
‫‪end‬‬

‫اصول طراحی کامپایلر‬ ‫‪46‬‬


‫مثال‬
‫‪S → Aa | b‬‬
‫‪A → Ac | Sd‬‬
‫از روی قاعده ‪ A → Sd‬داریم‬
‫‪A → Aad | bd‬‬
‫حال چپ گرد اشکارای ‪ A‬را حذف می کنیم‬
‫'‪A → bdA‬‬
‫‪A' → cA' | adA' | ε‬‬
‫گرامر نتیجه به صورت زیر خواهد بود‬
‫‪S → Aa | b‬‬
‫'‪A → bdA‬‬
‫‪A' → cA' | adA' | ε‬‬
‫اصول طراحی کامپایلر‬ ‫‪47‬‬
‫فاکتورگیری از چپ(‪)Left Factoring‬‬
‫‪ ‬مورد استف‪Y‬اده جهت پیاده سازی پارسرهای پیشگو‬
‫‪ ‬زمانی که دو قاعده داشته باشیم که به صورت زیر باشند‪:‬‬
‫‪A → αβ1‬‬
‫‪A → αβ2‬‬
‫پس از ف‪Y‬اکتورگیری‪ Y‬قواعد جدید به صورت زیر خواهند شد‪:‬‬
‫'‪A → αA‬‬
‫‪A' → β1 | β2‬‬
‫روش کلی‪:‬‬
‫‪A → αβ1 | αβ2 | … | αβm | δ1 | δ2 | … | δn‬‬
‫پس از فاکتورگیری‪:Y‬‬
‫‪A → αA' | δ1 | δ2 | … | δn‬‬
‫‪A' → β1 | β2 | … | βm‬‬

‫اصول طراحی کامپایلر‬ ‫‪48‬‬


‫مثال‬
‫‪S→iEtS‬‬
‫‪S→iEtSeS|a‬‬
‫‪E→b‬‬

‫پس از فاکتورگیری‪:‬‬

‫‪S → i E t S S' | a‬‬


‫‪S' → e S | ε‬‬
‫‪E→b‬‬

‫اصول طراحی کامپایلر‬ ‫‪49‬‬


‫تجزیه پیشگویانه غیر بازگشتی‬
‫‪‬در این روش از‪ Y‬موارد زیر جهت پارس استفاده می‬
‫شود‪:‬‬
‫◦ انباره (‪)Parse Stack‬‬
‫◦ جدول تجزیه (‪)Parsing Table‬‬
‫◦ بافر ورودی که در انتهای آن عالمت ‪ $‬افزوده شده باشد‬

‫اصول طراحی کامپایلر‬ ‫‪50‬‬


‫ساختار جدول پارس‬
‫این جدول یک ارایه دوبعدی به صور‪Y‬ت ]‪ M[A,a‬می‬
‫باشد که در آن ‪ A‬یک غیر پایانه و ‪ a‬یک پایانه و‬
‫عالمت ‪ $‬می باشد و مقدار‪ Y‬بعضی از خانه ها شمار‪Y‬ه‬
‫یک قاعده می باشد‪.‬‬

‫اصول طراحی کامپایلر‬ ‫‪51‬‬


‫نحوه عملکرد‬
‫اگر ‪ $=X=a‬باشد پارسر پایان موفقیت آمیز را اعالم می کند‬ ‫‪.1‬‬
‫اگ‪Y‬ر ‪ $><X=a‬باش‪Y‬د پارس‪Y‬ر ‪ X‬را از انباره حذف و توکن بعدی‬ ‫‪.2‬‬
‫را م‪Y‬ی خواند‪ .‬اگ‪Y‬ر ‪ X‬پایان‪Y‬ه باشدو ب‪Y‬ا ‪ a‬مطابق‪Y‬ت نکن‪Y‬د یک‬
‫خطای نحوی رخ داده است‪.‬‬
‫اگ‪Y‬ر ‪ X‬ی‪Y‬ک غی‪Y‬ر پایان‪Y‬ه باش‪Y‬د ب‪Y‬ه خان‪Y‬ه ]‪ M[X,a‬مراجع‪Y‬ه م‪Y‬ی کند‬ ‫‪.3‬‬
‫ک‪Y‬ه در آ‪Y‬ن ی‪Y‬ا شماره ی‪Y‬ک قاعده ب‪Y‬ا فرمت ‪ AABC‬قرار داردو‬
‫ی‪Y‬ا خالی‪ .‬در ص‪Y‬ورت اول پارس‪Y‬ر ‪ X‬را از انباره حذف و به‬
‫جای آ‪Y‬ن ‪ ABC‬را ب‪Y‬ه گون‪Y‬ه ای ب‪Y‬ه انباره اضاف‪Y‬ه م‪Y‬ی کن‪Y‬د که ‪A‬‬
‫در باال باش‪Y‬د و در ص‪Y‬ورتی ک‪Y‬ه خال‪Y‬ی باش‪Y‬د یک خطای نحوی‬
‫رخ داده است‪.‬‬

‫اصول طراحی کامپایلر‬ ‫‪52‬‬


‫پیشنیازها جهت پر کردن جدول پارس‬
‫‪‬تابع ‪First‬‬
‫سمت چپ ترین عالمت رشته های بدست آمده از آن‬
‫عالمت‬
‫‪‬تابع ‪Follow‬‬
‫اولین چیزی که بعد از ان عالمت می آید‬

‫اصول طراحی کامپایلر‬ ‫‪53‬‬


‫الگوریتم بدست آوردن ‪First‬‬
‫}‪First(X)={X‬‬ ‫اگر ‪ X‬یک پایانه باشد در آنصورت‬ ‫‪.1‬‬

‫)‪First(X‬‬ ‫اگر قاعده ای بصورت ‪ Xε‬در گرامر باشد ‪ ε‬را به‬ ‫‪.2‬‬
‫اضافه می کنیم‪.‬‬

‫اگر قاعده ای به فرم ‪ X → y1y2 … yk‬در گرامر موجود باشد‬ ‫‪.3‬‬


‫ابتدا ‪ First(y1) – ε‬را به )‪ First(X‬اضافه می کنیم‪ .‬در صورتی‬
‫که بتوان با اشتقاق ‪ y1‬به ‪ ε‬رسید آنگاه ‪ First(y2) – ε‬را به‬
‫)‪ First(X‬می افزاییم و این عمل را تا آخر تکرار می کنیم‪.‬‬

‫اصول طراحی کامپایلر‬ ‫‪54‬‬


‫مثال‬
A → aB
B → Cb | d
C→ε|c

First(A) = {a}
First(B) = { c,b,d }
First(C) = {ε , c }

‫اصول طراحی کامپایلر‬ 55


‫الگوریتم بدست اوردن ‪Follow‬‬
‫‪ $‬را در )‪ Follow(S‬قرارمی دهیم (‪ S‬عالمت شروع گرامر)‬ ‫‪.1‬‬

‫اگر قاعده ای بصورت ‪ X → αAβ‬داشته باشیم هرچه در‬ ‫‪.2‬‬


‫)‪ First(β‬به جز ‪ ε‬را به )‪ Follow(A‬اضافه می کنیم‪.‬‬

‫‪X → αAβ‬‬ ‫اگر قاعده ای بفرم ‪ X → αA‬داشته باشیم و یا اینکه‬ ‫‪.3‬‬


‫به نحوی که با اشتقاق ‪ β‬به ‪ ε‬برسیم هر چه در )‪Follow(X‬‬
‫قرار دارد را به )‪ Follow(A‬اضافه می کنیم‪.‬‬

‫اصول طراحی کامپایلر‬ ‫‪56‬‬


‫مثال‬
1 E → T E‘
2 – 3 E' → + T E' | ε
4 T → F T'
5 – 6 T' → * F T' | ε
7 – 8 F → ( E ) | id

Follow ‫مجموعه های‬ First ‫مجموعه های‬


Follow(E) = { ) , $ } First(E) = { ( , id }
Follow(T) = { + , ) , $ } First(T) = { ( , id }
Follow(F) = { * , + , $ , ) } First(F) = { ( , id }
Follow(E') = { ) , $ } First(E') = { ε , + }
Follow(T') = { + , ) , $ } First(T') = { ε , * }

‫اصول طراحی کامپایلر‬ 57


‫الگوریتم تشکیل جدول پارس‬
‫برای هر قاعده به صورت ‪ A → α‬در گرامر قدم های ‪2‬و ‪3‬‬ ‫‪.1‬‬
‫را انجام دهید‪.‬‬
‫برای هر پایانه ‪ a‬در )‪ ،First(α‬شماره قاعده ‪ A → α‬را به‬ ‫‪.2‬‬
‫خانه ]‪ M[A,a‬اضافه می کنیم‪.‬‬
‫اگر ‪ ε‬در )‪ First(α‬وجود داشت شماره قاعده ‪ A → α‬را به‬ ‫‪.3‬‬
‫خانه های ]‪ M[A,b‬برای هر ‪ b‬جز )‪ Follow(A‬قرار‬
‫میدهیم‪.‬‬

‫اصول طراحی کامپایلر‬ ‫‪58‬‬


‫مثال‬
‫جدول پارس گرامر‪ Y‬قبل به صورت زیر است‪:‬‬

‫‪Id‬‬ ‫‪+‬‬ ‫*‬ ‫(‬ ‫)‬ ‫‪$‬‬


‫‪E‬‬ ‫‪1‬‬ ‫‪1‬‬
‫‪’E‬‬ ‫‪2‬‬ ‫‪3‬‬ ‫‪3‬‬
‫‪T‬‬ ‫‪4‬‬ ‫‪4‬‬
‫‪’T‬‬ ‫‪6‬‬ ‫‪5‬‬ ‫‪6‬‬ ‫‪6‬‬
‫‪F‬‬ ‫‪8‬‬ ‫‪7‬‬

‫اصول طراحی کامپایلر‬ ‫‪59‬‬


‫مثال از نحوه پارس کردن ‪id+id*id‬‬

‫اصول طراحی کامپایلر‬ ‫‪60‬‬


‫گرامرهای )‪LL(1‬‬
‫اگر در‪ Y‬جدول پارس در یک خانه بیش از یک شمار‪Y‬ه‬
‫قرار گرفت آن گرامر )‪ LL(1‬نمی باشد‪.‬‬
‫برای مثال‪:‬‬
‫‪1 – 2 S → i E t S S' | a‬‬
‫‪3 – 4 S' → e S | ε‬‬
‫‪5E→b‬‬

‫اصول طراحی کامپایلر‬ ‫‪61‬‬


‫الگوریتم بررسی کردن )‪ LL(1‬بودن‬
‫گرامر‬
‫‪A → α | β:‬‬ ‫اگر قاعده ای داشته باشیم به صور‪Y‬ت‬
‫‪First(β) ∩ First(α) = ф‬‬ ‫‪.1‬‬

‫حداکثر یکی از ر‪Y‬شته های ‪ α‬و ‪ β‬رشته ‪ ε‬را تولید‬ ‫‪.2‬‬


‫کند‪.‬‬
‫اگر ‪ >=ε α‬در آن صورت ‪First(β) ∩ Follow(A) = ф‬‬ ‫‪.3‬‬

‫اصول طراحی کامپایلر‬ ‫‪62‬‬


1 ‫مثال‬
1 E → T E'
2 – 3 E' → + T E' | ε
4 T → F T'
5 – 6 T' → * F T' | ε
7 – 8 F → ( E ) | id
 First(+TE') = { + } , First(ε) = { ε } , { ε } ∩ { + } = ф
 First(+TE') = { + } , Follow(E') = { $,) } , { + } ∩ { $,) } = ф

 First(*FT') = { * } , First(ε) = { ε } , { ε } ∩ { * } = ф
 First(*FT') = { * } , Follow(T') = { $,),+ } , { * } ∩ { $,),+ } = ф

 First((E)) = { ( } , First(id) = { id } , { ( } ∩ { id } = ф

‫اصول طراحی کامپایلر‬ 63


‫مثال ‪2‬‬
‫‪S → i e t S S' | a‬‬
‫‪S' → e S | ε‬‬
‫‪E→b‬‬

‫‪First(eS) = { e } , Follow(S') = { e,$ } , { e,$ } ∩ { e } ≠ ф‬‬

‫گرامر هایی که چپ گردی داشته باشند )‪ LL(1‬نمی باشد‪.‬‬

‫اصول طراحی کامپایلر‬ ‫‪64‬‬


‫)‪LL(1‬‬ ‫روش های اصالح خطای نحوی در‬
‫در )‪ LL(1‬در یکی از دو صور‪Y‬ت زیر خطا ر‪Y‬خ می‬
‫دهد‪:‬‬
‫‪ .1‬خانه ]‪M[A,a‬خالی باشد‬
‫‪ .2‬توکن رشته ور‪Y‬ودی با باالی پشته هم خوانی نداشته‬
‫باشد‪.‬‬

‫روش حل مسئله‪:‬‬
‫ر‪Y‬وش ‪Panic Mode‬‬

‫اصول طراحی کامپایلر‬ ‫‪65‬‬


‫روش ساخت جدول در روش اصالح خطای‬
‫‪ Panic Mode‬در تحلیل نحوی )‪LL(1‬‬

‫‪‬ایجاد مجموعه ای به نام ‪Synchronizing‬‬


‫◦ نحوه انتخاب می بایستی به صورتی باشد تا تداد توکن های‬
‫کمتری از رشته ورودی حذف شود‬
‫‪ ‬استفاده از توابع ‪ First‬و ‪Follow‬‬
‫‪‬قرار دادن حرف ‪ S‬در جدول پارس برای هر عنصر‪Y‬‬
‫از مجموعه ‪Synchronizing‬‬

‫اصول طراحی کامپایلر‬ ‫‪66‬‬


‫روش پارس کردن رشته ورودی با استفاده از ‪Panic‬‬
‫‪ Mode‬در )‪LL(1‬‬
‫اگر پارسر خانه ]‪ M[A,a‬را خالی ببیند عالمت ‪a‬‬ ‫‪.1‬‬
‫را در ور‪Y‬ودی نادیده می گیرد‪.‬‬
‫اگر در محل خانه ]‪ M[A,a‬حرف ‪ S‬ببیند غیر پایانه‬ ‫‪.2‬‬
‫باالی پشته حذف می کند‬
‫مشروط بر اینکه تنها غیر پایانه موجود در پشته نباشد‬ ‫◦‬
‫اگر پایانه باالی انبار‪Y‬ه با ورودی جاری تطبیق نکند‬ ‫‪.3‬‬
‫پایانه باالی انباره حذف‪ Y‬می شود‪.‬‬

‫اصول طراحی کامپایلر‬ ‫‪67‬‬


‫مثال‬
1 E → T E'
2 – 3 E' → + T E' | ε
4 T → F T‘
5 – 6 T' → * F T' | ε
7 – 8 F → ( E ) | id
‫ تشکیل داده است‬Follow ‫ را مجموعه‬Synchronizing ‫مجموعه‬

Id + * ( ) $
E 1 1 S S
E` 2 3 3
T 4 S 4 S S
T` 6 5 6 6
F 8 S S 7 S S

‫اصول طراحی کامپایلر‬ 68


‫تجزیه پایین به باال‬
‫‪‬یکی از ر‪Y‬وش های معر‪Y‬وف این تجزیه ر‪Y‬وش انتقال‪-‬‬
‫کاهش می باشد‪.‬‬
‫◦ عکس روش باال به پایین است‪ .‬یعنی درخت تجزیه از برگ‬
‫ها آغاز می شود‪.‬‬
‫‪1 S → aABe‬‬
‫‪2 – 3 A → Abc | b‬‬
‫‪4B→d‬‬

‫اصول طراحی کامپایلر‬ ‫‪69‬‬


‫چالش های موجود در پارسر های پایین به باال‬
‫‪ .1‬کدام زیر رشته به عنوان دستگیره در نظر گرفته شود‬
‫‪ .2‬کدام قاعده جهت عملیات کاهش انتخاب شود‬
‫تعاریف مهم‪:‬‬
‫‪‬عبارت (‪:)Phrase‬‬
‫◦ زیر جمله است که توسط یک غیر پایانه تولید شده باشد‬
‫‪‬عبارت ساده (‪:)Simple Phrase‬‬
‫◦ عبارتی است که تنها با یک قدم به وجود بیابد‬
‫‪‬دستگیره (‪:)Handle‬‬
‫◦ عبارت ساده ای است که در جهت عکس یک بسط راست تولید شده‬
‫باشد‪(.‬سمت راست دستگیره هیچ غیر ترمینالی وجود ندارد)‬
‫اصول طراحی کامپایلر‬ ‫‪70‬‬
‫مثال از گرامر گنگ‬
‫‪1 – 4 E → E + E | E * E | ( E ) | id‬‬
‫‪Stmt: id + id * id‬‬
‫برای پارس گرامرهای گنگ چند مسیر موجود است‬

‫اصول طراحی کامپایلر‬ ‫‪71‬‬


‫الگوریتم تجزیه انتقال‪ -‬کاهش با استفاده از انباره‬
‫به انتهای جمله ورودی و انباره عالمت ‪ $‬می شود‬ ‫‪.1‬‬
‫آنقدر عملیات انتقال و کاهش را تکرار می کنیم تا به خطا بر بخوریم و یا‬ ‫‪.2‬‬
‫تنها المان موجود در انباره ‪ $‬باشد و به پایان جمله ورودی رسیده باشیم‬

‫‪ .1‬عملیات انتقال(‪:)Shift‬‬
‫عالئم ورودی را به انباره اضافه میکنیم‪ .‬تا زمانی که دستگیره در باالی انباره‬
‫تشخیص داده شود‬
‫‪ .2‬عملیات کاهش(‪:)Reduce‬‬
‫دستگیره در باالی انباره را حذف و به جای آن غیر پایانه سمت چپ قاعده مربوطه‬
‫را قرار می دهیم‬
‫‪ .3‬قبول ورودی(‪)Accept‬‬
‫‪ .4‬تشخیص خطا(‪)Error‬‬

‫اصول طراحی کامپایلر‬ ‫‪72‬‬


‫مثال‬
‫‪1 – 4 E → E + E | E * E | ( E ) | id‬‬
‫‪Stmt: id + id * id‬‬

‫اصول طراحی کامپایلر‬ ‫‪73‬‬


‫انواع تداخل در تجزیه انتقال‪ -‬کاهش‬
‫‪‬تداخل انتقال‪ -‬کاهش(‪:)Shift/Reduce Conflict‬‬
‫پارسر هم بتواند عمل انتقال را انجام دهد و هم کاهش‬
‫‪‬تداخل کاهش‪ -‬کاهش (‪)Reduce/Reduce Conflict‬‬
‫بیش از یک قاعده جهت کاهش وجود داشته باشد‬

‫اصول طراحی کامپایلر‬ ‫‪74‬‬


‫مثال از تداخل انتقال‪-‬کاهش‬
‫‪Stmt → if expr then Stmt‬‬
‫‪| if expr then Stmt else Stmt‬‬
‫‪| other‬‬
‫فرض کنی‪Y‬د ب‪Y‬ه توک‪Y‬ن ‪ else‬رس‪Y‬یده ای‪Y‬م حال تجزی‪Y‬ه گ‪Y‬ر ب‪Y‬ا توج‪Y‬ه به‬
‫اینکه در انباره عبارت ‪ if expr then Stmt‬وجود دارد م‪Y‬ی توان‪Y‬د عمل‬
‫کاه‪Y‬ش را انجام دهد‪ .‬همچنی‪Y‬ن م‪Y‬ی توان‪Y‬د انتقال را انجام داده و بعد‬
‫از کامل شدن از قاعده دوم عمل کاهش را انجام دهد‬

‫اصول طراحی کامپایلر‬ ‫‪75‬‬


‫مثال از تداخل کاهش‪-‬کاهش‬
‫‪1 – 2 Stmt → id ( Parameter-list ) | Expr := Expr‬‬
‫‪3 – 4 Parameter-list → Parameter-list , Parameter‬‬
‫‪| Parameter‬‬
‫‪5 Parameter → id‬‬
‫‪6 – 7 Expr → id ( Expr-list ) | id‬‬
‫‪8 – 9 Expr-list → Expr-list , Expr | Expr‬‬
‫قاعده شماره ‪ 1‬برای فراخوانی متد و قاعده شماره ‪ 6‬برای مراجعه به آرایه است‪.‬‬
‫رشته ورودی )‪ A(i,j‬را در نظر بگیرید‪ .‬اسکنر آن را )‪ id(id,id‬می بیند‪.‬‬
‫حال فرض کنید عبارت ‪ id(id‬در باالی انباره است‪ .‬در این خالت می توان از دو‬
‫قاعده ‪ 5‬و ‪ 7‬جهت کاهش انجام داد‪.‬‬
‫در اینجا می بایستی به نوع ‪ A‬مراجعه کرد که آیا رویه است یا آرایه و قاعده‬
‫درست را انتخاب کرد‪.‬‬

‫اصول طراحی کامپایلر‬ ‫‪76‬‬

You might also like