الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

إلى خبراء Token

مغلق
بدأه فواز الشمري في 18 أكتوبر 2005 · 29 رد · 5,359 مشاهدة · في لغة C و ++C
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

اخواني الكرام
وددت التعرف عن كيفية تميز الكلمات المحجوزة في محررات الغات
ياريت لو حد لدية فكرة عن هذه الخوارزمية

وماهي ايضا الخوارزمية المتبعة في التحقق اللغوي بحيق يتم التعرف على ان الصيغة خاطئة مثلا صيغى IF
ارجوا تزويدي ببعض المراجع ايضا ولكم جزيل الشكر :(

تم تعديل هذه المشاركة بواسطة مصطفى 36a2 في 5 أبريل 2014 في 18:14 — السبب: add some tags

#2

ممكن توضح شوية ياأخ فواز؟؟؟؟؟!!!!!

Muhammad Allam

Computer Science

@Resource(MappedURL="My Blog" )

#3

أولا, لكي تتعرف على الـ token لا بد ان توجد عندك قواعد معينة في تمييز انواع "الكلمات" الموجودة في النص ..

لكي نوضح أكثر, نسأل أولا ما هو الـ token؟

لنفرض لدينا النص التالي, و هو جزء من كود عادي:

if( var == 2.0f )
{
    doSomething();
}

و لنقل ان ما نريد القيام به هو فقط التعرف على الـ keywords (لن نشغل انفسنا بالأمور الأخرى)

فلنحلل مكونات هذا الكود:

اولا عندنا كلمة if, متبوعة بقوس, متبوعة بكلمة var, متبوعة بعلامتين = متبوعة برقم 2.0f مبتوعة بقوس .... معقوف؟ curly brace او }, متبوع بكلمة doSomething مبتوعة بقوسين متبوع بفاصلة منقوطة و اخيرات يليها قوس معقوف آخر.

يمكننا تمييز مكونات النص الى ثلاث أشياء: كلمات و ارقام و رموز.

مثلا, if و var و doSomething هي كلمات

و 2.0f هو رقم

و الأقواس و الاشارات الرياضية هي رموز.

بقي شيء آخر, و هو المسافات او الـ whitespace و التعليقات comments

لنهمل التعليقات الان, لانك اذا فهمت كيف تعرفنا على الكلمات و الارقام و الرموز .. فستعرف ايضا كيف نتعرف على التعليقات.

ملاحظة: ما احاول شرحه هنا هو ليس بالضرورة الحل الكامل او الأمثل, إنما احاول تبسيط المسألة.

كيف سنتعرف على الـ keywords؟ ممكن ان نقول, بما اننا سنقوم بالتعرف على كل الكلمات الموجودة في النص,فإننا كلما تعرفنا على كلمة, نقوم بمقارنتها بمجموعة كلمات محددة مسبقا (حيث هذه الكلمات هي جميع الـ keywords), و إذا وجدنا ان كلمتنا مساوية لإحدى هذه الكلمات, فسنعرف عندها انها عبارة عن keyword.

طيب, كيف سنتعرف على الكلمات بشكل عام؟

الطريقة اللتي اعرفها (و اللتي اعتقد انها مستخدمة في الـ compilers) هي قرائة النص حرفا حرفا, و تحديد ماذا يمثل كل حرف منها, فمثلا, يمكن القول انك إذا وجدت حرفا ابجديا, فهذا يعني انك في بداية كلمة, و إذا وجدت رقما, فهذا يعني انك في بداية رقم .. و إذا وجدت مسافة, فهذا يعني انك في بداية مساحة بيضاء او whitespace.

فإذا وجدت نفسك في بداية كلمة, فإنك تدخل نفسك في حلقة متواصلة لقراءة كل حروف الكلمة, و عندما تجد ان الكلمة قد انتهت, تقوم بالخروج من هذه الحلفة و العودة الى قرائة حروف النص المراد تحليله.

و كمثال على هذه الحلقة (و هذا المثال اقرب الى psedu-code منه الى كود حقيقي)

while( !doneProcessingText() )
{
    char c = peekNextChar();    

    if( isWordStart( c ) )
    {
        readNextWord();
    }
    else if( isNumberStart( c ) )
    {
        readNextNumber();
    }
    else if( isWhiteSpace( c ) )
    {
        readWhiteSpace();
    }
    else if( isSymbol( c ) )
    {
        readSymbol();
    }
    else
    {
        error("unknown token!");
    }
}

طبعا, لازم نعرف متى تنتهي الكلمة, و لكي نعرف ذلك لا بد ان نعرف ما هي الحروف اللتي ممكن ان تكون تابعة للكلمة, مثلا لو وجدنا

var1=var2+var3;

فهنا توجد ثلاث كلمات و ثلاث رموز,

فأولا تأتي كلمة var1 ثم الرمز = ثم الكلمة var2 ثم الرمز + ثم الكلمة var3 ثم الرمز ;

