• 0
bashmohandes

كيف تبني لغة برمجة(المرحلة الأولى)

سؤال

بسم الله الرحمن الرحيم...

اليوم ان شاء الله سأحاول أن أبدأ معكم المرحلة الأولى في علوم اللغات و المترجمات و ندعو الله أن يوفقنا حتى نصل الى مرحلة معقولة من الدروس ان شاء الله

المرحلة الأولى

ماهي لغات الحاسب؟؟

لغة الحاسب الأساسية هي الMachine Code أو لغة الإلة و هي اللغة التي لا يفهم الحاسب غيرها (معلومة قديمة و لكنها البداية الصحيحة) و لأنها ليست لغة بسيطة و لا يمكن بناء نُظُم أو تطبيقات بها لعدة أسباب منها أنها تعتمد على نوع المعالج و الhardware المصاحب له .. أيضاً غير مناسبة لعقلية المطورين بل تناسب أكثر علماء الHardware و المشتغلين به..

لهذا دعت الحاجة الى ظهور لغات أخرى أسهل و أكثر تخصصاً

مثل ال Assembly و B و C و ++C و COBOL و Fortran و ...... الخ

و لكن في النهاية جميع اللغات السابقة يجب أن تتحول في نهاية المطاف الى Machine Code و هذا ما تقوم به المترجمات

المترجمات أيضاً لها أنواع

1- الAssembler

الأسمبلر هو اسم الmodule الذي يقبل مدخل(input) من لغة الAssembly و يُنتج (output) مُخرج من لغة الإلة Machine Code و في العادة يكون تصميم الأسمبلر بسيط فهو مجرد Line by Line Translation أي مترجم سطري و هذا لطبيعة الAssembly البسيطة فهو يقوم بعمل Recognition للأوامر (mnemonics) و تحويلها الى الmachine code المناظر لها متبوعاً بالقيم التي تليه

بالطبع الAssemblers الأحدث أكثر تعقيداً و لكن مازالت الفكرة الأساسية واحدة...

2- الCompiler

الCompiler هو اسم الmodule الذي يقبل input من لغة High Level مثل الC و يعطي output من الObject Code المناظر له..

مقارنةً بما يفعله الAssembler فالCompiler أكثر تعقيداً فهو يقوم بعمل Analysis للInput و يحاول التعرف على المكونات الأساسية للكود(Tokens) ثم يحاول مقارنة مجموعات ال Tokens المتتالية بالGrammar Rules التي يعرفها حتى يصل الى المناسب و من ثم يفهم المقصود و يترجمه و هذا أصعب كثيراً بما يقوم به الassembler و يزداد صعوبة مع سهولة اللغة و رقيها..

و من الCompiled Languages مثلاً ال ++C/C و ال COBOLو الSNOBOL و الPascal

3-الInterpreter

الinterpreter هو اسم الmodule الذي يقوم بعملية الترجمة للسطر ثم ينتظر تنفيذه ثم ينتقل للسطر الأخر و هكذا و هو يشبه الى حد ما الCompiler و لكنه في أغلب الأحيان لا يمكن ان تُنتج منه Executable File أي أنه يجب أن يقوم الinterpreter بعمل الترجمة كل مرة لتشغيل البرنامج كما أن مهمته تزداد تعقيداً في وجود الLoops و الConditions و لأنه يجب عليه أن يترجم الloop كلها ثم يحتفظ بالكود الخاص بها في الذاكرة حتى يكررها ثم ينتقل بعد هذا الى مابعدها...

مقارنةً بينها و بين الCompilers فالInterpreters أبطأ كما أنها تحتاج الى ذاكرة أكبر لعملية الInterpretation أو الترجمة و لكن توجد مميزات أنك تستطيع اكتشاف الأخطاء و تعديلها أثناء عمل البرنامج دون الحاجة الى اغلاقه و تعديله و بناؤه من جديد ثم اعادة تشغيله

و من اللغات الInterpreted الHTML و الVisual Basic و الJava Script و الPHP و الASP والpython و الPerl

الشكل العام للCompiler او مايسمى Compiler Anatomy تشريح الCompiler

Compiler01.jpg

يتكون الCompiler من 4 أقسام أساسية

1- الLexical Analyzer

2- الSyntax & Semantic Analyzer

3- الCode Generator

4- الCode Optimzer

