التجميع الذري Atomic grouping
يسمى بذلك لأن له نفس تأثير القنبلة الذرية حيث أنه بمجرد خروج المحرك من المجموعة الذرية يتم إلغاء جميع أماكن التتبع الخلفي Backtracking التي قام المحرك بتخزينها كأماكن للمطابقات ولكن داخل المجموعة فقط. أي تقوم بإلغاء الأماكن التي ربما يقوم المحرك بعمل backtracking إليها داخل المجموعة عندما يفشل إذا تسببت مطابقة جزء من النم في فشل باقي رموز النمط. ويكتب التجميع الذري هكذا (?>group)
[highlight background=”” color=””]إنتبه إلى أنه يلغي كل الـ backtracking داخل المجموعة وليس خارجها[/highlight]
مثلاً عند تطبيق التجميع الإلتقاطي Capturing group هذا a(bc|b)c على abc أو abcc تحدث مطابقة، لكن عند تطبيق a(?>bc|b)c تحدث مطابقة مع abcc وليس مع abc. لماذا؟
عند تطبيق التجميع الإلتقاطي a(bc|b)c على abc يحدث الآتي:
- تحدث مطابقة a في النمط مع a في النص
- ينتقل المحرك للخيار الأول bc في النمط
- تحدث مطابقة في بين bc في النمط و bc في النص ويخرج المحرك من المجموعة
- الأن انتهى النص ومازال هناك حرف c في النمط لم يتم مطابقته.
- يعرف المحرك بأنه لم تتم مطابقة النمط بالكامل
- يعود المحرك بعمل تتبع خلفي Backtracking بحيث يعود إلى الموقع قبل الخيار الثاني في المجموعة.
- تحدث مطابقة بين b في النمط ومثيبلتها في النص ويخرج الحرك من المجموعة
- تحدث مطابقة بين c في النمط و c في النص
- فتكتمل المطابقة مع abc عند استخدام الخيار الثاني
لكن عند تطبيق التجميع الذري a(?>bc|b)c يحدث الأتي:
- تحدث مطابقة a في النمط مع a في النص
- ينتقل المحرك للخيار الأول bc في النمط
- تحدث مطابقة في بين bc في النمط و bc في النص ويخرج المحرك من المجموعة
- الأن انتهى النص ومازال هناك حرف c في النمط لم يتم مطابقته.
- في الوضع الطبيعي (مثلما حدث في التجميع الإلتقاطي) يفترض أن يعود المحرك قبل الخيار الثاني إذا كان يعرف مكان الـ backtracking
- لكن بما أنه تجميع ذري فلا يعرف المحرك ما هو المكان المفترض الرجوع إليه داخل المجموعة لان التجميع الذري قام بإلغاء كل أماكن الـ Backtracking داخل المجموعة عند الخروج من المجموعة الذرية، وبالتالي لايوجد محاولات أخرى للمحرك ويفشل في مطابقة abc.
تظهر أهمية التجميع الذري عندما يُكتب النمط بشكل يجعل المحرك يأخذ وقتاً طويلاً حتى يكتشف أن النمط لايمكن مطابقته، فهذا يشكل مشكلة كبيرة في آداء البرنامج ويؤدي إلى ما يسمى بالتتبع الخلفي الكارثي catastrophic backtracking، وهنا يمكن الإستفادة من التجميع الذري لتحسين أداء محرك البحث.
فمثلاً إذا أردنا تطبيق النمط \b(integer|insert|in)\b على النص integers (أي بدون التجميع الذري) فإن المحرك يجرب جميع المحاولات والخيارات وبعد مجهود سيكتشف أنه لاتوجد مطابقة. لذلك يمكننا أن نخبر المحرك أنه إذا لم يجد integer متبوعة بحد الكلمة \b يخرج من المطابقة ولا يحاول تجربة الخيارات الأخرى هكذا \b(?>integer|insert|in)\b وبالتالي عندما يتطابق الخيار الأول integer مع الجزء integer في النص سيخرج المحرك من المجموعة مع حذف كل الـ backtrackig ثم يحاول مطابقة \b مع s فيفشل وتتحول عملية المقارنة إلى مقارنة خطية Linear Comparison، وكما نعرف فإن المحرك في المقارنات الخطية لايستخدم التتبع الخلفي وإنما يحاول البدء من جديد من مكان آخر في النص لتطبيق النمط من جديد من هذا الموقع. وباختصار أنا فشلت إذت أبدأ من جديد من مكان آخر.
هناك بعض أساليب التعبيرات المنتظمة التي تعتبر أحد أنواع التجميع الذري. وهي محدادات الكميات الإستحواذية Possessive quantifiers ومجموعات البحث الأمامي Lookahead groups والبحث الخلفي Lookbehind groups. (نتحدث عنهم في موضوعات منفصلة)