Pegjs: استيراد / تضمين قواعد أخرى

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

قد يكون من المفيد للغاية أن تكون لديك القدرة على تحديد القواعد النحوية عن طريق استيراد القواعد من القواعد النحوية الأخرى.

عدة أفكار

<strong i="7">@include</strong> "expression.pegjs"
(or <strong i="8">@from</strong> "expression.pegjs" import expression)

tag_if
    = "if" space? expression space? { ... }

<strong i="9">@import</strong> "expression.pegjs" as expr

tag_if
    = "if" space? expr.expression space?

من الناحية المثالية ، لن يؤدي ذلك إلى إعادة إنشاء الكود بالكامل في كل ملف .pegjs يتضمن ملفًا آخر ؛ ربما يتعين علينا تعديل سلوك التحليل قليلاً إلى شيء من هذا القبيل ؛

التحرير حسب ما قلته في قضية options ؛

parse(input, startRule)
->
parse(input, { startRule: "...", startPos : 9000 })

وفي النهاية ، إذا كان startPos != 0 && result !== null ، فإننا لا نتحقق مما إذا كنا قد ذهبنا حتى input.length ، ولكن بدلاً من ذلك نعيد النتيجة بالإضافة إلى endPos (لا أعرف حقًا كيفية القيام بذلك بأناقة - ربما مجرد تعديل معلمة الخيارات؟).

سيسمح بإعادة استخدام القواعد النحوية ووضع الكود المعياري ، وهو ما أعتقد أنهما جانبان مهمان للغاية من الترميز بشكل عام.

feature

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

Dignifiedquire أفكر حاليًا في بناء الجملة والدلالات التي يمكن شرحها بشكل أفضل من خلال مثال:

static-languages.pegjs

langauges  = "C" / "C++" / "Java" / "C#"

dynamic-languages.pegjs

languages = "Ruby" / "Python" / "JavaScript"

all-languages.pegjs

static  = require("./static-languages")
dynamic = require("./dynamic-languages")

all = static.languages / dynamic.languages

كل ملف .pegjs سيعرف ضمنيًا وحدة تقوم بتصدير كل القواعد التي يحتوي عليها. سيستورد البناء <name> = require(<module>) مثل هذه الوحدة. ستكون قواعده متاحة بعد ذلك داخل مساحة اسم.

هذا التصميم مشابه بشكل متعمد لـ Node.js. سيؤدي استخدام مساحات الأسماء إلى تجنب التعارضات. هناك نوعان من الجوانب السلبية التي أراها:

  1. بناء <name> = require(<module>) مشابه جدًا لتعريفات القواعد وبالتالي يمكن أن يكون مربكًا (قد يعتقد المرء أنه تم استيراد قاعدة واحدة فقط).
  2. يتعارض بناء الجملة . مع المعنى الحالي لـ . ، وهو "أي حرف". يمكن حل هذا عن طريق الاختراقات القبيحة (على سبيل المثال ، . محاطًا بمسافة بيضاء يعني "أي حرف" ، بينما . المحاط بالمعرفات يفصل اسم مساحة الاسم عن اسم القاعدة) أو عن طريق تغيير بناء الجملة (على سبيل المثال باستخدام الكلمة الرئيسية any لتمثيل "أي حرف").

ال 32 كومينتر

أوافق على أن هذه ميزة مهمة ، أريد أن أفعل ذلك بعد الإصدار 1.0.

(راجع للشغل لا أحب الصيغة الشبيهة ببايثون التي تقترحها - شيء مشابه لـ Node.js require سيكون أفضل لأنه سيكون مألوفًا أكثر لمبرمجي JavaScript. لكن هذا شيء ثانوي يمكن تسويته في وقت لاحق.)

هل تعتبره للتضمين قبل الإصدار 1.0 إذا تم توفيره مع تصحيح؟

أوافق على ملاحظتك حول بناء جملة الثعبان.

+1 لهذه الميزة

ceymard نعم ،

+1 للميزة و +1 لإدراج نمط require

dmajdaceymard هل لديك أي أفكار بالفعل على كيفية تنفيذ ذلك؟ أحتاج هذا لمشروع في العمل وسأحاول تنفيذه. السؤال هو هل يجب أن يكون هذا مجرد إضافة لتقسيم القواعد النحوية إلى ملفات متعددة أو شيء مثل الميراث ، بحيث يمكن للمرء أن يرث جميع القواعد على سبيل المثال ثم الكتابة فوق قواعد معينة في القواعد الجديدة.