و يجب علينا ان نكون قادرين على تمييز هذه الرموز حتى بدون وجود اي مسافات تفصلهم, و لمعرفة ذلك, فلا بد لنا من معرفة ما هي "الحروف" اللتي تمثل جزءا من الكلمة, و متى تنتهي الكلمة.

و هذا يعتمد على قواعد اللغة, في لغة السي بلص بلص مثلا, الـ identifier يجب ان يبدأ بـ _ او حرف ابجدي, و يمكن ان يحتوي على حروف و أرقام و _

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

مثلا

Ae3d هي كلمة, و re3 هي كلمة, و t هي كلمة, و 98iuu ليست كلمة! لانها بدأت برقم.

قلكي نقرأ الكلمة, نقوم بتبع جميع الحروف الموجودة, و طالما ان الحرف القادم هو جزء صحيح من الكلمة, نقوم بقرائته كجزء من الكلمة. و متى صادفنا حرفا لا يصلح ان يكون جزءا من الكلمة, فسنعتبر ان الكلمة قد انتهت.

void readNextWord()
{
    char c = peekNextChar();
    while( isAlphabeticalLetter( c ) || isDigit( c ) )
    {
        readNextChar();
        
        c = peekNextChar();
    }    
}

طبعا هكذا نكون قد قرأنا الكلمة, اي, مرننا على كل حروف الكلمة, و عرفنا متى تبدأ و متى تنتهي ..

يبقى السؤال: كيف سنسجل اننا قرأنا هذه الكلمة؟ و كيف سنعرف محتوياتها؟

شخصيا لا اعرف اذا كانت هناك طريقة قياسية لعمل ذلك, لكني في احدى المرات قمت بعمل كائن Token يحتوي على على string يمثل الكلمة, و startIndex يمثل مكان الحرف الأول للكلمة في النص الأصلي.

يعني, ممكن ان نغير العملية او الدالة function اللتي تقوم بقرائة الكلمة, بحيث تقوم بتسجيل مكان الحرف الحالي قبل و بعد القراءة, و من ثم تخزينه في token جديد, و من ثم اضافته الى سلسلة الـ tokens اللتي نقوم بها:

void readNextWord()
{
    int startIndex = getCurrentIndex();
    
    char c = peekNextChar();
    while( isAlphabeticalLetter( c ) || isDigit( c ) )
    {
        readNextChar();
        
        c = peekNextChar();
    }    
    
    int endIndex = getCurrentIndex();
    
    Token word = new Token( WORD_TOKEN, startIndex, endIndex, getOriginalText() );
    addToTokenList( word );
}

و مرة أخرى, هذا الكود "ناقص", بمعنى انه فقط يوضح الخطوط العامة لالية العمل, دون اعطاء الكثير من التفاصيل.

يمكننا في هذه المرحلة ان نقوم باختبار ما اذا كانت هذه الـ token عبارة عن keyword ام لا, و اذا اكتشفنا انها keyword, سنقوم بتسجيل هذا الحدث (عن طريق ارسال رسالة الى محرر النصوص مثلا .. او كيفما يحلو لك), لنضع هذا الكود بعد تسجيل الـ token مباشرة:

    Token word = new Token( WORD_TOKEN, startIndex, wordIndex, getOriginalText() );
    addToTokenList( word );
    
    if( isTokenAKeyword( word ) )
    {
        TellEditorAboutKeywordToken( word );
    }

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

اتمنى يكون الشرح مفهوم بشكل عام ..

فيما يختص بسؤالك:

اقتباس
وماهي ايضا الخوارزمية المتبعة في التحقق اللغوي بحيق يتم التعرف على ان الصيغة خاطئة مثلا صيغى IF

ارجوا تزويدي ببعض المراجع ايضا ولكم جزيل الشكر

فهذا أمر لا زلت اتصارع معه .. ممكن غيري يفيدك فيه.

تم تعديل هذه المشاركة بواسطة hasan_aljudy في 18 أكتوبر 2005 في 17:57

#4

الف الف شكر اخي hasan_aljudy .

المشكلة لدي اخي الكريم اني دخت في معرفة الخوارمية الصحيحة والأسرع في المحررات يعني ما اعرف هل هناك خوارزمية محددة ياريت حد يخبرنا .

طريقتك جيدة وسوف احاول فيها واكرر شكري لك .

بقي بعد ان اتعرف على الكلمة المحجوزة عدد نقاط :

أولا كيف اقوم بعملية الفحص هل من بداية النص المكتوب إلى أخرة أم على سطر سطر أم على كلمة في سطر يعني هنا كيق تتم معالجة البحث عن الكلمات المحجوزة هل لديك فكرة عنها .

الرسالة إلى المحرر كيف تم إخبار المحرر ببداء تلوين الكلمة يعني هل اقوم بمعرفة الموقع الأول ثم موقع اخر الكلمة ثم اقوم بالتضليل ثم اقوم بتغير اللون .(انا استحدم RitchTextBox ) في vb.net .

