Pegjs: القدرة على تحديد عدد التكرار (كما هو الحال في regexps)

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

سيكون من المفيد لو سمحت قواعد PEG.js باستخدام شيء مثل تعبيرات النطاق لتعبيرات POSIX العادية الأساسية. على سبيل المثال:

  • "a"\{1,7\}

تطابق a ، aa ، ...، aaaaaaa

  • "a"\{0,1\}

السلسلة الفارغة و a

  • "a"\{,6\}

يتطابق مع سلسلة تصل إلى (وتشمل) ستة a 's

  • "a"\{6,\}

تتطابق مع سلسلة من ستة أو أكثر من a 's

  • "a"\{3\}

يطابق فقط aaa ، وهو ما يعادل "a"\{3,3\}

feature

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

أحب التكرار كذلك. لكنني أقترح بناء جملة مختلفًا قليلاً. Pegasus مطابق تقريبًا لـ pegjs ، فقط لـ C #. انظر هنا: https://github.com/otac0n/Pegasus/wiki/Syntax-Guide#expressions

وقاموا بتنفيذ هذه الميزة باستخدام هذا: d<3> e<2,> f<1,5>

ال 22 كومينتر

لن أقوم بتنفيذ هذه الميزة.

السبب الرئيسي هو أنه لا يوجد مكان في قواعد PEG.js لبناء جملة {m,n} - تم استخدام الأقواس بالفعل للإجراءات ولا أريد استخدام الخطوط المائلة العكسية كما تقترح (فهي قبيحة وغير متوافقة مع تعبيرات Perl التي تعد الأكثر استخدامًا الآن وأيضًا مصدر لبناء جملة PEG.js الأخرى) أو محددات أخرى (قد يكون ذلك محيرًا).

من واقع خبرتي ، يحدث هذا النوع من التكرار المحدود بشكل أساسي في الأجزاء "المعجمية" من القواعد (قواعد مثل color = "#" hexdigit hexdigit hexdigit hexdigit hexdigit hexdigit ) وليس كثيرًا. أعتقد أنه لا بأس من مجرد استخدام متواليات من التعبيرات وعوامل التكرار الحالية ( * ، + ، ? ) هناك.

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

أرغب في تجنب بناء جملة يشبه التعبير العادي {m,n} لأن { و } قد تم اتخاذهما بالفعل لاتخاذ إجراءات وإعادة استخدامها سيخلق الغموض. أفكر حاليًا في شيء مثل هذا:

"foo" @ 1..10   // repeat 1 to 10 times
"foo" @ 1..     // repeat at least once
"foo" @ ..10    // repeat at most 10 times

السؤال الأكبر هو ما يجب أن تكون عليه الحرف (الأحرف) الفاصلة وكيفية ترميز النطاقات.

بالنسبة للحرف الفاصل ، يبدو @ لطيفًا بالنسبة لي. كنت أفكر في % و # ، لكن في رأيي ، يرتبط الأول بالفعل باستيفاء السلسلة (على سبيل المثال في Python) والثاني مع التعليقات (بلغات مختلفة). أفكر أيضًا في تخطي الفاصل تمامًا:

"foo" 1..10   // repeat 1 to 10 times
"foo" 1..     // repeat at least once
"foo" ..10    // repeat at most 10 times

بالنسبة لترميز النطاق ، فقد ألهمت روبي. كنت أفكر أيضًا في - ، لكنها تشبه إلى حد كبير علامة الطرح. من ناحية أخرى ، يبدو أيضًا : بالنسبة لي.

لست متأكدًا من نطاقات نصف مفتوحة. ربما يكون من الأفضل ترميزها باستخدام + و - مثل هذا:

"foo" @ 1+    // repeat at least once
"foo" @ 10-   // repeat at most 10 times

أي أفكار أو تعليقات؟

رائع حقًا أنك تخطط لدعم هذه الميزة!

يعجبني اقتراحك (الافتراضي):
"foo" @ 1..10 // كرر من 1 إلى 10 مرات
"foo" @ 1 .. // كرر مرة واحدة على الأقل
"foo" @ ..10 // كرر 10 مرات على الأكثر

لا أحب بناء الجملة +/- للنطاقات نصف المفتوحة ، بناء الجملة مزدوج النقاط هو أكثر سهولة وقابلية للقراءة IMO.

الشيء الوحيد الذي راودتني بشأنه هو استخدام "#" vs "@" ، لأن IMO "#" تعني بشكل طبيعي الأرقام / العد ، بينما تشير "@" بشكل طبيعي إلى مرجع ، لذلك قد يكون "#" أكثر سهولة وقراءة (وربما يمكنك استخدام "@" في المستقبل لشيء ما؟). ولكن هذه مشكلة صغيرة حقًا ، وسأكون سعيدًا بصيغة "@".

هتافات!

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

ماذا عن حالة خاصة مقابل {num, num} على حد سواء؟ وهو ما يعني التكرار ، نظرًا لأن { , num} و { num, } ليسا كود js صالحًا ، و {num, num} و { num } لا معنى لهما.

من غير المحتمل أن تكون ذات معنى حتى لو كان الإجراء بلغات أخرى.

تعجبني هذه المتغيرات من بين المقترحات (ولكن الأمر متروك لك بالطبع للاختيار ، نظرًا لأنك المؤلف :)):