و يستخدم كلهم مايُسمى بالSymbol Table و سأحاول أن أصل الى هذه النقطة ان شاء الله

و سنتعرض لكل نقطة بالتفصيل قدر المستطاع

1- الLexical Analyzer أو ما يُسمى أحياناً الSCANNER

الSCANNER كما هو واضح من الاسم يقوم بعمل scan أو مسح للSource Code و يقوم بعدة مهام أساسية

1- تجميع الجمل التي تتكون من عدة سطور في سطر واحد

2- ازالة كل ما ليس له علاقة بالبرنامج مثل الcomments و المسافات الزائدة

3- التعرف على المكونات الأساسية للغة Basic Entities مثل

- الثوابت Constants

- المُعرفات Identifiers مثل الVariables و الKeywords

- الOperators أو العوامل مثل ال+ و / و * أو < و > و هكذا

4- عمل التغييرات اللازمة في الSymbol Table عن المكونات التي تم التعرف عليها ليتم استخدامها في باقي المراحل

أما الOutput الصادر عن الScanner يكون في شكل Tokens كما ذكرنا من قبل و كل Token يحتوي على نوع المُعرف و أحياناً عنوانه في الSymbol Table

مثال على الLexical Analyzer

تخيل أن الInput Code هو

IF A >= B + C THEN A = B

فسيصبح الoutput من الLexical Anaylizer مثلاً

14 99.8 61 99.9 51 99.12 15 99.8 57 99.9

بفرض أن

14 ====> هو الToken الخاص بكلمة IF

99.8 ===> هو الToken الخاص بالمتغير A حيث 99 تعني أنه متغير و 8 هي عنوانه في الSymbol Table

61 ===> هو الToken الخاص بالمعامل الثنائي >= و هكذا

و أيضاً يجب أن تعرف أن الLexical Analyzer ليس له أي علاقة بالGrammar الخاص باللغة كل ما يقوم به هو التعرف على الكلمات الأساسية و الRegular Expressions الدالة على المعرفات الأساسية مثلاً

ال Regular Expression التالي [a-zA-Z][a-zA-Z0-9]* هو أسماء المتغيرات

و هو يعني أن يبدأ المتغير بحرف واحد على الأقل متبوعاً بأي عدد من الحروف و الأرقام.. فعندما يجد الLexical Anaylzer هذا الPattern في الInput Code فإنه يضيف Record جديد في الSymbol Table باسم الvariable و يصنع Token له.

2- الSyntax & Semantic Analyzer

الSynatx & Semantic Analyzer أو مايُعرف بالParser هو مايقوم بتطبيق الSentactic Rules أو قواعد اللغة على الinput Code لفهم الغرض من البرنامج..

مثال

IF A >= B + C THEN A = B

سيتم التعرف على الجملة السابقة على أنها جملة شرطية Conditional Statement حيث

B + C هو Expression يجب حسابه

A >= B + C هو شرط Condition

A = B هي جملة يجب تنفيذها في حالة أن الشرط صحيح

و يستطيع الParser أن يُنتج لغة وسيطة أو ماتُسمى علمياً الQuadruples أو الرُباعيات و تكون بالشكل التالي

Operation   Operand1   Operand2   Result

و في الCode السابق سيكون الناتج

ADD   C   B   T1
GTE   T1  A   T2
BNZ   T2  L1    
STO   B   A
LBL   L1

في السطر الأول يجمع المتغيرين B و C و يضع الناتج في المتغير الإحتياطي T1

في السطر الثاني يقارن باستخدام Greater Than or Equal GTE أو أكبر من أو يساوي و يضع نتيجة المقارنة في متغير احتياطي T2

في السطر الثالث يستخدم Branch ifNot Zero BNZ للقفز الى نهاية الجملة في حالة عدم حدوث الشرط (بفرض أن القيمة في T2 تكون صفراً اذا كان الشرط صحيحاً)

في السطر الرابع يقوم بعمل Store STO أو حفظ لقيمة B في A

3- الCode Generator

الCode Generator هو الmodule الذي يأخذ الQuaruples كInput ليقوم بتحويلها الى الMachine Code المناظر و هي تبدو للوهلة الأولى مهمة سهلة و لكنها أيضاً مهمة معقدة حيث أن على الCode Generator التعامل مع عدد محدود من الRegisters و التعامل معها بحرص حتى ينتج برنامج سريع و قوي كما أن هذا يختلف من Hardware الى الآخر

