parsing - lexers vs موزعي




antlr pygments (5)

هل اللوغارون والمحللون يختلفون نظريا؟

يبدو من المألوف أن نكره التعبيرات العادية: ترميز الرعب ، آخر بلوق وظيفة .

ومع ذلك ، فإن الأدوات الشعبية القائمة على lexing: pygments أو geshi أو prettify ، تستخدم جميعها التعبيرات العادية. يبدو أنهم يقررون أي شيء ...

متى يتم ذلك بما يكفي ، متى تحتاج إلى EBNF؟

هل استخدم أي شخص الرموز المميزة التي تنتجها هذه اللغو مع مولدات محلل البيسون أو antlr؟


Answers

للإجابة على السؤال كما هو مطلوب (دون تكرار ما يبدو في إجابات أخرى)

لا يختلف Lexers والمحللون بشكل كبير ، كما هو مقترح في الإجابة المقبولة. كلاهما يعتمدان على شكليات لغة بسيطة: اللغات العادية للكنيسة ، وغالبًا ما تكون لغات خالية من السياق (CF) للمحللين. كلاهما مرتبطان بنماذج حسابية بسيطة إلى حد ما ، و automaton الحالة المحدودة و automaton push-down automaton. اللغات العادية هي حالة خاصة من اللغات الخالية من السياق ، بحيث يمكن إنتاج اللّغات باستخدام تكنولوجيا CF أكثر تعقيدًا إلى حد ما. ولكنها ليست فكرة جيدة لسببين على الأقل.

النقطة الأساسية في البرمجة هي أنه يجب أن يكون عنصر النظام مع التكنولوجيا الأكثر ملاءمة ، بحيث يسهل إنتاجه وفهمه وصيانته. لا ينبغي أن تكون التكنولوجيا مبالغة (باستخدام تقنيات أكثر تعقيدا وتكلفة من اللازم) ، ولا ينبغي أن تكون في حدود قوتها ، مما يتطلب تقاطعات تقنية لتحقيق الهدف المنشود.

هذا هو السبب في "يبدو من المألوف أن نكره التعبيرات العادية". على الرغم من أنهم يستطيعون فعل الكثير ، إلا أنهم في بعض الأحيان يحتاجون إلى ترميز غير قابل للقراءة من أجل تحقيقه ، ناهيك عن حقيقة أن العديد من الامتدادات والقيود في التنفيذ تقلل إلى حد ما من بساطتها النظرية. لا تقوم Lexs عادة بذلك ، وعادة ما تكون تقنية بسيطة وفعالة ومناسبة لتحليل الرمز المميز. استخدام محلل CF للرمز سيكون مبالغة ، على الرغم من أنه من الممكن.

هناك سبب آخر لعدم استخدام شكليات CF للقوائم اللغوية ، وهو أنه قد يكون من المغري استخدام قوة CF الكاملة. لكن هذا قد يزيد من المشاكل الهيكلية فيما يتعلق بقراءة البرامج.

من الناحية الأساسية ، فإن معظم بنية نص البرنامج ، والتي يتم استخراج المعنى منها ، هي بنية شجرية. يعبر عن كيفية إنشاء جملة الجملة (البرنامج) من قواعد بناء الجملة. علم الدلالة مشتق من التقنيات التركيبية (الشبيهة بالمظهر الموجه رياضياً) من الطريقة التي تتكون بها قواعد التركيب لبناء شجرة التحليل. ومن ثم فإن بنية الشجرة ضرورية. لا يتم تغيير حقيقة أن الرموز المميزة مع lexer ذو مجموعة عادية يغير الوضع ، لأن الترجمات CF التي تتكون بشكل منتظم لا تزال تعطي CF (أنا أتحدث بشكل كبير جدًا عن محولات الطاقة العادية ، التي تحول تيارًا من الأحرف إلى تيار من الرموز المميزة).

ومع ذلك ، فإن التليف الكيسي المكوّن بالـ CF (عبر محولات طاقة CF ... آسف للرياضيات) ، لا يعطينا بالضرورة الـ CF ، وقد يجعل الأشياء أكثر عمومية ، لكن أقل قابلية للتطبيق عملياً. لذلك CF ليست الأداة المناسبة للأحبار ، على الرغم من أنه يمكن استخدامها.

