Y@SiN
09-29-2009, 01:12 PM
ساختار کامپایلر
http://pnu-club.com/imported/2009/09/4739.jpg
اکنون شرح مختصری از هر پیمانه را ارائه خواهیم کرد:
پیمانه ورودی متن برنامه ، فایل متن برنامه را مییابد، آن را میخواند، و آن را به صورت جریانی از کاراکترها تحویل میدهد . ممکن است به فایلیهای دیگری که به یان فایل ضمیمه شدهاند . سربزند . این عمل ممکن است نیاز به همکاری سیسم عامل و تحلیل گر لغوی داشته باشد.
پیمانه تحلیل لغوی نشانههای موجودی در جریان ورودی را جدا میکند ورده و نمایش آنها را تعیین مینماید. این پیمانه را میتوان به صور دستی نوشت یا از توصیف نشانهها تولید نمود. علاوهبراین , ممکن است تفسیرهای محدودی را بر روی بعضی از نشانهها انجام دهد :به عنوان مثال، تعیین کند که آیا شناسهای یک ماکرو است یا یک واژه کلیدی.
پیمانه تحلیل نحوی جریانی از نشانهها را به درخت نحوی انتزاعی (AST) تبدیل میکند. بعضی از تحلیلگران نحوی حاوی دو پیمانهاند: پیمانه اول جریانی از نشانهها را میخواند وبرای هر ساختار نحوی که تشخیص داده میشود, تابعی را از پیمانه دوم فراخوانی میکند. توابع موجود در پیمانه دوم , گرههای AST را ایجاد کرده به هم پیوند میدهند. امتیاز این کار این است که میتوان با جایگزینی پیمانه تولید AST از یک تحلیل گر نحوی, AST دیگری را ایجادکرد , و از طرف دیگر , میتوان با جایگزیننی تحلیل گر نحوی, همان نوع AST را زا زبان دیگر به دست آورد.
پیمانه اداره کننده متن , اطلاعات مربوط به متنها را از نقاط مختلف برنامه جمع آوری میکند و گرهها را بر اساس این اطلاعات , حاشیه نویسی میکند. نمونههایی از این اطلاعات عبارتند از: اطلاعات نوع نشای از اعلان عبارات, اتصال دستوارت go to به برچسبهای آنها درزبانهای دستوری و در زبانهای توزیعی , تصمیم گیری در مورد این که کدام فراخوانی روالها ,محلی و کدامها از راه دور هستند. سپس این حاشیه نویسیها برای وارسی متن به کار میروند یا به پیمانههای دیگری ارسال میشوند (مثلا برای تولید کد)
پیمانه تولید کد میانی , ساختار های زبان را که در AST وجود دارند , به ساختارهای کلی تری تبدیل میکند این ساختارهای کلی , کد میانی را تولید میکنند که به طور خلاصه آن را IC مینامیم . طراح کامبایلر تصمیم میگیرد کد کدام ساختار , خاص زبان و کدام ساختار کلی است , اما معمولا این انتخاب چندان دشوار نیست . یک معیار برای سطح کد میانی این است که , تولید کد ماشین برای هر نوع ماشینی آسان باشد معمولا کد میانی متشکل از انحصار متقابل عبارات و دستور کنترل جریان است .
نمونههایی از ترجمههایی که توسط پیمانه تولید کد میانی انجام شده اند , عبارتند از : جایگزینی دستور while باشرطها ,برچشبها و پرشها در زبانهای دستوری در زبانهایی با انقیاد پویا کدی را درج میکند تا مشخص نماید که چه متدی از یک شیء باید فراخوانی شود, قرار دادن روالی به جای قاعده پرولوگ جستجوی عقبگرد را انجام میده . در هر یک از این موارد , روش دیگر این است که در سیستم زمان اجرا, روالی را با پارامترهای مناسبی فراخوانی کرد (سیستمهای زمان اجرا را در ادامه بررسی خواهیم کرد )
قاعده پرولوگ میتواند به شکل نمادی باقی بماند و توسط یک روال زمان اجرا تفسیر شود, روال زمان اجرا میتواند به طور پویا متدی را پیدا کند که فارخوانی شود. اگر شرط وبدنه دستور while به زیر روالی بی نام تبدیل شوند, این دستور میتواند توسط یک روال زمان اجرا انجام شود. پیمانه تولید کد میانی جایی است که در مورد انجام کار توسط کد درونی یا سیستم زمان اجرا تصمیم گیری میشود.
پیمانه بهینه سازی کد میانی , پیش پردازشهایی ار بر روی کد میانی انجام میدهد تا پیمانه تولید کد میانی کار آمد شود . نمونهای از یک پیش پردزاش ساده , بر چیدن ثوابت است که در ان , تمام عملیات موجود در عبارات که عملوندهای آن مشخص هستند, انجام میشوند مثال پیچیده تر , درونی سازی است که در آن , دستور فراخوانی تابع حذف شده به جای آن بدنه تابع قرار میگیرد.
پیمانه تولید کد , AST را به صورت یک لیست خطی از دستورات ماشین مقصد بازنویسی میکند . برای این کار , دستوراتی را برای بخشهایی از AST انتخاب میکند , ثباتهایی را باری نگهداری دادهها تخصیص میدهد و این دستورات را به ترتیب مناسبی میآراید.
پیمانه بهینه سازی که مقصد,لیستی از دستورات نمادی ماشین را در نظر میگیرد وسعی میکنند آن را بهینه سازی نماید. برای این منظور , به جای دنبالهای از دستورات ماشین , دنبالههای سریعتر یا کوتاهتری را قرار میدهد . این پیمانه , از ویژگیهای ماشین مقصد استفاده میکند.
مرزهای دقیقی بین بهینهسازی کد میانی, تولید کد , وبهینه سازی کدمقصد وجود ندارد . اگر تولید کد به خوبی صورت گیرد, در بهینه سازی کد مقصد کار زیادی انجام نمیشود , بر چیدن ثوابت میتواند در اثنای تولید کد یا کد مقصد انجام گیرد . علاوه براین بعضی از بهینه سازیها در یک پیمانه نسبت به پیمانه دیگر بهتر انجام میشودو تفکیک سه سطح فوق , اهمیت دارد.
پیمانه تولید کد ماشین , دستورات نمادی ماشین را به الگوهای بیتی متناظر تبدیل میکند. آدرس ماشین کد برنامه و دادهها را تعیین و جداول ثابت و جداول جابهجایی را تولید مینماید.
پیمانه خروجی کد اجرایی , دستورات ماشین کد شده , جداول ثابت , جداول جابهجایی , سرآیندها , پس آیندها و سایر موارد مورد نیاز را توسط سیستم عمل در فایل کد اجرایی ترکیب میکند.
http://pnu-club.com/imported/2009/09/4739.jpg
اکنون شرح مختصری از هر پیمانه را ارائه خواهیم کرد:
پیمانه ورودی متن برنامه ، فایل متن برنامه را مییابد، آن را میخواند، و آن را به صورت جریانی از کاراکترها تحویل میدهد . ممکن است به فایلیهای دیگری که به یان فایل ضمیمه شدهاند . سربزند . این عمل ممکن است نیاز به همکاری سیسم عامل و تحلیل گر لغوی داشته باشد.
پیمانه تحلیل لغوی نشانههای موجودی در جریان ورودی را جدا میکند ورده و نمایش آنها را تعیین مینماید. این پیمانه را میتوان به صور دستی نوشت یا از توصیف نشانهها تولید نمود. علاوهبراین , ممکن است تفسیرهای محدودی را بر روی بعضی از نشانهها انجام دهد :به عنوان مثال، تعیین کند که آیا شناسهای یک ماکرو است یا یک واژه کلیدی.
پیمانه تحلیل نحوی جریانی از نشانهها را به درخت نحوی انتزاعی (AST) تبدیل میکند. بعضی از تحلیلگران نحوی حاوی دو پیمانهاند: پیمانه اول جریانی از نشانهها را میخواند وبرای هر ساختار نحوی که تشخیص داده میشود, تابعی را از پیمانه دوم فراخوانی میکند. توابع موجود در پیمانه دوم , گرههای AST را ایجاد کرده به هم پیوند میدهند. امتیاز این کار این است که میتوان با جایگزینی پیمانه تولید AST از یک تحلیل گر نحوی, AST دیگری را ایجادکرد , و از طرف دیگر , میتوان با جایگزیننی تحلیل گر نحوی, همان نوع AST را زا زبان دیگر به دست آورد.
پیمانه اداره کننده متن , اطلاعات مربوط به متنها را از نقاط مختلف برنامه جمع آوری میکند و گرهها را بر اساس این اطلاعات , حاشیه نویسی میکند. نمونههایی از این اطلاعات عبارتند از: اطلاعات نوع نشای از اعلان عبارات, اتصال دستوارت go to به برچسبهای آنها درزبانهای دستوری و در زبانهای توزیعی , تصمیم گیری در مورد این که کدام فراخوانی روالها ,محلی و کدامها از راه دور هستند. سپس این حاشیه نویسیها برای وارسی متن به کار میروند یا به پیمانههای دیگری ارسال میشوند (مثلا برای تولید کد)
پیمانه تولید کد میانی , ساختار های زبان را که در AST وجود دارند , به ساختارهای کلی تری تبدیل میکند این ساختارهای کلی , کد میانی را تولید میکنند که به طور خلاصه آن را IC مینامیم . طراح کامبایلر تصمیم میگیرد کد کدام ساختار , خاص زبان و کدام ساختار کلی است , اما معمولا این انتخاب چندان دشوار نیست . یک معیار برای سطح کد میانی این است که , تولید کد ماشین برای هر نوع ماشینی آسان باشد معمولا کد میانی متشکل از انحصار متقابل عبارات و دستور کنترل جریان است .
نمونههایی از ترجمههایی که توسط پیمانه تولید کد میانی انجام شده اند , عبارتند از : جایگزینی دستور while باشرطها ,برچشبها و پرشها در زبانهای دستوری در زبانهایی با انقیاد پویا کدی را درج میکند تا مشخص نماید که چه متدی از یک شیء باید فراخوانی شود, قرار دادن روالی به جای قاعده پرولوگ جستجوی عقبگرد را انجام میده . در هر یک از این موارد , روش دیگر این است که در سیستم زمان اجرا, روالی را با پارامترهای مناسبی فراخوانی کرد (سیستمهای زمان اجرا را در ادامه بررسی خواهیم کرد )
قاعده پرولوگ میتواند به شکل نمادی باقی بماند و توسط یک روال زمان اجرا تفسیر شود, روال زمان اجرا میتواند به طور پویا متدی را پیدا کند که فارخوانی شود. اگر شرط وبدنه دستور while به زیر روالی بی نام تبدیل شوند, این دستور میتواند توسط یک روال زمان اجرا انجام شود. پیمانه تولید کد میانی جایی است که در مورد انجام کار توسط کد درونی یا سیستم زمان اجرا تصمیم گیری میشود.
پیمانه بهینه سازی کد میانی , پیش پردازشهایی ار بر روی کد میانی انجام میدهد تا پیمانه تولید کد میانی کار آمد شود . نمونهای از یک پیش پردزاش ساده , بر چیدن ثوابت است که در ان , تمام عملیات موجود در عبارات که عملوندهای آن مشخص هستند, انجام میشوند مثال پیچیده تر , درونی سازی است که در آن , دستور فراخوانی تابع حذف شده به جای آن بدنه تابع قرار میگیرد.
پیمانه تولید کد , AST را به صورت یک لیست خطی از دستورات ماشین مقصد بازنویسی میکند . برای این کار , دستوراتی را برای بخشهایی از AST انتخاب میکند , ثباتهایی را باری نگهداری دادهها تخصیص میدهد و این دستورات را به ترتیب مناسبی میآراید.
پیمانه بهینه سازی که مقصد,لیستی از دستورات نمادی ماشین را در نظر میگیرد وسعی میکنند آن را بهینه سازی نماید. برای این منظور , به جای دنبالهای از دستورات ماشین , دنبالههای سریعتر یا کوتاهتری را قرار میدهد . این پیمانه , از ویژگیهای ماشین مقصد استفاده میکند.
مرزهای دقیقی بین بهینهسازی کد میانی, تولید کد , وبهینه سازی کدمقصد وجود ندارد . اگر تولید کد به خوبی صورت گیرد, در بهینه سازی کد مقصد کار زیادی انجام نمیشود , بر چیدن ثوابت میتواند در اثنای تولید کد یا کد مقصد انجام گیرد . علاوه براین بعضی از بهینه سازیها در یک پیمانه نسبت به پیمانه دیگر بهتر انجام میشودو تفکیک سه سطح فوق , اهمیت دارد.
پیمانه تولید کد ماشین , دستورات نمادی ماشین را به الگوهای بیتی متناظر تبدیل میکند. آدرس ماشین کد برنامه و دادهها را تعیین و جداول ثابت و جداول جابهجایی را تولید مینماید.
پیمانه خروجی کد اجرایی , دستورات ماشین کد شده , جداول ثابت , جداول جابهجایی , سرآیندها , پس آیندها و سایر موارد مورد نیاز را توسط سیستم عمل در فایل کد اجرایی ترکیب میکند.