المترجمات Compilers
تختلف لغاتنا التي نتواصل بها عن اللغة التي يفهمها الحاسوب! هذه اللغة تسمى بـ “Binary Code”، و هي عبارة عن آحاد وأصفار فقط! أما البرامج والتطبيقات التي نستعملها؛ فهي مكتوبة في الأصل بلغات مختلفة وهي لغات البرمجة، مثل: Java, C++, Python…
للتبسيط؛ تخيل معي أننا برمجنا آلة حاسبة بسيطة يمكنها أن تجمع عددين بعملية حسابية، هذه العملية الحسابية تتم على أربع مراحل: استقبال العدد الأول، ثم استقبال العدد الثاني، ثم جمع العددين، ثم عرض النتيجة. يكتب المبرمج هذه التعليمات ببضعة أسطر مستخدمًا الأبجدية الإنجليزية، لكن أبجدية الآلة هي 0/1 (سميناها Binary)، فكيف سيفهم الحاسب التعليمات المكتوبة بلغة غير الBinary؟! وهنا يحين دور المترجم Compiler، الذي يحوّل الكود المكتوب بلغة البرمجة عالية المستوى (مثل java و Python) إلى لغة الآلة (وحدات وأصفار, Binary).
الكود المصدري Source Code :
لنفرض أن التعليمات التالية كُتبت بلغة C++:
int a ;
int b ;
int c = a + b
نلاحظ في بداية كل سطر كلمة “int”، و هي اختصار لكلمة Integer، والتي تعني الأعداد الصحيحة الطبيعية (الأعداد بدون فاصلة عشرية). فمن أجل استعمال أي نوع من البيانات فلا بد لك أن تسميه(مثل a, b و c)، وتحدد نوعه(مثل int , char) قبل استعماله. ففي السطر الأخير استعملنا متغيرًا (اسمهC) وهو عدد صحيح طبيعي، وهذا المتغير سيكون ناتج المجموع للمتغيرين a و b. و في نهاية كل سطر توجد علامة “;” و التي تعني أن هذا الأمر انتهى، لأن الحاسوب لن يعلم من تلقاء نفسه متى ينتهي الأمر، لذلك وجب إخطاره بكتابة “;”.
ملاحظة: عملية الإسناد ) : يُسند فيها الناتج (a+b) في الطرف اليميني إلى المتحول في الطرف اليساري (c). ويحول المترجم هذه التعليمات إلى لغة الحاسب (فرضاً):
01000101010111000010101010
10101010000110100010101010
10001001010010101010010101
مكوّنات نظام الترجمة Compiler
كيف يحول المترجم الكود عالي المستوى إلى كود الآلة السابق؟
تشترك عدة مكوّنات داخل نظام الترجمةCompilation System لإنجاز هذه المهمة، وأهمّ هذه المكوّنات هي:
– محلل المفردات أو Lexical Analysis : يقرأ الكود البرمجي حرفًا حرفًا، وينشأ جدولًا يدون فيه أسماء المتحوّلات (a, b, c) وقيمة كل متحوّل، ثم يعطي لكل متحوّل اسمًا ثنائيًا (مثل 0100101)
– محلل الصيغ النحوية أو Syntax Analysis : في هذه المرحلة تُبنى شجرة الإعراب أو Parse Tree أو Syntax Tree. ولتوضيح الفكرة نورد مثالًا:
تتكون الجملة الفعلية في اللغة العربية من (الجملة= فعل+ فاعل+ مفعول به)، ليكن الفعل: أكل، والفاعل: الولد، والمفعول به: التفاحة. في لغة البرمجة لدينا القاعدة التالية: (التعليمة= نوع المتحول + اسم المتحوّل + فاصلة منقوطة)، نوع المتحول = int, اسم المتحول = a, الفاصلة المنقوطة = “;”. أي: حُوّل الكود (النص) إلى شجرة.
– محلل الدلالات أو Semantic Analysis : تُحدّد دلالات أي برنامج من خلال سلوكه أثناء التشغيل، لكن أغلب اللغات تتسم بصفات تمكنها من تحديد هذه الدلالات قبل بدء التشغيل. اسم هذه الصفات هو الدلالات الثابتة Static Semantics, عملها أن تحلل دلالات مثل التعريفات Declarations كما فعلنا في أول المقال، فقد ذكرنا وجود متغير تحت اسم حرف، و هذا المتغير عبارة عن عدد صحيح طبيعي Integer واختصارًا int ليس عبارة عن حرف أو سلسلة من الحروف التي تكون كلمات أو جمل…
– محسن شيفرة المصدر أو Source Code Optimizer : لنفرض الكود التالي:
Int a;
a = 5;
int b;
وأننا كتبنا البرنامج ولم نستخدم المتحوّل b أبدًا، هنا يحذف المحسّن Optimizer التعليمة int b; واستبدال التعليمات السابقة بتعليمة واحدة هي int a = 5;.