واحد من الاختلافات الرئيسية بين العادية و CF هو أن اللغات العادية (والمحولات) يؤلف بشكل جيد للغاية مع أي شكلية تقريبا بطرق مختلفة ، في حين أن اللغات CF (والمحولات) لا ، حتى مع أنفسهم (مع بعض الاستثناءات).

(لاحظ أن المحولات العادية قد يكون لها استخدامات أخرى ، مثل إضفاء الطابع الرسمي على بعض تقنيات معالجة الأخطاء في بناء الجملة.)

BNF هو مجرد بناء جملة محددة لتقديم قواعد النحو CF.

EBNF هو السكر النحوي ل BNF ، وذلك باستخدام مرافق التدوين المنتظم لإعطاء نسخة مزعجة من القواعد النحوية BNF. يمكن دائما أن تتحول إلى BNF نقية مكافئة.

ومع ذلك ، غالباً ما يستخدم الترميز المنتظم في EBNF فقط للتأكيد على هذه الأجزاء من التركيب اللغوي التي تتوافق مع بنية العناصر المعجمية ، ويجب أن يتم التعرف عليها مع اللويدر ، في حين يتم عرض الباقي في BNF مباشرة. لكنها ليست قاعدة مطلقة.

لتلخيص ، يتم تحليل البنية الأبسط للرمز بشكل أفضل باستخدام تقنية أبسط من اللغات العادية ، في حين يتم التعامل بشكل أفضل مع البنية الموجهة للأشجار للغة (بناء جملة البرنامج) من خلال قواعد النحو CF.

أود أن أقترح أيضا في الإجابة على AHR .

لكن هذا يترك السؤال مفتوحًا: لماذا الأشجار؟

الأشجار هي أساس جيد لتحديد بناء الجملة لأن

  • يعطون بنية بسيطة للنص

  • هناك ملائمة كبيرة لربط الدلالات مع النص على أساس ذلك الهيكل ، مع تكنولوجيا مفهومة جيدا رياضيا (التركيبية عبر الأشكال المتشابهة) ، كما هو مبين أعلاه. إنها أداة جبرية أساسية لتحديد دلالات الأشكال الشكلية الرياضية.

ومن ثم فهو تمثيل وسيط جيد ، كما هو موضح في نجاح شجرة مجردة (AST). لاحظ أن AST تختلف في الغالب عن شجرة التحليل لأن تقنية التحليل المستخدمة من قبل العديد من المحترفين (مثل LL أو LR) لا تنطبق إلا على مجموعة فرعية من القواعد اللغوية CF ، مما يؤدي إلى إجبار عمليات النحوص النحوية التي يتم تصحيحها لاحقًا في AST. يمكن تجنب ذلك بتكنولوجيا تحليل أكثر عمومية (تعتمد على البرمجة الديناميكية) التي تقبل أي قواعد CF.

بيان حول حقيقة أن لغات البرمجة حساسة للسياق (CS) بدلاً من CF هي تعسفية وقابلة للنزاع.

تكمن المشكلة في أن الفصل بين التركيب اللغوي ودلالات الدلالة أمر عشوائي. قد يُنظر إلى التحقق من الإعلانات أو اتفاقية النوع على أنها جزء من البنية ، أو جزء من علم الدلالة. وينطبق الشيء نفسه على الجندر والاتفاق الرقم باللغات الطبيعية. ولكن هناك لغات طبيعية حيث يعتمد الاتفاق التعددي على المعنى الدلالي الفعلي للكلمات ، بحيث لا تتناسب بشكل جيد مع التركيب اللغوي.

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

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


هناك عدد من الأسباب التي من المفترض أن يتم فصل جزء التحليل من المترجم إلى تحليل معجمية وتحليل تحليل (بناء الجملة) مراحل.

  1. بساطة التصميم هي أهم الاعتبارات. غالباً ما يسمح لنا الفصل بين التحليل المعجمى والنحوي بتبسيط واحدة على الأقل من هذه المهام. على سبيل المثال ، محلل كان عليه التعامل مع التعليقات والمساحة البيضاء كوحدات تركيبية. أكثر تعقيدا بكثير من تلك التي يمكن أن نفترض التعليقات والمساحة البيضاء قد تم إزالتها بالفعل من قبل محلل المعجمية. إذا كنا نصمم لغة جديدة ، فإن فصل المخاوف المعجمية والنحوية يمكن أن يؤدي إلى تصميم لغوي شامل أكثر نظافة.
  2. تم تحسين كفاءة برنامج التحويل البرمجي. يسمح لنا محلل معجم مستقل بتطبيق التقنيات المتخصصة التي تخدم فقط المهمة اللغوية ، وليس مهمة التحليل. بالإضافة إلى ذلك ، يمكن لتقنيات التخزين المتخصصة لقراءة أحرف الإدخال تسريع المترجم بشكل كبير.
  3. تم تحسين قابلية التحويل البرمجي. يمكن أن تقتصر خصوصيات جهاز الإدخال على محلل معجم.