ام انه هناك كريقة ما ترسل للنافذة مثل SendMessage للنافذة . لأن التضليل على الكلمة يضهر لون التضليل على الكلمة ثم تغير ثم إلغاء التضليل وهذا يسبب نوع من الإهتزاز . شكرا لك في النهاية وفي انتضار ردك والأخوان

#5
اقتباس
بقي بعد ان اتعرف على الكلمة المحجوزة عدد نقاط :

أولا كيف اقوم بعملية الفحص هل من بداية النص المكتوب إلى أخرة أم على سطر سطر أم على كلمة في سطر يعني هنا كيق تتم معالجة البحث عن الكلمات المحجوزة هل لديك فكرة عنها .

اذا كنت تقصد عملية الـ tokenization فتقوم بقراءة حروف النص حرفا حرفا.

البحث عن الكلمات المحجوزة, يمكن ببساطة وضع جميع الكلمات في array و مقارنة كلمتك بعناصر الـ array .. او يمكن استخدام hashtable تكون فيه الكلمات هي الـ key و اعتقد هذا سيكون أسرع في البحث لكن لست متأكدا من ذلك.

اقتباس
الرسالة إلى المحرر كيف تم إخبار المحرر ببداء تلوين الكلمة يعني هل اقوم بمعرفة الموقع الأول ثم موقع اخر الكلمة ثم اقوم بالتضليل ثم اقوم بتغير اللون .(انا استحدم RitchTextBox ) في vb.net .

هذا يعتمد على تفاصيل عمل المحرر, يعني الـ implementation details, و في هذا الجزء لا استطيع افادتك .. لاني لا اعرف شي في الـ vb.net و فضلا عن ذلك, لا اعرف شيء في الـ mfc ولا win32 api

#6

لا افهم سوألك الاخير انا سبق لى وكتبت محرر ولكن كان لا يدعم عملية التلوين والتوكين

اعد صياغة السوال يمكن اقدر اساعدك

_____________________________

C Language && Windwos_API

_____________________________

#7

اكرر شكري لك اخي hasan_aljudy :

لكن هل المعالجة تكون على مستوى النص بالكامل يعني مثلا لو كان لدي عشرون سطر

وانا واقف على السطر العشرين في الموقع 2 مثلا وقمت بكتابة حرف ما وليكن a في هذه الحالة هل اقوم باستدعاء tokenization عند كل ضغطة زر على الكيبور وفي هذه الحالة هل يقوم الـ tokenization بالبحث من بداية النص من السطر الأول إلى السطر العشرين ثم يقوم بالتلوين وكذلك تميز الكلمات المحجوزة أم ان tokenization تقوم بالبحث في السطر العشرين فقط من بدايتة إلى موقع المؤشر ثم تقوم بتلوين السطر هذا فقط وتحديثة .

اقصد من هذا هوا الية استدعاء الـ tokenization متى تتم وهل يتم جعلها تعالج النص من جديد , إذا كان ذلك كيف تعالج مشكلة البطئء في هذه الحالة يعني قد يكون لدي 3000 الف سطر فهل اقوم بعمعالجة الثلاثة الألف بمجرد ضغط زر في الكيبورد . أتمنا ان يكون القصد واضح .

بالنسبة للسؤال الأخير :

مثلا معادلة التلوين الي انا فكرت فيها هي لو كتبت

if (b==20)
{
b =20;
}

أوجدت لي الـ tokenization موقع الـ if موقع الحرف i ونهاية الحرف f وبالتالي هنا ميزت الن الكلمة if هي كلمة محجوزة كيف اقوم بإخبار المحرر اي Ritch بأن تقوم بتلويم الكلمة if بالون الأزرق

الفكرة التي لدي هي ان اقوم بتضليل الكلمة if بفرض اني اعرف موقع الكلمة بحيث يكون التضليل على الكلمة بالضبط ثم اقوم بتلوين الكلمة مثلا بالون الأزرق ثم اقوم بإلغاء التضليل وإادة موقع العلامة بعد كلمة if

المشكلة الناتجة من هذه الحالة هوا ان التضليل يعمل اهتزاز في حال وجد اكثر من عملية تلوين في النافذة يعني يضهر ويختفي في لمح البصر وهذا يسبب نوع من الإهتزاز .

السؤال هوا كيف يتم معالجة التلوين يعني اخبارالنافذة بتلوين الكلمة المحددة , بدون استحدام التضليل على الكلمة حتى اتفادى مشكلة الإهتزاز في التضليل .

اخي hasan_aljudy لدي مجموعة من الأمثلة لكن باستخدام vc++ لكن لأسف لم افهم منها شي لعدم خبرتي في هذه الغة اي vc++ فإذا قمت بوضع الأمثلة لك لتقوم بداستها وهي صغيرة وليست كبيرة وهي توضح مفهوم هذه الفكرة . فهل اجد لديك الوقت لذلك .

