تعریف کامپایلر

کامپایلر چیست؟

با عرض سلام خدمت کاربران سایت پی وی لرن . ساده ترین تعریف یک کامپایلر یک برنامه است که کد را در یک زبان برنامه نویسی  high-level (مانند جاوا اسکریپت یا جاوا) به low-level  (مانند Assembly)  ترجمه می کند که به طور مستقیم توسط کامپیوتر یا برنامه دیگری مانند یک ماشین مجازی اجرا می شود.

به عنوان مثال، کامپایلر جاوا JVM (ماشین مجازی جاوا) کد Java را به Java Bytecode تبدیل می کند. مثالهای دیگر V8، موتور جاوا اسکریپت از گوگل است که کد جاوا اسکریپت را به کد ماشین یا GCC تبدیل می کند که می تواند کد نوشته شده در زبان های برنامه نویسی مانند C، C ++، Objective-C، و غیره را به کد ماشین تبدیل کند.

تعریف کامپایلر

تعریف کامپایلر

چه چیزی در جعبه سیاه است؟

تا کنون ما یک کامپایلر را به عنوان یک جعبه سیاه جادویی می دانستیم که حاوی حروف الفبا برای تبدیل کد high-level به کد low-level  است. بیایید آن جعبه را باز کنیم و ببینیم چه چیزی در داخل است.

یک کامپایلر را می توان به ۲ قسمت تقسیم کرد.

اولین قسمت که معمولاجلوی انتهای صفحه، کد منبع ارسال شده برای خطاهای syntax، چک ها (و در صورت لزوم) نوع هر متغیر اعلام شده را اسکن می کند نامیده می شود و تضمین می کند که هر متغیر قبل از استفاده شناسایی شده است.اگر خطایی وجود داشته باشد، پیام های خطای اطلاع رسانی را برای کاربر فراهم می کند.همچنین یک ساختار داده ای به نام symbol table  نشان می دهد که حاوی اطلاعات در مورد تمام نمادهای موجود در کد منبع است. در نهایت، اگر هیچ خطایی شناسایی نشود، ساختار داده های دیگر، نمایش متوسط از کد، از کد منبع ساخته شده و به عنوان ورودی به بخش دوم منتقل می شود.

بخش دوم، از نمایش حد متوسط و جدول نماد ساخته شده برای تولید کد  low-level  استفاده می کند.هر دو قسمت جلویی و انتهای جلویی عملیات خود را در یک مرحله از مراحل انجام می دهند. هر فاز یک ساختار داده خاص را از ساختار داده های دیگر منتشر شده توسط فاز قبل از آن ایجاد می کند.فازهای جلویی عموما عبارتند از تجزیه و تحلیل واژگان، تجزیه و تحلیل نحو، تجزیه و تحلیل معنایی و تولید کد کوتاه، در حالی که انتهای عقب شامل بهینه سازی و تولید کد می شود.

 

آنالیز جعبه سیاه

آنالیز جعبه سیاه

 

تجزیه و تحلیل Lexica
مرحله اول کامپایلر، تحلیل لفظی است. در این مرحله، کامپایلر کد منبع ارسال شده را در عناصر معنی دار به نام lexemes شکست می دهد و یک توالی از نشانه ها را از lexemes تولید می کند.یک lexeme را می توان به عنوان رشته ای قابل شناسایی منحصر به فرد در زبان برنامه نویسی منبع دانست، به عنوان مثال، کلمات کلیدی مانند: if,while یا func شناسه ها، رشته ها، اعداد، اپراتورها یا کاراکترهای تک مانند: (, ), . یا :.

یک نشانه شی توصیف یک lexeme است. همراه با مقدار lexeme (رشته ای قابل شناسایی lexeme)، حاوی اطلاعاتی مانند نوع آن (آیا کلمه کلیدی است؟ یک شناسه اپراتور؟ …) و موقعیت ( خط و / یا شماره ستون) در کد منبع که در آن ظاهر می شود.

 

تجزیه و تحلیل Lexica

تجزیه و تحلیل Lexica

 

اگر کامپایلر یک رشته از کاراکتر ها را که برای آن یک نشانه ایجاد نمی کند، روبرو شود، اجرای آن را با پرتاب یک خطا متوقف می کند. برای مثال، اگر یک رشته یا عدد ناقص یا یک شناسه نامعتبر (مانند یک علامت غیر ASCII در جاوا) روبرو شود.

تجزیه و تحلیل syntax

در طی تحلیل تجزیه و تحلیل، کامپایلر از دنباله ای از نشانه های تولید شده در طی تجزیه و تحلیل واژگان استفاده می کند تا یک ساختار داده ای مشابه درخت به نام ، AST را برای چکیده کوتاه Syntax تولید کند. AST نشان دهنده ساختار syntax و منطقی برنامه است.

 

تجزیه و تحلیل نحو

تجزیه و تحلیل syntax

 