4- الCode Optimizer

هي عملية ترتيب و تنظيم الكود الناتج من Code Generator و ازالة التكرار فيه و أيضاً الحصول على كود أسرع More Efficient...

انتهت بحمد الله المرحلة الأولى ...

في انتظار اسئلتكم و استفساراتكم حتى موعد المرحلة الثانية ان شاء الله و سنتحدث فيها عن تعريف اللغات و تقسيماتها و كيفية كتابة الProduction Rules

المصادر

Computer Languages & Compilers, Prof. Dr. Ali Fahmy, Cairo, 1997

تقديم م/ محمد حســـام

تم تعديل بواسطه bashmohandes
4

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

19 إجابة على هذا السؤال .

  • 0

السلام عليكم

بداية جيدة يا أخ محمد

ولكن كان لدي هناك تعليق

بالنسبة لل code optimizer فيتم تنفيذه قبل code generator .

بالنسبة لل code optimeizer فهو يجعل البرنامج يستخدم أقل كمية ممكنة من الذاكرة ، وذلك بالقيام بعمل إدارة للذاكرة بصورة تمكنه من ذلك ، بمعنى أنه لا يستطيع أن يغير أي شيء من محتويات البرنامج، ولكنه قد يقسم البرنامج إلى أجزاء ثم يقوم بتحميل هذه الأجزاء إلى الذاكرة بصورة لا تجعل البرنامج يلتهم الذاكرة كلها ، هل ما أقوله صحيح أم لا؟

بالنسبة للأخ حمادة:

المفسرات لها مجال والمترجمات لها مجال ولا يمكن أن نستغني عن أحدهما ،فالمفسرات لها فوائد كما ذكرها محمد.

ولكن توجد هناك مفسرات جديدة مثل تلك التي تستعمل مع لغة python ،،حيث أنها تترجم البرنامج كله إلى لغة وسيطة لتسريع عملية التنفيذ فيما بعد.

ولا توجد صعوبة في رأيي في أي شيء في أي علم ، طالما أن بشرا مثلنا قام بها فهذا دليل قوي على أن الأمر ممكن، وإذا كنت ستسمر في طريق اختيار الأسهل فلن تتقدم أبدا، هذه نصيحة مني لك يا أخ حماده :)

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

الحقيقة هذه نقطة سابقة لأوانها و لكن لا مانع من التطرق لها الآن

الCode Optimization في الواقع يتم على مرحلتين مرحلة قبل الCode Generation على الQuadruples و مرحلة بعد الCode Generation على الAssembly Code

المرحلة التي تتم على الQuadruples يكون الهدف منها تقليل حجم الquadruples بإزالة التكرار و لكن يبقى الناتج أيضاً Quadruples و لكن الoptimization على مستوى الassembly يكون مختلفاً قليلأً فيكون محاولة لدمج سطور متتالية من الأسمبلي في سطور أقل باستخدام الinstructions المتقدمة الخاصة بالمعالج و تُستخدم هذه التقنيات على سبيل المثال عندما تريد أن تبني مترجم ل intel 8086 و لكن بعد عدة سنوات يظهر معالج جديد يختلف قليلأً فهل ترمي الCode Generator و تكتب واحد جديد؟؟؟ بل انك تحاول أن تعرف الفروق البسيطة و التي اختصرت مجموعات من الأسمبلي في سطر واحد أو سطور أقل و تبني Optimizer على هذا المستوى فقط بدلاً من اعادة كتابة الCode Generator كله مرة أخرى و لكن بالطبع بعد مرحلة معينة من التطور يجب اعادة كتابة الCode Generator

و لكن أنت مُحق في أن الOptimization الأساسي يكون قبل الCode Generation و لكن عامةً في أبحاث الCompilers أكثر من 70% تكون في الOptimization فهناك أيضاً Optimization على مستوى الSource Code و هذا أكثرهم تعقيداً و أبسط نوع منه ماتجده في بعض المحررات الحديثة مثل Eclipse مثلاً.. الOptimization تجده في كل مكان لأنه العامل الأساسي الذي يُفرق بين Compiler و آخر

تم تعديل بواسطه bashmohandes
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

كلام جميل, انا كنت منتظر شي كهذا :)