من خلال التعليق هذا اتمنا خي hamada hassan ali ان تكون فهمت القصد من السؤال الأخير

شكرا لك اخي eng_3llam اتمنا ان تكون فهمت القصد من الأسئلة من خلال التعليقات السابقة .

في انتضار الرد :unsure:

#8

أها .. اذا كنت تكتب باستمرار و الملف مفتوح, في هذه الحالة لا تحتاج لعمل scan إلا للأجزاء اللتي تغيرت ..

لو عندك مثلا 20 token و قمت بتحرير النص فتخربط الـ token رقم 12 و 13, تقوم بمسح النص من ما بعد الـ token رقم 11 الى بداية الـ token رقم 14 .. بس طبعا العملية اكثر تعقيدا من ذلك, لانك لما تضيف نص جديد في وسط النص القديم, فإن الـ offsets كلها ستتخربط .. يعني الاماكن السابقة للـ tokens ستتخربط, سيكون عليك معرفة اين اضفت الحرف الجديد (او الكلمة الجديدة), وان تعرف على اي من الـ tokens سيؤثر هذا التغيير و من ثم عليك ان تقوم بتغيير كل الـ tokens في النص لتعكس التغييرات الجديدة.

أعتذر لان كلامي عام جدا و لا يوجد به الكثير من التفاصيل, و هذا لأنني لم اتعامل مع هذه القضية من قبل بشكل جاد .. عندما كنت العب معeclipse كانت هذه العملية تعالج من قبل البرنامج نفسه.

بالنسبة للـ RichEdit فكما اسلفت, ليست لدي ادنى معلومة عنه. بس حاول تشوف اي documentation له .. على الـ msdn مثلا!

تم تعديل هذه المشاركة بواسطة hasan_aljudy في 22 أكتوبر 2005 في 21:43

#9

عزيزى فواز الشمري

ما الادوات الذى ستستخدمها لبناء المحرر وانا عندى استعداد اساعدك فى تصميمه

_____________________________

C Language && Windwos_API

_____________________________

#10
اقتباس
أوجدت لي الـ tokenization موقع الـ if موقع الحرف i ونهاية الحرف f وبالتالي هنا ميزت الن الكلمة if هي كلمة محجوزة كيف اقوم بإخبار المحرر اي Ritch بأن تقوم بتلويم الكلمة if بالون الأزرق

الفكرة التي لدي هي ان اقوم بتضليل الكلمة if بفرض اني اعرف موقع الكلمة بحيث يكون التضليل على الكلمة بالضبط ثم اقوم بتلوين الكلمة مثلا بالون الأزرق ثم اقوم بإلغاء التضليل وإادة موقع العلامة بعد كلمة if

المشكلة الناتجة من هذه الحالة هوا ان التضليل يعمل اهتزاز في حال وجد اكثر من عملية تلوين في النافذة يعني يضهر ويختفي في لمح البصر وهذا يسبب نوع من الإهتزاز .

السؤال هوا كيف يتم معالجة التلوين يعني اخبارالنافذة بتلوين الكلمة المحددة , بدون استحدام التضليل على الكلمة حتى اتفادى مشكلة الإهتزاز في التضليل .

اخي انا واجهتني نفس المشكلة في بناء محرر ، ويمكن أن أعطيك بعض الكود الذي يفيدك في فجوال سي++ ، لكن الطريقة بالمختصر هو أن تقوم بعمل freeze update أو disable update لل rich edit control قبل عملية ال select ومن ثم فع ماتريد وبعدها تقوم بresume update ، وهي تعمل بشكل جيد ، ولكنها بطيئة ..

قمت ببناء محرر آخر سريع للسي ، ولكن لا يعتمد على أي control وهو أفضل اختيار . تجد أن كل المحررات مثل محرر فجوال ستديو وغيرها لا يعتمد على أي كونترول في وندوز .. هذا افضل لكنها اصعب حيث يجب أن تقوم لوحدك بكتابة كود للكتابة والمسح والاختيار وال drag&drop و و و و ..

بالنسبة للتعرف على صيغة if هل هي صحيحة ام لا لغويا فاستخدم parsing وإذا أردت كتابته لوحدك فاستخدم top-down parsing او يمكنك استخدام ادوات جاهزة تنتج كود لك مثل yacc حيث تعطيها ال grammer وتعطيك كود جاهز بالسي يقوم بعملية ال parsing ...

بالنسبة لل tokenization فيمكن مثل ماشرحة الأخوة ان تكتب كود خاص فيه يعمل ال tokenization وهو عبارة عن كود يقرأ السلسلة ويحولها إلى أقسام مفهومة ، يمكنك كتابته بنفسك إذا احببت وهو سهل أو يمكن استخدام أداة flex وهو الأفضل لأنه سوف يقوم بانتاج كود جاهز لك وسريع من أجل عملية tokenization ماعليك فقط هو أن تخبره بال regular expressions لكل token ..