Dignifiedquire أفكر حاليًا في بناء الجملة والدلالات التي يمكن شرحها بشكل أفضل من خلال مثال:

static-languages.pegjs

langauges  = "C" / "C++" / "Java" / "C#"

dynamic-languages.pegjs

languages = "Ruby" / "Python" / "JavaScript"

all-languages.pegjs

static  = require("./static-languages")
dynamic = require("./dynamic-languages")

all = static.languages / dynamic.languages

كل ملف .pegjs سيعرف ضمنيًا وحدة تقوم بتصدير كل القواعد التي يحتوي عليها. سيستورد البناء <name> = require(<module>) مثل هذه الوحدة. ستكون قواعده متاحة بعد ذلك داخل مساحة اسم.

هذا التصميم مشابه بشكل متعمد لـ Node.js. سيؤدي استخدام مساحات الأسماء إلى تجنب التعارضات. هناك نوعان من الجوانب السلبية التي أراها:

  1. بناء <name> = require(<module>) مشابه جدًا لتعريفات القواعد وبالتالي يمكن أن يكون مربكًا (قد يعتقد المرء أنه تم استيراد قاعدة واحدة فقط).
  2. يتعارض بناء الجملة . مع المعنى الحالي لـ . ، وهو "أي حرف". يمكن حل هذا عن طريق الاختراقات القبيحة (على سبيل المثال ، . محاطًا بمسافة بيضاء يعني "أي حرف" ، بينما . المحاط بالمعرفات يفصل اسم مساحة الاسم عن اسم القاعدة) أو عن طريق تغيير بناء الجملة (على سبيل المثال باستخدام الكلمة الرئيسية any لتمثيل "أي حرف").

dmajda نظرًا لأن <identifier> = <expression> مأخوذ بالفعل من خلال تعريفات القواعد ، فلماذا لا تفعل شيئًا كهذا:

static := require("./static-languages")
dynamic := require("./dynamic-languages")

all = static::languages / dynamic::languages

لا يتم استخدام :: أي مكان أعرفه في PEG.js ويجعل من السهل التمييز بين مساحات الأسماء والأشياء الأخرى. لست متأكدًا من := الذي يجلب النقطة عبره ولكن أشعر أنه غريب جدًا بالنسبة لجافا سكريبت ..

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

static := {
  languages  = "C" / "C++" / "Java" / "C#"
}

dynamic := {
  languages = "Ruby" / "Python" / "JavaScript"
}

لست معجبًا كثيرًا بـ :: و := ، فهم يبدون غريبين في عالم javaScript / CoffeeScript.

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

ماذا عن ببساطة:

<strong i="6">@require</strong> foo = "./foo"

bar = foo:languages

تعد النقطتين بمثابة حل وسط ، ولكنها تُستخدم لفصل مساحات الأسماء في العديد من الأماكن: C ++ و C # و XML وما إلى ذلك.

سيظل : مرتبطًا دائمًا بـ cons للعديد من المبرمجين العاملين. أقترح الابتعاد عن هذا العامل. :: جيدًا بالنسبة لي. أليس هذا مستخدمًا لمساحات C ++؟ لست مقتنعًا حتى الآن بأن . هو خيار سيء أيضًا.

لا يمكن استخدام . بدون تغيير فاصل. سيكون غامضا في اللغة.

يُستخدم :: في C ++ لمساحات الأسماء ، وفي C # لبادئات مساحة الاسم (على سبيل المثال ، global::System ).

كنت أفكر في حل بديل سريع حول هذا الموضوع - لحل التوريث البسيط فقط - لصق ملفات pegjs معًا ، مع وجود كل شيء في نطاق الأسماء.

قد يجعل ذلك القواعد النحوية مطولة جدًا ، وينطوي على خطوة بناء - ولكن بالنظر إلى الجانب المشرق ، سيجبرك على الحصول على قواعد نحوية محببة DRY & OTW

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

languages = static__languages / dynamic__languages
<static-languages.pegjs>
<dynamic-languages.pegjs>
/* alternative */
languages = STATIC__languages / DYNAMIC__languages

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

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

odonnell +1 لإصدار أي شيء - بغض النظر عما إذا كان لديك الوقت لتنظيفه

و +1 للتوضيح. يجب التعامل مع هذا كحل سريع ، وليس حلاً مناسبًا طويل الأجل.

odonnell على الإنترنت على https://github.com/andreineculau/core-pegjs - يرجى الوخز لي إذا كان لديك شيء أفضل.

+1 لهذه الميزة