resource___ Compilers (الإصدار الثاني) كتبه Alfred V. Abo Columbia University مونيكا إس لام جامعة ستانفورد رافي سيثي أفايا جيفري دي أولمان جامعة ستانفورد


متى يتم ذلك بما يكفي ، متى تحتاج إلى EBNF؟

EBNF حقا لا يضيف الكثير لقوة القواعد النحوية. انها مجرد ترميز / الاختصار / "السكر النحوي" على القواعد النحوية القياسية لنموذج تشومسكي (كنف). على سبيل المثال ، بديل EBNF:

S --> A | B

يمكنك تحقيقه في CNF من خلال سرد كل منتج بديل بشكل منفصل:

S --> A      // `S` can be `A`,
S --> B      // or it can be `B`.

العنصر الاختياري من EBNF:

S --> X?

يمكنك تحقيقه في CNF باستخدام إنتاج nullable ، أي ، الذي يمكن استبداله بسلسلة فارغة (يُشار إليها فقط بالإنتاج الفارغ هنا ؛ بينما يستخدم البعض الآخر epsilon أو lambda أو دائرة متقاطعة):

S --> B       // `S` can be `B`,
B --> X       // and `B` can be just `X`,
B -->         // or it can be empty.

يسمى الإنتاج في شكل مثل آخر B أعلاه باسم "erasure" ، لأنه يمكن أن يمحو كل ما يمثله في إنتاجات أخرى (منتج سلسة فارغة بدلاً من شيء آخر).

صفر أو أكثر من التكرار من EBNF:

S --> A*

يمكنك أن تنتف عن طريق استخدام الإنتاج المتكرر ، أي الذي يدمج نفسه في مكان ما فيه. يمكن القيام به بطريقتين. أول واحد هو ترك العودية (والتي عادة ما ينبغي تجنبها ، لأنه لا يمكن تحليل موزعي التنازلي من الأعلى إلى الأسفل):

S --> S A    // `S` is just itself ended with `A` (which can be done many times),
S -->        // or it can begin with empty-string, which stops the recursion.

مع العلم أنه يولد مجرد سلسلة فارغة (في نهاية المطاف) يتبعها صفر أو أكثر ، ويمكن التعبير عن نفس السلسلة ( ولكن ليس نفس اللغة! ) باستخدام التكرار الأيمن :

S --> A S    // `S` can be `A` followed by itself (which can be done many times),
S -->        // or it can be just empty-string end, which stops the recursion.

وعندما يتعلق الأمر بـ + لتكرار واحد أو أكثر من EBNF:

S --> A+

يمكن أن يتم ذلك عن طريق وضع A و باستخدام * كما كان من قبل:

S --> A A*

التي يمكنك التعبير عنها في CNF على هذا النحو (أستخدم التكرار الصحيح هنا ؛ حاول أن تكتشف الآخر بنفسك كممارسة):

S --> A S   // `S` can be one `A` followed by `S` (which stands for more `A`s),
S --> A     // or it could be just one single `A`.

مع العلم بذلك ، يمكنك الآن التعرف على قواعد لتعبير معتاد (أي ، القواعد العادية ) كواحد يمكن التعبير عنه في إنتاج واحد من EBNF يتكون فقط من رموز المحطة الطرفية. بشكل عام ، يمكنك التعرف على القواعد النحوية المعتادة عندما ترى إنتاجات مشابهة لهذه:

A -->        // Empty (nullable) production (AKA erasure).
B --> x      // Single terminal symbol.
C --> y D    // Simple state change from `C` to `D` when seeing input `y`.
E --> F z    // Simple state change from `E` to `F` when seeing input `z`.
G --> G u    // Left recursion.
H --> v H    // Right recursion.