طبعا كما ذكر الأخوة إذا أردت تلوين الكود فما عليك هو فقط أن تلون السطر الذي يكتب فيه المستخدم من أوله إلى آخر كلمة (وليس إلى الكلمة التي يكتب عندها الآن) ، طبعا هذا صحيح في اللغات التي لا تحتوي على block comment . أي تعمل لمحررات ال basic و assembly ولكن لا تعمل للدلفي أو سي أو جافا ، لأنها تحتوي على block comment .. وهذا أمر صعب ويحتوي على عدة خوارزميات .. أنا قد بنيت محرر للسي في دلفي ومحرر للسي في فجوال سي ، وكل واحد استخدمت فيه خوارزمية اخرى ولكن افضل الذي صنعتها في الفجوال سي ، ويمكن أن أشرحها بطريقة مختصرة ..

يمكن أن أشرح لاحقا عن الخوارزمية إذا أحببت ..

تم تعديل هذه المشاركة بواسطة هاني الأتاسي في 21 أكتوبر 2005 في 19:49

Coding on the Cloud and for the Cloud!

My Blog

#11

اخي الفاضل hasan_aljudy عاجز فعلا عن شكرا لكن بارك الله فيك على تفاعلك .

اخي حمادة حسان الفكرة هي اني استخدم Ritch Text Box في عمل المحرر ومن هنا ترددت كثير قبل ان اتحذ القرار في استخدامها .

اخي هاني بارك الله فيك افرحتني بردك والمعلومات التي اخبرت بها شكرا لك .

بالنسبة لبناء كنترول من جديد لتحرير النصوص اخي الكريم فكرت بذلك لكن المشكلة اني ابحث عن حد يشرح لي كيف ذلك وما هي الأساسيات لعملها . ومن هنا خفت ان ادخل نفسي في مجال طويل واهمل الأساس مع علمي انها ستكون اسرع ان استخدمت الخوارزميات المطلوبة في بنا المحرر بدل ritch

اكثر فرحي ايضا بـ parsing أو المعرب ,

ذكرت مجموعة من الأدوات التي قلت استخدمها وهي تعطيني الكود وتساعدني في عمل القواعد و Token ياريت لو تضع لي روابط هذه الأدوات حتى اراها .

وممكن كمان نتساعد في طريقة التعامل مع القاعدة التي نتجت يعني كيف استخدمها . لأني في هذه الحالة سوف افهم الفكرة واحولها بكود vb.net لأني شاهدت برنامج شارب دفلوبر وهوا مفتوح المصدر طبعا لم افهم منه شيئ لكن الجزء المهم انه استخدم القواعد الأساسية في ملف بإمتداد غريب ثم قام باستدعاء الملف والتنقل فية ليقراء منه القواعد .وهوا معمول بـ C#.net.

بالنسبة للخوارزميات اخي هاني انا منتظرك (بفارغ الصبر) :rolleyes:

ان شاء الله كلنا بالتعاون مع بعض سنجد حلول للمشاكل التي قد تواجهنا .

نسيت ملاحضة اني قواعد اللمحرر تحتوي على التعليق الكتلي block comment وهذه فعلا مدوختني في معالجتها وما وجت لها خوارزمية . حاولت فيها لكن البطئ كان مصاحب لها بشكل كبير .

في الإنتضار :lol:

#12

مشكور اخى ولكن لم افهم بالظبط ماذا تريد

تم تعديل هذه المشاركة بواسطة hamada hassan ali في 22 أكتوبر 2005 في 16:21

_____________________________

C Language && Windwos_API

_____________________________

#13

بس ما تكون انتضرت تشذير :P

اقتباس
بالنسبة لبناء كنترول من جديد لتحرير النصوص اخي الكريم فكرت بذلك لكن المشكلة اني ابحث عن حد يشرح لي كيف ذلك وما هي الأساسيات لعملها . ومن هنا خفت ان ادخل نفسي في مجال طويل واهمل الأساس مع علمي انها ستكون اسرع ان استخدمت الخوارزميات المطلوبة في بنا المحرر بدل ritch

هذا يعتمد على المشروع فهل تحب أن يكون لديك تحكم كامل بالمحرر فعليك ان تكتبه بنفسك والأمر ليس صعب لكن عليك ان تلم بشكل كامل بتوابع رسم الأحرف والmessages من اجل دخل الكبيورد والفارة . وأيضا ال scrolling و إذا كنت تريد دعم العربية او لغات غير الأجنبية فيجب ان تلم بال Uniscripe .. :)

يعني بالمختصر هذا الشئ يرجع إلى حاجتك .. أنا بفكري أصنع محرر عام لجميع اللغات ويدعم اللغات الأجنبية وخلافه .

اقتباس
ذكرت مجموعة من الأدوات التي قلت استخدمها وهي تعطيني الكود وتساعدني في عمل القواعد و Token ياريت لو تضع لي روابط هذه الأدوات حتى اراها .