تجزیه و تحلیل syntax نیز مرحله ای است که خطاهای syntax نهایی شناسایی و به کاربر در قالب پیام های اطلاع رسانی می شود. به عنوان مثال، در مثال بالا، اگرنماد } فراموش کنیم بعد از تعریف تابع مجموع، کامپایلر باید یک خطا را نشان دهد که یک missingوجود دارد و خطا باید به خط و ستون که در آن} گم شده برود.

اگر هیچ خطایی در این مرحله یافت نشد، کامپایلر به مرحله تجزیه و تحلیل Semantic حرکت می کند.

 

تجزیه و تحلیل Semantic
در طی تجزیه و تحلیل Semantic، کامپایلر از AST تولید شده در تجزیه و تحلیل نحوی برای بررسی اینکه آیا برنامه با تمام قواعد زبان برنامه نویسی سازگار است، استفاده می کند. تجزیه و تحلیل معنایی شامل می شود.

اگر زبان برنامه نویسی از نتیجه نوع پشتیبانی کند، کامپایلر سعی خواهد کرد تا نوع تمام عبارات untyped در برنامه را بیابد. اگر یک نوع با موفقیت نتیجه گیری شود، کامپایلر گره متناظر را در AST با اطلاعات نوعی تعریف می کند.

کامپایلر بررسی می کند که تمام مقادیر اختصاص داده شده به متغیرها و تمام استدلال های درگیر در یک عملیات دارای نوع صحیح هستند. به عنوان مثال، کامپایلر اطمینان حاصل می کند که هیچ نوع متغیری از نوع String دو مقدار خاصی را تعیین نمی کند و یا یک مقدار از نوع Bool به یک تابع پذیرفته یک پارامتر از نوع Double یا دوباره نمی رسد که ما سعی در تقسیم یک رشته نداریم توسط Int،”Hello” / 2 (مگر اینکه تعریف زبان آن را اجازه می دهد).

همراه با انجام نوع استنتاج و چک تایم، کامپایلر یک ساختار داده ای به نام جدول نماد حاوی اطلاعات در مورد تمام نمادها (یا نام ها) که در برنامه دیده می شود را نگه می دارد. کامپایلر از جدول نماد برای پاسخ به سوالات مانند این است که آیا این متغیر قبل از استفاده اعلام شده است، آیا دو متغیر با یک نام در یک دامنه وجود دارد؟ نوع این متغیر چیست؟ آیا این متغیر در دامنه فعلی موجود است؟ و خیلی بیشتر.

خروجی فاز تجزیه و تحلیل معنایی یک AST  و جدول نماد است.

 

خروجی فاز تجزیه و تحلیل معنایی یک AST

خروجی فاز تجزیه و تحلیل معنایی یک AST

 

تولید کد واسط

پس از مرحله تجزیه و تحلیل معنایی، کامپایلر از AST استفاده می کند تا یک کد واسط و ماشین مستقل تولید کند. یکی از این موارد کد سه بعدی است.

کد سه-آدرس (۳AC)، در ساده ترین شکل، یک زبان است که در آن دستور یک تخصیص است و حداکثر ۳ operands دارد.

اکثر دستورالعمل ها در ۳AC از فرم هستندa := b <operator> c or a := b.

 

تولید کد واسط

تولید کد واسط

 

در تصویر بالا، یک کد ۳AC تولید شده از یک AST حاشیه ای ایجاد شده در طی تدوین تابع را نشان می دهد

func sum(n: Int): Int = {
n * (n + 1) / 2
}

تولید کد واسط فاز پایان جلویی کامپایلر را به پایان می رساند.

 

بهينه سازي
در مرحله بهینه سازی، فاز اول انتهای عقب، کامپایلر با استفاده از تکنیک های بهینه سازی مختلف برای بهبود کد کوتاه با ایجاد کد سریع یا کوچکتر تولید شده به عنوان مثال، بهینه سازی بسیار ساده در کد ۳AC در مثال قبلی، حذف تخصیص موقت t3: = t2 / 2 است و به طور مستقیم id2به مقدار  t2 / 2 اختصاص می دهد.

 

جدول بهينه سازي

جدول بهينه سازي

 

تولید کد
در این مرحله آخر، کامپایلر کد میانگین بهینه شده را به کد وابسته به دستگاه، مجمع یا هر هدف دیگر به زبان low-level  ترجمه می کند.

 

جدول تولید کد

جدول تولید کد

 

کامپایلر در مقابل مترجم

مترجمان و کامپایلرها در ساختار بسیار شبیه هستند. تفاوت اصلی این است که یک مترجم مستقیما دستورالعمل ها را در زبان برنامه نویسی منبع اجرا می کند در حالی که کامپایلر این دستورات را به کد ماشین کارآمد ترجمه می کند.یک مترجم معمولا نماینده ,واسط تولید می کند و بلافاصله آن را ارزیابی می کند. بسته به مترجم، نماینده واسط می تواند یک ASTیا یک نمایشگر low-level  مستقل از دستگاه مانند کد سه بعدی باشد.

به اشتراک بگذارید