بمعنى ، استخدام السلاسل الفارغة فقط ، والرموز الطرفية ، والمطاريف غير البعيدة للتبديلات وتغيير الحالة ، واستخدام التكرار فقط لتحقيق التكرار (التكرار ، الذي هو مجرد تتابع خطي - هو الذي لا يشبه الشجرة). لا شيء أكثر تقدما فوق هذه ، فأنت على يقين من أنها صيغة منتظمة ويمكنك أن تذهب فقط مع ذلك.

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

S --> a S b    // `S` can be itself "parenthesized" by `a` and `b` on both sides.
S -->          // or it could be (ultimately) empty, which ends recursion.

عندئذ يمكنك أن ترى بسهولة أنه لا يمكن القيام بذلك بالتعبير العادي ، لأنه لا يمكنك حلها في إنتاج واحد من EBNF بأي شكل من الأشكال ؛ سوف ينتهي بك الحال مع استبدال S لأجل غير مسمى ، والذي سيضيف دائمًا s و b s على كلا الجانبين. لا يمكن لليكسرز (على وجه التحديد: Finite State Automata التي تستخدمها lexers) الاعتماد على العدد التعسفي (وهي محدودة ، وتذكر؟) ، حتى لا يعرفوا كم كان هناك لمطابقتها بالتساوي مع الكثير من b s. تسمى القواعد النحوية مثل قواعد النحو خالية من السياق (على الأقل) ، وأنها تتطلب محلل.

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

A R B --> A S B

يمكنك التفكير في هذه الرموز الإضافية على اليسار "سياق" لتطبيق القاعدة. يمكن أن تكون هناك بعض الشروط المسبقة ، الشروط المسبقة ، إلخ. على سبيل المثال ، القاعدة المذكورة أعلاه ستحل محل R في S ، ولكن فقط عندما تكون بين A و B ، مع ترك تلك A و B نفسها دون تغيير. هذا النوع من البنية يصعب تحليله ، لأنه يحتاج إلى آلة Turing كاملة. إنها قصة أخرى كاملة ، لذا سأنتهي هنا.


نعم ، فهي مختلفة من الناحية النظرية ، وفي التنفيذ.

يتم استخدام Lexers للتعرف على "الكلمات" التي تشكل عناصر اللغة ، لأن بنية هذه الكلمات بسيطة بشكل عام. التعبيرات العادية جيدة للغاية في التعامل مع هذا الهيكل الأبسط ، وهناك محركات مطابقة التعبير العادي عالية الأداء المستخدمة في تنفيذ اللكنات.

يتم استخدام المحللون للتعرف على "بنية" عبارات لغوية. هذه البنية هي عموما أبعد ما يمكن أن تعترف به "التعبيرات العادية" ، لذلك يحتاج المرء إلى موزعي "حساسين للسياق" لاستخراج هذه البنية. من الصعب بناء محللات حساسة للسياق ، لذلك فإن الحل التوفيقي الهندسي هو استخدام القواعد النحوية "الخالية من السياق" وإضافة الاختراقات إلى الموزعين ("جداول الرموز" ، وما إلى ذلك) للتعامل مع الجزء الحساس للسياق.

من غير المحتمل أن تختفي تقنية lexing أو parsing في وقت قريب.

قد يتم توحيدها من خلال اتخاذ قرار باستخدام تقنية "تحليل" للتعرف على "الكلمات" ، كما يتم استكشافها حاليًا من قبل محللي GLR الذين لا يحتاجون إلى الماسح الضوئي. هذا له تكلفة وقت التشغيل ، لأنك تقوم بتطبيق آليات أكثر عمومية على مشكلة غالباً ما لا تحتاج إليها ، وعادة ما تدفع مقابل ذلك في النفقات العامة. عندما يكون لديك الكثير من الدورات المجانية ، قد لا يهم هذا الحمل. إذا قمت بمعالجة الكثير من النص ، فإن الأمر لا يهم ، وسوف يستمر استخدام محللي التعبير العادي العادي.


لا يمكن أن يعمل هذا دون تغيير الانقسام من مسافة إلى شيء آخر مثل "|".

النظر في هذا:

الفريد بستر: الفريد بيستر الفريد : الفريد بيستر

  • هل هذا مفتاح "الفريد بيستر" وقيمة ألفريد "أو مفتاح" ألفريد "وقيمة" بيستر ألفريد "؟




parsing antlr lexer pygments