http://dinosaur.compilertools.net/

يمكنك القرائة عنها وتنزيلها من الموقع السابق ، أيضا مرة وجدت أحد صنع flex and yacc للسي# .. :( سبقني لها كنت اريد كتابتها بنفسي ، ولكني لم أجرب استخدامها وجدتها باستخدام محركات البحث ولا أعرف أين هي الآن ..ولكن لا أنصحك باستخدام التحليل اللغوي من أجل التلوين ، فالأمر أسهل من أنك تستخدمها فيه .. كنت أعتقد أنك تريدها من أجل معرفة الأخطاء اثناء الكتابة مثل وضع علامة حمراء تحت قوس ناقس وهكذا ..

بالنسبة لل block comment .. فهذه هي الخوارزمي فقد كتبتها لتوي وأرجو تنبيهي إذا فيها أخطاء :

1. Editing outside comment block
    1.2 if you wrote an open comment (like /*)
         1.2.1 Scan from the current line to the bottom of the file
               altering the current commenting states (not really until 
               the end of the file, read suggestions below)

2. Editing inside comment block
    2.1 If you wrote a close comment
         2.1.1 Scan from the beginning of the block until the end of the file 
               altering the comments states
    2.2 If you break the comment structure of openning (something like putting 
               space between /*)
         2.2.1 This is similar to 1.2.1 above
    2.3 If you break the comment structure of end block (space between or delete */)
         2.3.1 Extend the current block scanning until the end of the file


Suggestions:

- You don't have to scan each time until the end of the file, you can stop if 
  encounter one of the following cases:
    1- You found an end comment token that matches the current block comment
    2- You found a start comment token that matches the next block comment, this 
       means that you return back to your current comments pattern and no need
       for furthur processing