: +1:

: +1:

: +1:

ذهبت وكتبت مكونًا إضافيًا / ملحقًا لـ PEG.js يقوم بالاستيراد: https://github.com/casetext/pegjs-import.

+1 لهذا أيضًا.

أقوم بتنفيذ هذا في # 308 بطريقة عامة: تضمين القواعد هو طريقة واحدة فقط لتطبيق قواعد التحليل.

ميزة كبيرة: +1:

نتطلع لرؤيتها صدر.

: +1:

مدهش! : +1:

dmajda أنا قادم متأخرًا إلى هذه الحفلة ، لكني أتساءل كم مرة نحتاج إلى استيراد العديد من القواعد من مكتبة أخرى. أود أن أكون قادرًا على استيراد أشياء مثل Url و Email إلى القواعد النحوية الخاصة بي ولكني لا أهتم أن Url قد يحتوي أيضًا على أشياء مثل HierarchicalPart و AsciiLetter . هل تعتقد أن شيئًا مثل صادرات Node المسماة سيكون وسيلة قابلة للتطبيق للمضي قدمًا ، مع الحفاظ على فوائد تباعد الأسماء مع السماح باستيراد الأسماء المباشرة؟

import { SchemalessUrl, Url } from "./Urls.pegjs"

Token
  = PhoneNumber
  / Url
  / SchemalessUrl

لقد كان تحديد مسافة الأسماء مشكلة بالنسبة لي لأنني أحاول استكشاف كتابة قواعد النحو القابلة للتكوين بطريقة أخرى. أنا عالق الآن في تضمين الملفات في الملفات وتسمية الأشياء بالطريقة التي تم بها تسمية وظائف PHP قبل تقديم مساحات الأسماء المناسبة: UrlIpHost ، HtmlQuotedString ، إلخ ...

تضمين التغريدة

أي تقدم في هذه المسألة؟ أو المناقشة الأولية التي تعيش الآن على # 473؟
ينمو ملف القواعد الخاصة بي بسرعة كبيرة :(
سيكون من الجيد تقسيمها عدة مرات

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

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

mikeaustin أرى هذه الميزة كنوع من Node.JS required :

القط bash.pegjs
{
const _ = تتطلب ("مسافة بيضاء") ؛
const LB = تتطلب ("line_break") ؛
const CodeBlock = تتطلب ("code_block") ؛
const BoolExpr = تتطلب ("boolean_expression") ؛
}
...
IfStatement = "if" _ "[" BoolExpr "]" _ "؛" _ "ثم" LB؟ CodeBlock "fi"

أوافق على أن تقسيم القواعد النحوية وجعلها معيارية يعد ميزة رائعة ، ولكن التعامل مع هذه الحالات سيكون مشكلة:
1- القواعد الفرعية التي تعتمد على متغير عام تم تعريفه في كود النحو الرئيسي؟
2- متغيرات مكررة واسم نحوي؟

IMO ، نهج مناسب مؤقتًا هو إنشاء ملحق جديد لـ PEG.js (مستقل عن PEG.js) يحدد كلمة أساسية للاستيراد (على سبيل المثالload (anotherGrammarFileLocation)) يجب ألا تكون الكلمة الأساسية جزءًا من قواعد javacsript / peg.js ،
قم بإنشاء reg-exp أو قواعد نحوية peg لاكتشاف تلك الكلمة الرئيسية واستبدالها بمحتوى "anotherGrammarFile Location" ، وإرسال الكود المستبدَل إلى PEG.js

مثال:

أعداد صحيحة

integers=[0-9]* {return parseInt(text())}

main.pegjs
arrayOfInteger="["(integers ",")* integers"]"
@load("integers.pegjs")

لاحظ باستخدام هذه الطريقة ، إذا لم يعرّف شخص ما قواعد البدء ، ووضع load قبل "arrayOfInteger" ، فسيفترض peg.js أن القواعد النحوية الأولى هي البداية (قواعد نحوية صحيحة)

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

يجب أن يكون المستخدم مسؤولاً عن أي تكرار.

أريد فقط أن أوضح أن هذه المشكلة هي في الأساس طلب تحسين ، لأن القابلية للتركيب / النمطية هي شيء يمكنك تحقيقه بنفسك ، خاصةً عندما تتحكم في النطاق الكامل للقواعد.

إذا لم تكن مرتاحًا لقواعد نحوية بطول 1k ، فقم بتقسيمها ، وسلسلها مرة أخرى كما تراه مناسبًا قبل ضخها في pegjs.

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