Pegjs: إعادة تصميم الإبلاغ عن الأخطاء

تم إنشاؤها على ١٤ أغسطس ٢٠١٣  ·  7تعليقات  ·  مصدر: pegjs/pegjs

أرى ثلاث مشكلات في نظام الإبلاغ عن الأخطاء الحالي في PEG.js:

  1. تقرير الإجراءات عن الأخطاء بإرجاع null
Reporting using `null` is inflexible (it doesn't allow to carry any information about the kind of error) and makes it impossible to return `null` as a regular value from actions, which would be useful sometimes (for example [in a JSON parser](https://github.com/dmajda/pegjs/blob/791034fad92c9cd7a9d1c71187df03441bbfd521/examples/json.pegjs#L45)).

انظر أيضا # 17.

  1. لا توجد طريقة لإنتاج أخطاء برسائل مخصصة بالكامل
For example, imagine a HTTP 1.1 parser that wants to report an error about missing `Host` header in a HTTP request with a message like "A HTTP 1.1 request must contain a Host header". Currently the only way to do this is to throw an exception with desired message manually. This is cumbersome and it does not interact well with the backtracking behavior (throwing an exception halts the parsing completely, even when it is possible to backtrack and try another alternatives).

  1. الخاصية expected SyntaxError يصعب معالجتها ميكانيكيًا
The `expected` property of `SyntaxError` is either an array of expectations (each describing one alternative which the parser expected at the position of error) or `null` (meaning that the end of input was expected).

يتم تمثيل كل توقع بواسطة سلسلة. يمكن أن تعني هذه السلسلة حرفيًا متوقعًا (يتم تمثيله باستخدام بناء جملة PEG.js - سلسلة مقتبسة) ، أو فئة الحرف (يتم تمثيلها باستخدام بناء جملة PEG.js - [...] ) ، أو أي حرف (يمثله سلسلة "any" ). للتمييز بين هذه الحالات ، يتعين على المرء تحليل تمثيلات السلسلة يدويًا ، مما يجعل أدوات البناء القائمة على PEG.js مثل أجهزة الإكمال التلقائي صعبة دون داع.

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

كيف يعمل الإبلاغ عن الأخطاء حاليًا؟

عندما يحاول المحلل اللغوي PEG.js مطابقة سلسلة حرفية ، أو فئة حرف ، أو . ، ويفشل ، ينتج عنه _ فشل تطابق_. ويتكون من _وضع_ وتوقع_ (وصف لما حاول المحلل مطابقته).

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

يكون الموقف أكثر تعقيدًا قليلاً إذا تم استخدام القواعد المسماة ، لكن هذا غير ذي صلة بهذه المناقشة.

التغييرات المقترحة

أفكر في التغييرات التالية في نظام الإبلاغ عن الأخطاء:

  1. لن يتم تمثيل التوقعات في SyntaxError.expected بالسلاسل ، ولكن من خلال الكائنات. ستحتوي الكائنات على خاصية type (بقيم مثل "literal" ، "class" ، "any" ، "eof" ) والتي ستحدد نوع التوقع. بالنسبة لبعض أنواع التوقع ، ستحتوي الخصائص الأخرى على التفاصيل (على سبيل المثال ، توقع "literal" حيث ستكون خاصية value تحتوي على السلسلة المتوقعة). سيؤدي ذلك إلى تبسيط المعالجة الميكانيكية للتوقعات.

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

  1. سيسمح للإجراءات بإرجاع null . ستكون قيمة عادية ولن تدل على خطأ.
  2. ستكون الإجراءات قادرة على تشغيل فشل المطابقة باستخدام وظيفة error جديدة. سوف يستغرق الأمر رسالة خطأ كمعلمة. ستتألف حالات الفشل التي تسببها هذه الوظيفة (تسمى _فشل المطابقة المخصصة_) من _وضع_ و _رسالة خطأ_. لن يكون لديهم أي توقعات.

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

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

سيختلف استثناء SyntaxError المستند إلى فشل المطابقة المخصصة عن الاستثناءات التي تستند إلى الإخفاق المعتاد. الخاصية message ستكون مساوية لرسالة الخطأ الخاصة بالفشل وخاصيتها expected ستكون null .

مثال

""
بدء = تسجيل: [+ -]؟ أرقام: [0-9] + {
var نتيجة = parseInt ((علامة || "") + digits.join ("")، 10) ؛

 if (result % 2 == 0) {
   error("The number must be an odd integer.");
 }

 return result;

}
""

عند الإدخال 2 ، سينتج المحلل اللغوي الناتج عن القواعد النحوية أعلاه SyntaxError مع تعيين message على "The number must be an odd integer." و expected تم ضبطه على null

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

سيكون استثناء SyntaxError المستند إلى فشل المطابقة الذي تم إنشاؤه بواسطة الدالة expected مماثلاً للاستثناءات التي تستند إلى الفشل المنتظم.

مثال

""
بدء = تسجيل: [+ -]؟ أرقام: [0-9] + {
var نتيجة = parseInt ((علامة || "") + digits.join ("")، 10) ؛

 if (result % 2 == 0) {
   expected("odd integer");
 }

 return result;

}
""

عند الإدخال 2 ، سينتج المحلل اللغوي الناتج عن القواعد النحوية أعلاه مجموعة SyntaxError مع تعيين message على "Expected odd integer but "2" found." و expected مضبوطة على [ { type: "user", description: "odd integer" } ]

الخطوات التالية

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

feature

التعليق الأكثر فائدة

إذن ، لا توجد وظيفة "تحذير" حتى الآن؟

ال 7 كومينتر

سيكون من الأفضل أن تؤدي الاستدعاءات المتعددة لوظيفة الخطأ إلى أخطاء متعددة. يمكنك بعد ذلك الاستمرار في التحليل قدر الإمكان.

string = '"' value:(!(eol / '"') .)+ '"' { return value; }
       / '"' value:(!(eol / '"') .)+     { error('unterminated string constant'); return value; }

أوصي أيضًا بإضافة دعم للتحذيرات أيضًا.

سيكون من الأفضل أن تؤدي الاستدعاءات المتعددة لوظيفة الخطأ إلى أخطاء متعددة. يمكنك بعد ذلك الاستمرار في التحليل قدر الإمكان.

هل يمكنك تسمية بعض حالات الاستخدام التي قد تحتاج إليها؟ يبدو لي أن المثال الذي قدمته سيعمل مع اقتراحي أيضًا.

لدي بالفعل بعض حالات الاستخدام ، لكنني لا أعرف مدى تمثيلها ، لذلك أود رؤية المزيد.

أوصي أيضًا بإضافة دعم للتحذيرات أيضًا.

أنا أيضا أفكر في ذلك.

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

ما نوع واجهة برمجة التطبيقات (API) التي ستجدها أكثر عزيمة هنا؟ مرة أخرى ، لدي بعض الأفكار ، لكني أرغب في رؤية ما يعتقده الآخرون.

هل يمكنك تسمية بعض حالات الاستخدام التي قد تحتاج إليها؟ يبدو لي أن المثال الذي قدمته سيعمل مع اقتراحي أيضًا.

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

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

يتم تنفيذ هذا الآن. يوضح البرنامج النصي tools/impact تأثير الأداء التالي لمجموعة الالتزامات بالكامل:

Speed impact
------------
Before:     1144.21 kB/s
After:      999.89 kB/s
Difference: -12.62%

Size impact
-----------
Before:     863523 b
After:      1019968 b
Difference: 18.11%

(Measured by /tools/impact with Node.js v0.6.18 on x86_64 GNU/Linux.)

أعتقد أن 12.62٪ عقوبة سرعة و 18.11٪ حجم عقوبة جيدة لحل مثل هذه المجموعة طويلة الأمد من المشاكل.

إغلاق.

@ dmajda : هذه أخبار رائعة! أنا سعيد جدًا لأن null لم يعد يشير إلى فشل.

إذن ، لا توجد وظيفة "تحذير" حتى الآن؟

يتم تعقب موضوع وظيفة التحذير في # 325

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات

القضايا ذات الصلة

vldmr1986 picture vldmr1986  ·  12تعليقات

futagoza picture futagoza  ·  13تعليقات

richb-hanover picture richb-hanover  ·  7تعليقات

mattkanwisher picture mattkanwisher  ·  5تعليقات

audinue picture audinue  ·  13تعليقات