- Keep a list of all comment blocks (each comment block is categorized by: 
    - start (line, column)
    - end (line, column)
- The list is sorted by line so you can find if you are inside or outside a comment
  block quickly using binary search.
- Make sure to update line and column information of all comments when you edit
  the file, something like inserting a new line should shift comments down by 1.

- Instead of keeping a list of comment blocks, an easier way to do this is to 
  have an array of integers as big as the number of lines in your file. The
  contents of the array is the following:
    1- 0: the line doesn't have comment block, or it's not inside one
    2- MinInt: the line is inside a comment block
    3- i where i > 0: the line has a start comment block token at the index i
    4- j where j < 0: the line has an end comment block token at the index -1*j

- What about multiple block comments on the same line:
    1- It's better to treat them as regular tokens, because they don't spawn
       multiple lines, so you detect and color them in your draw routine.
    2- Once you find out in your scanning that a block comment spawn to the next line
       then it's considered a block comment and follows the descussions above.

- What about strings that spawn into multiple lines? It could be that a string spawn
  two lines and the second line has (/*). I know a good strategy regarding this, but
  if you don't want it I won't mention it for now. :)
    basically this type of string is like a block string, and you can think of it same as 
a block comment. But, since you have block comment and a block string then 
you need to apply a slightly modified abroch that the one above :)

أيضا لا تنسى موضوع pasting أو cut .. :wacko: فالpasting وال cut قد يغيران من بنية ال block comments .. B)

تم تعديل هذه المشاركة بواسطة هاني الأتاسي في 22 أكتوبر 2005 في 23:48

Coding on the Cloud and for the Cloud!

My Blog

#14

سوف أتبع وضع الخوارزمية من أجل كل الحالات block comment and block string أو اي token يمتد على أكثر من سطر .

الفكرة هنا تسهل إذا فكرنا بها أن ال token يمتد من سطر إلى آخر إذا كان هناك رمز وهمي في آخر السطر يخبر الكود أن الtoken يطبق على السطر التالي وهكذا . طبعا هذا الشئ ملاحظ في block string حيث يتم استخدام الرمز \ من أجل هذا في كود السي .

انظر المثال التالي:

0: some code;                                   [No token extension]
1: other code;                                  [No token extension]
2:                                              [No token extension]
3: some code /* block comment block comment     [Block Comment extension]
4: block comment block comment block comment    [Block Comment extension]
5: block comment block comment */ other code    [No token extension]
6:                                              [No token extension]
7: some code some code "block string block \    [Block String extension]
8: block string block string block string  \    [Block String extension]
9: block string block string ";                 [No token extension]

الآن لو أردنا تلوين السطر رقم 5 من بدايته لعرفنا أنه يجب أن يبدأ بcomment لأن السطر الذي قبله ينتهي بالعلامة block comment extension .. وبالتالي نقوم بالتلوين من اوله حتى نجد رمز نهاية ال comment block باللون الذي يدل على comment .

إذا اتبعت هذه الطريقة بالتلوين فلن تحتاج إلى تتبع بشكل منفصل بداية ونهاية كل comment او string .. وما عليك سوى تعبئة المصفوفة في اليمين ب extension code أثناء عملية الرسم ذاتها للشاشة . والموضوع سهل لأنك تعرف حالة كل سطر من اوله من الحالة النهائية للسطر السابق .

لا أدري لماذا تكلمت كثيرا عن هذا الموضوع :D حيث لا أعتقد انه سوف يفيدك كثيرا إذا استخدمت Richedit control .. ولكن قد يفيد بعض الشئ :)

تم تعديل هذه المشاركة بواسطة هاني الأتاسي في 23 أكتوبر 2005 في 03:40

Coding on the Cloud and for the Cloud!

My Blog

#15

ما دخل الأسطر بالموضوع؟

طبعا انا جاهل بالـ RichEditControl .. و لكن نظريا المفروض ما يكون هناك مشكلة مع الأسطر الجديدة .. لانها مجرد حرف, اليس كذلك؟

بالمناسبة, قواعد الـ tokens ليس شرطا دائما ان تكون regular expression, في لغة D هناك nested comments يعني

/+
this is a comment
    /+
           this is a comment too
    +/
this is still part of the comment

this is now the end of this nested comment block:
+/
#16

حسان ، لا أدري إن كنت أحب هذه ال nested comments .. فمن تعريف الcomment يجب أن تلغي أي شئ حتى نهايتها ، وبالتالي يجب أن تلغي الرمز /+ الذي يفتح الinner comment ومنه لمذا يعدون ال comment الدخلي عبارة عن comment ..

لا أعرف!! أعتقد هذا ضعف باللغة نفسها ..

لكن مادخل ال regualar expression هنا ، في هذه الحالة لا تستطيع فحص ال كتلة كلها ك regular expression واحد لكن سوف تفحص البداية والنهاية بشكل منفصل وعلى ال parser ان يحدد أيهما هي comment خارجي وايهما داخلي وهكذا ..

Coding on the Cloud and for the Cloud!

My Blog

#17

أقصد ان اداة مثل flex قد لا تستطيع إنشاء كود لتفسير هذه الـ token لأنه لا يمكن تعريفها كـ regular expression (مع العلم اني لم اتعامل ابدا مع هذه الادوات, و لكن من كلامك السابق استنتجب بأن هذه الأدوات تعتمد على الـ regular expressions لانشاء كود lexer)

الـ nested comment مفيدة جدا لانها تمكنك من تحويل جزء من الكود او comment a part of the code حتى لو كان هذا الجزء يحتوي في داخله على comments!

ملاحظة: اسمي حسن, مش حسان!!!!

تم تعديل هذه المشاركة بواسطة hasan_aljudy في 23 أكتوبر 2005 في 03:57

#18

بالمناسبة صديق لي دلني على هذه الأداة

http://www.devincook.com/goldparser/

ويمكن استخدامها ك flex and yacc في سي# وغيرها :)

Coding on the Cloud and for the Cloud!

My Blog

#19

شكرا للجميع اخي hasan_aljudy و hamada hassan ali واستاذي العزيز هاني .

وودت ان اعلق قبل ان اقراء الموضوع حتى أتمعن في الردود :blink: لكن على عجالة سوف اوضح التالي :

تصميم المحرر باستخدام RitchText وسوف استخدم دوال Api لمحاولة التعامل مع هذا الكائن في حال قصرة او احتياجي لتنفيذ عملية ما على الرغم من ان .net اصبح مريح فعلاً وسيوفر لي العديد من الخدمات التي احتاجها .

بالنسبة لخوارزمية التعليق سوف اقوم بقرائتها ولكن في حال النسخ واللصق سوف احتاج في هذه الحالة ان اراقب رسائل RitchText لمعرفة هل الرسالة الحالية هي عبارة عن لصق . وكنت حاولت من قبل ان اعرف ذلك لكن للأسف نجحت معي في textbox اما RitchText لم تنفع (معرفة متى يتم اللصق على النافذة) .

بالنسبة للقواعد :

انا اود فعلاً من المحرر ان يقوم بعمل فحص لحضة التحرير حتى يضهر الأخطاء كأن يعمل خط أحمر وغيرة . ويضهر نوع الخطأ وهذا كلة اعتقد انه يجب ان يكون هناك مدقق لغوي للقواعد الغوية حتى يتم التعرف على الخط أثناء التحرير كما هوا حاصل في محرر .net

سوف اقراء الردود ثم اعلق مرة اخرى :lol:

#20

في بداية الكلام اشكر اخي هاني جزيل الشكر فقد عمل لي قفزة في المعلومات التي كنت ابحث عنها .

اولا token

نحن تحدثنا في المشاركات عن كيفية استخراج الـ Token ولفكرة الحمد الله وصلت لكن بقيى هناك بعض الأسئلة التي تراودني :

في حال بناء ال Token ماهوا الجدول الخاص ببنائها يعني هل اقوم بأخذ الكلمة أو الرمز ثم عنوان موقعة أم ماذا .

وفي حال قمت ببناء المحرر بدون استخدام tichtext هل تكون نفس الخطوات .

ام انه توضع الـ Token في مصفوفة تحوي على العناوين للكمات مثلا من بداية الموقع وإلى النهاية

اخي هاني اتمنا ان توضح بإسهاب عن هذه النقطة . والمشاكل التي تتمثل في تغير مواقع الـ Token مثلا لو إضفت كلمة ما في نصف المحرر فإن مواقع الـToken سوف تتغير وبذلك سوف أحتاج إلى إعادة بناء الـ Token من جديد . كيف الحل في هذه الحالة .

ياريت لو اجد طريقة بناء المحرر من الصفر كيف ذلك .

القواعد الغوية :

مثلا ليكن لدي هذه القاعدة

<statment> ::= If <Statment> Then <Statment>

هذا النوع من الصيغ في بناء القواعد اللغوية بماذا يعرف اي ماهوا وهل هناك صيغ اخرى تتبع في بناء القواعد اللغوية .

ثم كيف لي ان اعرف او اتعامل مع هذه الصيغة بنفسي يعني :

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

من خلال قراءتي وجدت مسمى (بناء شجرة المعرب Parser) كيف تم بنائها والتامل معها .

في الإنتضار :wacko:

#21

السلام عليكم

في البداية احب ان اشكر جميع الاخوة الذين شاركوا في الموضوع

بالنسبة للRich Text Box لا اعتقد ان هناك امكانية لعمل محرر بواسطته يضاهي محررات لغات البرمجة من حيث السرعة .. لاني قمت بعمل محرر بواسطة هذه الاداة واعتقد اني وصلت للنهاية معها بدون ان احقق الهدف المنشود ...

المشكلة معي ومع فواز اننا مبرمجين للفيجيوال بيسك دوت نت :D وبتعرفوا كل الامثلة التي تاخذ هذا الموضوع علي محمل الجد .. يعني تقوم بعمل محرر من الصفر معمولة بلغة السي

فارجوا ان يتكرم احد الاخوة باعطائنا الفكرة عن كيفية الرسم ومن ثم استعادة ما تم كتابتة علي userControl جديد

ارفقت مثال حصلت علية من الانترنت يقوم بعمل محرر من الصفر ولكن المبرمج صاحب الكود قام بعمل اضافات كثيرة ..

اذا احد الاخوة مبرمجين السي لدية وقت ارجوا ان يقوم بتنزيل المثال واعادة صياغتة بابسط طريقة ممكنة حتي يتاح لنا دراستة واعادة تحويلة للفيجيوال بيسك ...

تحياتي ...

wp.rar

#22
اقتباس
فارجوا ان يتكرم احد الاخوة باعطائنا الفكرة عن كيفية الرسم ومن ثم استعادة ما تم كتابتة علي userControl جديد

شوف مثلا :

/index.php?showtopic=79710

قدم بعض الاخوة اكثر من حل .. ممكن تفيدك .

لكن بما انك قلت ان rich edit غير عملية ,,, فاريد ان اقول حل ممكن ينفع .

انشاء RECT .

انشاء caret (مؤشر يومض )

تحريك هذا المؤشر .

تفعيل الازرار ( END -HOME - .... )

واخيرا حفظ ما بداخل هذا RECT .

وقد عملت مثال مشابه .... صغير .

اعتقد هذه الطريقة هي المستخدمة في الورد ... حيث انهم لايستخدمون rich edi :)