// why we need separator, anyway? for me it looks very cool and simple to understand
"foo" 1..10   // repeat 1 to 10 times
"foo" 1..     // repeat at least once
"foo" ..10    // repeat at most 10 times

أو

"foo"@1..10   // repeat 1 to 10 times
"foo"@1..     // repeat at least once
"foo"@..10    // repeat at most 10 times

لكن الثانية أقل تفضيلاً

تبدو فكرة x..y / ..y / x.. رائعة جدًا ، نظرًا لأن .. تبدو عامل تشغيل ثابت بفضلها.

+/- ليس جيدًا بالنسبة لي ، لأنهم يربكون ويصبحون عوامل تشغيل إضافية أعلى من ..+ مستخدم بالفعل)

التفكير في الأمر مرة أخرى. هل ستنجح هذه؟

'foo'<1,5>
'foo'< ,3>
'foo'<2, >

منذ < و > غير مستخدمين حاليًا بواسطة القواعد

: +1: مني ، هذا يبدو جيدًا.

بالطبع ، <,3> يعادل <0,3> ، لذلك قد نطلب أيضًا الحد الأدنى للرقم. سيكون هذا متوافقًا مع ما فعلته ECMA لتعبيرات JavaScript العادية.

أنا أحب <,> . لكنني أقترح أيضًا استخدام <3> مثل <3,3> .

أوافق ، يجب تعيين بناء الجملة <> مباشرةً إلى سلوك {} في RegExp قدر الإمكان.

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

foo 1,2 fighter
bar ,3 tender
baz 4, lurhmann
qux 5 quux

كلها لا لبس فيها.

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

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

بالإضافة إلى ذلك ، اعتاد الناس على استخدام النمط {1,6} في RegExps على أي حال.

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

حالة الاستخدام الخاصة بي: تحليل القيم الحرفية في استجابات خادم IMAP ، والتي تبدو مثل {42}\r\n... ، حيث 42 هو عدد الأحرف بعد السطر الجديد التي تمثل سلسلة (تظهر هنا كعلامة حذف). نظرًا لعدم وجود محدد نهاية لـ IMAP حرفي ، فإن حساب الأحرف هو الطريقة الوحيدة لتحليل هذه الاستجابة.

ماذا عن المتغيرات في القيود؟ هذا مفيد جدًا للرسائل ذات الرأس ، التي تحتوي على طولها. على سبيل المثال ، القواعد

  = len:number message:.<len,len> .* {return message;}
number
  = n:[0-9] {return parseInt(n);}

يجب أن يحلل

4[__] -> ['[', '_', '_', ']']
4[___] -> ['[', '_', '_', '_']
4[_] -> Error: expected 4 chars, got 3

هذا مفيد للعديد من البروتوكولات.

يمكن استخدام هذا النحو:
expression |min,max| ، ثم يمكن استخدام الأقواس المعقوفة لقواعد النموذج.

هل مازلت تفكر في تنفيذ هذا؟
ماذا عن شيء مشابه لنطاقات ABNF ؟

exp *     // 0 or more times
exp 1*    // at least once
exp *10   // up to 10 times
exp 1*10  // 1 to 10 times

أهلا. لدي تنسيق ملف معقد لتحليله. إنه نصف ثنائي ونصف ASCII.

هنا نسخة مبسطة من المشكلة:

KK4TesRandom أو KK10TestATestBRandom

المنطق:

<StringIndicator><StringLength><String><otherStuff>

KK هو مؤشر لتمييز سلسلة. الأرقام التالية (هنا 4 و 10 ) هي طول السلسلة. ثم السلسلة نفسها (هنا Test و TestATestB ). لم يتم إنهاء السلسلة بأي نمط يمكن التنبؤ به. لا بد لي من استخدام معلومات الطول. أود أن أقول أن هذا نمط شائع في تنسيقات الملفات الثنائية ولكن هل من الممكن التحليل باستخدام القواعد النحوية الحالية؟

شكرا لك.

أقوم بتنفيذ شيء من هذا القبيل في نطاقات فرعي - ديناميكية - حدود . ستبدو القواعد كما يلي:

start = len:nx data:.|len| { return data; };
nx = n:$[0-9]+ { return parseInt(n, 10); };

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

أحب التكرار كذلك. لكنني أقترح بناء جملة مختلفًا قليلاً. Pegasus مطابق تقريبًا لـ pegjs ، فقط لـ C #. انظر هنا: https://github.com/otac0n/Pegasus/wiki/Syntax-Guide#expressions

وقاموا بتنفيذ هذه الميزة باستخدام هذا: d<3> e<2,> f<1,5>

ما الذي يعمل الناس حوله من أجل هذا؟ أنا فقط أدخل في PEGjs الآن ، لذلك ربما أحاول تشغيل المسمار بمطرقة ، لكنني أحاول فقط المطابقة بين 1 و 6 أرقام :)

أنا أستخدم تطبيقي الخاص (راجع # 267 لبناء الجملة ، الحل النهائي يدعم الأرقام والمتغيرات وكتل التعليمات البرمجية كحدود) وسأعد العلاقات العامة قريبًا لـ Peggy (إعادة تسمية العلامة التجارية لـ PEG.js fork التي يتم الاحتفاظ بها)

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

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

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

lontivero picture lontivero  ·  25تعليقات

jiyinyiyong picture jiyinyiyong  ·  34تعليقات

dmajda picture dmajda  ·  20تعليقات

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