لاني بصراحة احاول كتابة شي من هذا القبيل (ليس كومبايلر كامل) للغة D (موقعها http://www.digitalmars.com/d) و اعتمد حاليا على الـ specification الخاصة باللغة (و هي هنا http://www.digitalmars.com/d/lex.html)

في البدء كنت اريد بناء parser بسيط لاضافة دعم اكثر للغة في Eclipse IDE و لكن بعد ذلك كبرت الشغلة في دماغي فحولته الى مشروع منفصل و اصبح تحدي يعني :lol:

طيب .. سؤال: بالنسبة للـ lexcal analysis, فهل التعريف اللذي اعطيته اياها هو تعريف معتمد و متفق عليه؟ ام ان كل شخص قد يعرفها على كيفه؟ لان مهندس لغة D يعرفها كالتالي:

lexical analysis

The source file is divided up into a sequence of tokens. Special tokens are replaced with other tokens. Special token sequences are processed and removed.

يعني مجرد تحويل النص الى مجموعة tokens مع استبدال نصوص خاصة (قليلة جدا) بنصوص أخرى (مثل __FILE__ و __LINE__) , و لا يذكر في هذه المرحلة اي شي عن الـ symbol table بل يتركها الى الـ semantic analysis على ما يبدو.

و هذا يبدو لي اكثر واقعية .. فاذا كنت ستتعرف على المتغيرات في مرحلة الـ lexical analysis فماذا ابقيت للـ parser او بمعنى اصح, لماذا قمنا بتقسيم المهمة الى عدة مراحل؟

حسب ما فهمته (و هذا فهمي الخاص .. اخذته من معلومات مبعثرة من هنا و هناك, و لم أقرأها في كتاب), نحن نريد تحليل النص, و لكن لا نستطيع القيام بقرائته مباشرة كما نقرأ string عادي, و ذلك لاننا لا نستطيع بناءا افتراضات معينة لمجرد وجود سلسلة متتابعة من الحروف اللتي قد نظن انها تعني شيئا معينا.

يعني, لو وجدنا ثلاثة حروف متتابعة int فهذا لا يعني بالضرورة اننا وجدنا تعريف لمتغير من نوع int, فمن الممكن ان تكون كلمة int داخل string او ان تكون جزء من comment او تكون جزء من كلمة اخرى intersection مثلا .. الخ. لذلك لا بد اولا من تحليل النص بشكل ادق ..

و الـ lexer ايضا (حسب فهمي) عندما يحول نصا معينا الى token فإنه يحدد نوع هذا الـ token, فلو وجد قوسا مثلا ')' فسيقوم باضافة token من نوع يعبر عن هذا القوس .. مثلا TOK_OPEN_PARENTHESIS او شي من هالقبيل .. و نفس الشي فإنه عندما يقرا رقما فإنه سيقوم بملاحظة ان هذه الـ token هو في الحقيقة رقم ..

و هذا هو الهدف الوحيد من الـ lexer بحسب فهمي (يصير أسمي الـ lexical analyser بـ lexer .. صح؟)

و الان بعد ان قمنا بعملية الـ 'lexing' فإن تحليل الكود سيصبح اسهل بكثير .. فبدلا من محاولة فهم النصوص في سياقها, فإننا سنقوم بتتبع الـ tokens (و اللتي تمثل النصوص اصلا) و محاولة فهم ماللذي تعنيه بالنسبة للغة.

فلماذا يتعب الـ lexer نفسه بمحاولة اكتشاف المتغيرات او بناء symbol table؟

و سؤال يمكن سابق لأوانه: ما هو الـ symbol table؟ هل هو قائمة باسماء المتغيرات و الدوال functions و الفئات classes؟ ام انه شيء آخر؟ و اليست هذه القائمة في الحقيقة شجرة, لانها قائمة متفرعة؟ يعني لو كان هناك كلاس فإنه اكيد سيحتوي في داخله على اسماء المتغيرات و الدوال التابعة له .. اليس كذلك؟

ام ان الـ symbol table لا علاقة له بهذه الأشياء؟

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

بالنسبة للLexical Analyzer (Lexer) فوظيفته التعرف على الpatterns الأساسية في اللغة سواءً كانت متغيرات أو كلمات محجوزة أو operators أو غيرها و تحويلها إلى Tokens متفق عليها بينه و بين الSyntax & Semantic Analyzer (Parser) ...

أما بالنسبة للتعرف على المتغيرات و تخزينها في الٍSymbol Table فإن هذا شئ ضروري جداً لأنه يجب الاشارة الى المتغير بوسيلة ما تُحدد خصائص كثيرة فيه و لكن تكون وظيفة الLexer هي مجرد وضع الRecord في الSymbol Table فقط و الإشارة إليه بالToken بوسيلة أو بأخرى و لكن لن يضيف الLexer أي معلومات عن المتغيرات في الSymbol Table لأن المعلومات تنتج من المراحل اللاحقة و لكن أول من يكتشف وجود المتغير أو الثابت هو الLexer و لهذا فهو الذي ينشئ الRecord استعداداً للمراحل التالية ...

و من المعلومات التي تضاف في الSymbol Table أيضاً و لكن تضاف في الParser هي إذا كان المتغير تم تعريفه , هل تم وضع قيمة أولية فيه, هل تم استخدامه ام لا, نوع المتغير, القيمة الأولية له (اذا كان ثابتاً) , و بعض المعلومات الأخرى التي يحتاجها الCompiler في مراحله المختلفة و التي تختلف باختلاف تفاصيل بناء الCompiler نفسه

بالنسبة لاحتمال ورود الكلمة مثل int في مكان أخر مثلاً داخل الComments فإن أو مهمة للLexer كما ذكرنا هي ازالة جميع الComments أولاً

و أيضاً بالنسبة لاحتمال اللخبطة مع الكلمات مثل intersection مثلاً فان أي Lexer لو كان في أبسط الحالات يقسم الinput code الى كلمات على أساس المسافات فلن يخطئ هذا الخطأ أبداً و هذا أيضاً يتوقف على تفاصيل Syntax اللغة فهناك لغات تسمح بانشاء متغيرات باسماء الreservered word بلا مشاكل (فتخيل تعقيد الLexer) الذي سيتعرف بالرغم من هذا على متغير اسمه IF و يُفرقه عن كلمة الشرط IF و لا تعجب فهناك لغات تسمح بهذا فعلاً... فيمكنك كتابة جملة مثل

IF ELSE THEN IF = ELSE ELSE ELSE = FALSE ENDIF

و هنا ستجد أنه تم تعريف متغيرين من نوع bool هما IF و ELSE و ستكون هذه جملة صحيحة و يفهمها الCompiler :lol:

1

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

طيب كيف سيعرف الـ lexer ما هو المتغير اذا لم يكن يحاول فهم الجملة كاملة؟ هل يأخذ اي identifier لا يعرفه و يعتبره symbol جديد مثلا؟ باعتبار الشيء الوحيد المعرف هو الـ keywords, فبالتالي اي identifier جديد لا بد ان يكون اسم لـ symbol؟ ام هناك شيء آخر؟

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

والله كنت أفكر في كل هذا قبل أيام!!

كنت أسأل نفسي: هل صنعت مترجم أو Compiler بسيط في حزمة Math Parser التي صنعتها هنا:

حزمة قارئ المعادلات الرياضية

الشفرة متاحة للعلم.

طريقة عمل ترجمة الجمل الرياضية: تجد هذه في الطريقة readOperation في الفئة SmartExpressionReader.

1- تقرأ الحزمة المدخل على شكل جملة String. ولتكن الجملة التالية:

الوقود =  إذا( مطلق (مسافة السفر - 1000 ) > 100 ، مسافة السفر * 2 ، 4000)

معناها: إلى كانت القيمة المطلقة ل(مسافة السفر -1000) أكبر من 100

إذن:  قيمة الوقود = مسافة السفر *2

وإلا: الوقود = 4000

2-ندخل مرحلة التحليل أو Lexical Analyzer:

أولا getSubStringPositions: تأخذ هذه الطريقة الجملة الرياضية وتعطينا مواقع المتغيرات، والدوال، والإشارات والأقواس وأي شيء آخر. فيصبح لدينا مصفوفة تحمل مواقع الدوال، والمتغيرات، والأرقام، والإشارات وغيرها في الجملة مثلا: {0،3،6،8،...}

ثانيا readSubStrings: نقرأ الناتج من العملية السابقة ليصبح لدينا مصفوفة بجميع الفواصل Tokens التي داخل الجملة. مثلا هكذا:

{إذا ، ( ، مطلق ، ( ، مسافة السفر ، - ، 1000 ، ) ، > ، 100، ، ، مسافة السفر ، .......}

ثالثا: readSubLists: وهذا يقرأ الناتج من الجملة السابقة ويقسم مجموعة الكلمات إلى مجموعات داخل مجموعات، (يأخذ الأقواس ويجمع ما في دخلها في مجموعة واحدة ويرفقها للمجموعة التي تحتويها!

رابعا: convertStringToOperations: نحول مجموعة الكلمات الناتجة من العملية السابقة إلى عمليات يفهمها البرنامج. (Operation) هذه العمليات تستطيع التعامل مع بعضها وأخذ النتائج منها في ما بعد. مثلا:

إذا: تصبح الدالة المعروفة إذا أو if!

مسافة السفر: تصبح متغير اسمه مسافة السفر.

مطلق: تصبح دالة معروفة ترجع القيمة المطلقة. Abs

(-) : إشارة سالب..

وهكذا.

وفي هذه المرحلة أيضا يتم بناء جدول الدوال والمتغيرات المستخدمة في الجملة. (SymbolTable) الجدول اسمه في البرنامج Operator Source!

3- مرحلة تحليل الجمل أو Semantic Analizer: وقد وصلت إلى ما أسميه الإصدار 5

الطريقة integrateOperations: في هذه المرحلة يتم تركيب وفهم الجمل مع بعضها. وعلى الترتيت تنقسم إلى:

أ- integrateFunctions: وهذه تقرأ الدوال وتحاول فهمها.

ب- integrateMarkOperator: وهذه تقرأ الإشارات الخاصة مثل (!) التي وظيفتها عكس جدول الصدق!

ج-integrateSigns: وهذه تقرأ الإشارات المضافة إلى رقم أو متغير أو دالة وتغير في إشارتها، وهي بالخصوص ( +، -)

د- integrateOperands: وهذه تقرأ باقي الإشارات، (*،^،&،<،=،+،- ....) مراعية بذلك أولويتها.

ناتج المرحلة 3 هو الحصول على Operation جاهز للتنفيذ!! فهو يعتبر الملف المترجم أو Compiled! (بالمناسبة تستطيع حفظه كملف تنفيذي!!)

4- مرحلة التنفيذ

إذا أردت تنفيذ هذا (الملف) التنفيذي فعندك الأمر:

 operation.result();

وستحصل على النتائج. طبعا ناتج العملية السابقة = 2000.. لاحظ أن قيمة المتغير (مسافة السفر) تساوي صفرا، مالم تغير قيمتها!

هنا في هذه المرحلة سيتم حساب الجملة الرياضية وإعطائنا النتائج!

طبعا لا يوجد والله أعلم منتج للشفرة Code Generator لكن ربما هي مدمجة في منطق البرنامج، ولا أدري. ولو أردت الاجتهاد لقلت أنها موجودة في كلا المرحلتين الثانية والثالثة!

أما عن الحلول المثلى Code Optimizer،، فلم أصنع هذا، لكنها مندرجة تحت المخططات الغير منفذة حاليا. ولشرح الخطة:

الشفرة التالية:

(5 +3 *8+س ) هذه الشفرة، إذا استبعدنا السلام عليكم ورحمة الله وبركاته لا تحتوي على متغيرات! ولهذا نستطيع استبدالها (وقت الترجمة) بالعدد 29 تصبح المعادلة( 29+ س)! بدلا من حسابها وقت التنفيذ!! وهذا سيسرع من عمل البرنامج! والحصول على النتائج!

ملاحظات على الحزمة:

لاحظ أنك تستطيع كتابة:

إذا( إذا > مطلق ، مطلق (-40) ، إذا +80 )

كما أشار المهندس محمد على بعض إمكانية بعض اللغات لمعرفة وقراءة هذه الجمل!!

لاحظ أن الحزمة تتعرف على المتغيرات الجديدة،والدوال الجديدة أيضا!

لاحظ أن الدوال تستعمل متغيرات وهي مختلفة عن المتغيرات التي تستخدمها مباشرة، لكل دالة مجالها في التسمية! FunctionContext! أو Block Context!

لاحظ أن الحزمة تدعم التكرار For Loop مبسطة على شكل الدالة Sigma الجديدة المتوفرة في الإصدار 2.5!

Sigma(-2, 4 , Abs())

وهذه الدالة ستعطي ناتج مجموع القيم المطلقة من -2 إلى 4 يصبح الناتج 13!

شرح الحزمة أو Documentation الحزمة متوفر هنا: Documentation الشروحات

أرجو أن أكون وفقت في شرح هذا، وأشكر المهندس محمد على ما قدم!

وآسف على الإطالة!

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

إضافة إلى ما سبق، توجد في الحزمة أخطاء وقت الترجمة Compile Time Errors:

أخطاء SyntaxErrorException في الغالب، أو UnknownArgumentException

وأخطاء وقت التنفيذ Runtime Errors:

MathLogicException: مثلا إذا كانت الدالة غير منطقية (لا تنتهي) recursion! أو التكرار لا ينتهي!! أو أن المتغير يساوي نفسه، الخ..

وأخرى!

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0
طيب كيف سيعرف الـ lexer ما هو المتغير اذا لم يكن يحاول فهم الجملة كاملة؟ هل يأخذ اي identifier لا يعرفه و يعتبره symbol جديد مثلا؟ باعتبار الشيء الوحيد المعرف هو الـ keywords, فبالتالي اي identifier جديد لا بد ان يكون اسم لـ symbol؟ ام هناك شيء آخر؟

الLexer لايستطيع تحديد نوع المتغير كل ما يستطيع أن يعرفه هو أن هذا الsequence من الcharacter ينطبق شكلاً على شكل المتغيرات و لكن ربما لم يتم وضع نوع له و لكن هذه ليست مشكلة الLexer

مثال

في جملة مثل الجملة التالية سيعتبرها الLexer صحيحة و لكنها في الحقيقة خطا 100% و لكن اكتشاف هذا النوع من الأخطاء يتم في الSyntax & Semantic Analyzer

Integer float if then while end arabTeam

هذا الكود الذي تراه غير منطقي سيعتبره الLexer صحيحاً لأن كلاً من كلمة Integer, float, if, the, while, end هي كلمات يعرفها و كلمة arabteam سيعتبرها identifier و هكذا...

لكن السؤال ما نوع الأخطاء التي يمكن أن يتعرف عليها الLexer ؟

الأخطاء هي الUnrecognized Symbol بمعنى اذا عرفت متغير يبدأ بأرقام مثل 123abc و كان من شروط اللغة أن لا يبدأ الIdentifier بأرقام في هذه الحالة لن يستطيع التعرف على هذا الsequence و سينتج عنه خطأ ...

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

ياجماعة انا عاوز اعرف حاجة

هو lex و yacc لابد من استخدمهم معا ام كل منهما ادة منفصلة

يعنى لو كتبت yacc هل احتاج لكتابة lex

السوال ببساطة ؟

هل لابد من وجدو الاثنين معا ام كل جزء منهم مرحلة اذا كتبتyacc ممكن الاستغناء عن lex

ولا لازم يكتب الاثنين لتكون لغة

--------------------------------------------------

وانا بانتظار الدرس التانى بس يارت ياباشمهندس لو توضح فى قائمة بسيطة عناصر الموضوع هكذا يعنى :

1- كيف يكتب lex

2- تعلم تصميم code genertor

3-وهكذا

ما هى خطة الدروس

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

بالنسبة للLex و الYacc فهما أداة واحدة مقسمة الى قسمين و هو الLexer Lex و الParser (Semantic Analyzer) Yacc و يجب استخدامهما سوياً

بالنسبة لطريقة كتابة الLex و الYacc سأشرحها ان شاء الله حين يحين وقتها فيجب أولاً فهم الأساسيات و أنا حالياً أحضر للمرحلة الثانية ...

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

هممم ... الـ lexer اللذي كتبته اصلا لا يهتم بالاخطاء! يعني لوكتبت

123abcd

فسيعتبره رقما قد يتبعه suffix .. و في حالة الاداة اللتي اريد عملها فهذا مقبول لانها ليست compiler .. يعني الـ lexer لا يهتم فيما اذا كان كل شيء يتبع قواعد اللغة, طالما ان هذا لا يؤثر في صحة قرائة الملف .. يعني المهم ان هذا لا يستبب في قراءة الملف بشكل خاطئ, لانه حصلت معي اني اهملت بعض القواعد مما كان يؤدي الى قرائة الملف بشكل خاطئ.

هناك نقطة في الـ parser معقدتني شوية ..

الان لو جئت اقرأ declaration فقد يكون بسيط او معقد (هذه التعريفات من اختراعي)

البسيط هو ببساطة:

type identifier;

اما المعقد هو من قبيل:

int *[] (*p);

لا اعرف اصلا اذا كان هذا التصريح valid ام لا .. و لكن هناك اشياء مشابهة ..

هذه كيف نحللها؟

اعرف ان السؤال سابق لأوانه .. لكن وددت ان اشير اليه الان لعلك تستطيع التعريج عليه فيما بعد :lol:

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

لمن يرغب فى بناء لغته الخاصة

اليكم اهم الانباء

1- كتاب رائع و فظيع فى بناء المترجمات والمفسرات واللغات التى غير موجودة

++ writing compiler and interpreters using C

2- كتاب اخر بس بشع وجامد اوى

compiler :principles , techniques , tools

واسال الله ان يوفقنا جميعا

تم تعديل بواسطه hamada hassan ali
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0
هممم ... الـ lexer اللذي كتبته اصلا لا يهتم بالاخطاء! يعني لوكتبت

123abcd

فسيعتبره رقما قد يتبعه suffix .. و في حالة الاداة اللتي اريد عملها فهذا مقبول لانها ليست compiler .. يعني الـ lexer لا يهتم فيما اذا كان كل شيء يتبع قواعد اللغة, طالما ان هذا لا يؤثر في صحة قرائة الملف .. يعني المهم ان هذا لا يستبب في قراءة الملف بشكل خاطئ, لانه حصلت معي اني اهملت بعض القواعد مما كان يؤدي الى قرائة الملف بشكل خاطئ.

عذراً لم أفهم قصدك فأنا لا أتابع الأداة التي تقوم بعملها داخل Eclipse و لكن أعتقد أن هذا ليس استفساراً مني أو اعتراضاً على أي شئ شرحته و لهذا سأنتقل إلى بقية المشاركة

الDeclaration الذي ذكرته على سبيل أنه معقد في الحقيقة هو أيضاً Declaration بسيط

بمعنى تعريف مؤشر في الC

int * ptr

هذا الكود لن يتم تعريفه على انه Identifier لأنه ببساطة لا يتبع قاعدة الIdentifier التي ذكرتها من قبل [a-zA-Z][a-zA-Z0-9]* و هذا لوجود العلامة * و طبقاً لهذه القاعدة فإن الLexer سيعتبر أن ال* علامة ضرب و يعطي لها الToken الخاص بالضرب و هذا لأنه لا يملك قاعدة تحكم الpointer declaration و لكن لو أضفنا قاعدة خاصة بالpointers

[a-zA-Z][a-zA-Z0-9]*[*] و هي تعبر عن وجود العلامة * متبوعة بتعريف الIdentifier و في هذه الحالة سينتج الLexer نتيجة Token مختلف يُعبر عن الpointer ...

لو صبرت حتى الدرس الثالث ستعرف كيف يطبق الCompiler القواعد في التعرف على الPatterns و تفريقها عن الPatterns الأخرى المشابهة لها و هو يستخدم ما يُسمى بال Finite State Machine

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

الفقرة الاولى مجرد تعليق عالماشي .. للانك ذكرت ان الـ lexer يحاول اكتشاف بعض الاخطاء من قبيل 123abc فعلقت بتعليق صغير يعني ..

الفقرة الثانية (السؤال) .. فأنا لم اقصد الـ lexer بل قصدت الـ parser .. و لهذا قلت انه سابق لأوانه.

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

مشكور وماقصرت اناعندي كتاب بس انجليزي

طلب ودي تتكلم عن كيفية بناء symbol tables عن طريق arryوtryوhash tablesو

linked list

وشكراً

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

ما شاء الله

بارك الله فيك يا أخ bashmohandes

ربنا يعلم إنك سبب رئيسي في نهضة المنتديات بسبب نشاطك وسعة اطلاعك وعدم بخلك بما تعرف

جزاك الله خيرا

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

:lol: شكرا أخي :lol:

هذه المشاركة التي كنت أتمناها عن إنشاء لغة برمجة (h)

Me.Thank(You)

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

والله الموضوع فعلا رائع ولكن ليه توقفت فاجئة ؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟

2

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
زوار
This topic is now closed to further replies.

  • يستعرض القسم حالياً   0 members

    لا يوجد أعضاء مسجلين يشاهدون هذه الصفحة .