....................

حرفنا الموضوع عن اتجاهه:)

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#23

شكرا اخي علي الرد

المشكلة ليست في الرسم المشكلة تكمن في استعادة ما تم رسمة

مثلا هل نخزن الحروف في مصفوفا واذا نعم هل هذه في الطريقة المثلي وام لا

بالنسبة لكونا خرجنا عن الموضوع .. اظن اننا ما زلنا في نفس الموضوع ..

#24
اقتباس
ارفقت مثال حصلت علية من الانترنت يقوم بعمل محرر من الصفر ولكن المبرمج صاحب الكود قام بعمل اضافات كثيرة ..

اذا احد الاخوة مبرمجين السي لدية وقت ارجوا ان يقوم بتنزيل المثال واعادة صياغتة بابسط طريقة ممكنة حتي يتاح لنا دراستة واعادة تحويلة للفيجيوال بيسك ...

وينــــــــــــــــــــــكم يا شبــــــــــــــــــــــــــــاب

#25

تعليقا على المشاركة 21

المحررات يمكن بناءها من لغة الفيجوال بيسك

مش عارف كل الناس مش بتحب فيجوال بيسك ليه زيه زى اى لغة

استخدم الاداة TEXTBOX واجعلها تبع خاصية MULTILINE

ممكن تريحك اكتر من RETICH TEXT BOX

_____________________________

C Language && Windwos_API

_____________________________

هذا الموضوع مغلق.

مواضيع مشابهة