Pegjs: Сокращение для семантических действий

Созданный на 10 сент. 2018  ·  13Комментарии  ·  Источник: pegjs/pegjs

Было бы неплохо добавить сокращение для семантических действий.

Скажем, вместо того, чтобы писать { return value } , мы пишем, например, { extract } который определен в инициализаторе.

Например:

{
  function extract(value) {
    return value;
  }
  function concat(head, tail) {
    return head ? [head].concat(tail) : [];
  }
  function toAddExpr(head, tail) {
    return { type: 'addExpr', expressions: concat(head, tail) };
  }
}

List
  = '(' _ head:Item? tail:( _ ',' _ value:Item { extract } )* _ ')' { concat }

// Another kind of list
Add
  = '(' _ head:Multiply? tail:( _ '+' _ value:Multiply { extract } )* _ ')' { toAddExpr }

Во-первых, это позволит нам повторно использовать функции ... более приятным образом: smile:
Во-вторых, это сделает нашу грамматику более читаемой.

Я считаю, что это также будет более полезно, когда выражение, содержащееся в сокращении действия, будет выражением-членом { foo.bar.baz } а не просто идентификатором { foo } . Так что авторы грамматики могут организовать свои функции внутри объекта или даже модуля.

discussion feature

Самый полезный комментарий

На самом деле, я думал, эти изменения могут просто сработать:

CodeBlock "code block"
  = "=>" _ expession:CallExpression {
       return `return ${ expession };`;
     }
  / "{" <strong i="6">@Code</strong> "}"
  / "{" { error("Unbalanced brace."); }

// Will be based on ECMAScript's CallExpression
CallExpression
  = ...
  / MemberExpression

// Will be based on ECMAScript's MemberExpression
MemberExpression
  = ...
  / ValidIdentifier

// Change `LabelIdentifier` into `ValidIdentifier`

Этот способ по-прежнему потребует интеграции некоторых вещей, таких как первичные выражения ECMAScript (числа, логические значения, массивы и т. Д.), Которые будут использоваться в качестве аргументов, поэтому необходимо будет тщательно выяснить, что добавить.


балансировочные скобы и скобы

Это не будет исправлено до тех пор, пока в парсер PEG.js не будет встроен соответствующий парсер JavaScript, но, честно говоря, я немного сомневаюсь в этом, поскольку есть несколько проектов плагинов, которые генерируют парсеры на других языках (C, PHP, TypeScript и т. д.), и я также работаю над компьютерным языком, на котором я надеюсь однажды сгенерировать парсеры.


Наряду с _PEG.js v0.12_ я буду работать над OpenPEG , который будет предлагать пакет NPM, который по сути является урезанной версией PEG.js без использования какого-либо JavaScript и генерации парсера, но с достаточным количеством функций, чтобы такие проекты на основе JavaScript, как PEG.js может использовать его как серверную часть. Когда выйдет _v0.12_, я постараюсь убедиться, что все проекты плагинов, которые генерируют настраиваемые синтаксические анализаторы, уведомлены об OpenPEG, и до того, как v1 реализует полный синтаксический анализатор ECMAScript 2015 в синтаксическом анализаторе грамматики PEG.js.

Все 13 Комментарий

Интересная идея, но я лично не думаю, что это было бы более понятным способом, поскольку не очевидно, какие аргументы передаются функции. Кроме того, если вам нужно передать «настраиваемый» параметр - вам нужно будет смешать их с обычными вызовами функций, чтобы он не выглядел так чисто, как в более простых случаях.

Кто-то в # 235 предложил синтаксис => для использования со стрелочными функциями, который, на мой взгляд, был довольно ясным и лаконичным.

  = '(' expr:some_expression ')' => expr
  ;

Я склоняюсь к выбору одного из следующих сокращений синтаксиса:

  • => expr; _ (требуется поддержка синтаксиса) _
  • { => expr } _ (сейчас можно использовать, но нужно развернуть) _
  • { > expr } _ (требуется поддержка синтаксиса) _

Еще не решил, поэтому открыт для обсуждения.

Что касается того, что хочет OP, было бы лучше реализовать плагин (после или до того, как будет определен сокращенный синтаксис), который использует Acorn или @ babel / parser для разворачивания идентификатора или выражения члена, преобразовывая его в выражение вызова при добавлении метки в качестве аргументов и возвращают сгенерированный код.

=> expr;

На мой взгляд лучший.

{ => expr }

Конфликты с синтаксисом Javascript IMO. Поскольку он находится внутри { } , можно ожидать, что это будет полная стрелочная функция ( () => ).

{ > expr}

Немного ортогональный любому другому синтаксису в PegJS или Javascript, не сразу читает «это возвращает значение, сокращенное обозначение» IMO - в основном потому, что он заключен в фигурные скобки, я думаю. Тот же аргумент, что и {=> expr} , вы ожидаете, что там будет Javascript.


Кроме того, добавление синтаксиса, отличного от JS, в {} является проблемой для выделителей синтаксиса, линтеров и т. Д. Я не рекомендую этого делать.

Если я могу предложить еще один вариант, возможно, > отдельно (не внутри блока предикатов). Это помогает поддерживать выравнивание, когда вы разносите правила по вертикали:

    = foo:bar qux:(' '+ @qix)+
    > {foo, qux}
    ;

а также встроенный

some_rule = foo:bar qux:(' '+ @qix)+ > {foo, qux};

Зачем нужна точка с запятой для '=>'? Я хотел бы вернуть значение во вложенном коде вместо использования buildList (), например:

  = "(" _ head:Expression _ tail:("," _ expr:Expression => expr)* ")" {
      return [head, ...tail]
    }

Я считаю, что это чище, чем использование магического индекса (см. Ниже). Другой вариант - возможность ссылаться на вложенные метки. например, ("," _ tail:Expression)* ")"

  = "(" _ head:Expression _ tail:("," _ Expression)* ")" {
      return buildList(head, tail, 2)
    }

Я смотрел parser.pegjs и вижу около строки 434 CodeBlock. Что нужно сделать, чтобы попробовать? Код правила просто читает SourceCharacter, что означает просто "."

CodeBlock "code block"
  = "=>" __ <strong i="13">@Code</strong> // this?
  / "{" <strong i="14">@Code</strong> "}"

@mikeaustin Да, это примерно так, но он не знает, где закончить эту последовательность, поэтому будет потреблять все после =>

Может быть, «Код» мог бы быть немного умнее, уравновешивая скобки и фигурные скобки и обрабатывая LineTerminator? Не нужно знать о полном JavaScript, но это может быть сложнее, чем кажется.

На самом деле, я думал, эти изменения могут просто сработать:

CodeBlock "code block"
  = "=>" _ expession:CallExpression {
       return `return ${ expession };`;
     }
  / "{" <strong i="6">@Code</strong> "}"
  / "{" { error("Unbalanced brace."); }

// Will be based on ECMAScript's CallExpression
CallExpression
  = ...
  / MemberExpression

// Will be based on ECMAScript's MemberExpression
MemberExpression
  = ...
  / ValidIdentifier

// Change `LabelIdentifier` into `ValidIdentifier`

Этот способ по-прежнему потребует интеграции некоторых вещей, таких как первичные выражения ECMAScript (числа, логические значения, массивы и т. Д.), Которые будут использоваться в качестве аргументов, поэтому необходимо будет тщательно выяснить, что добавить.


балансировочные скобы и скобы

Это не будет исправлено до тех пор, пока в парсер PEG.js не будет встроен соответствующий парсер JavaScript, но, честно говоря, я немного сомневаюсь в этом, поскольку есть несколько проектов плагинов, которые генерируют парсеры на других языках (C, PHP, TypeScript и т. д.), и я также работаю над компьютерным языком, на котором я надеюсь однажды сгенерировать парсеры.


Наряду с _PEG.js v0.12_ я буду работать над OpenPEG , который будет предлагать пакет NPM, который по сути является урезанной версией PEG.js без использования какого-либо JavaScript и генерации парсера, но с достаточным количеством функций, чтобы такие проекты на основе JavaScript, как PEG.js может использовать его как серверную часть. Когда выйдет _v0.12_, я постараюсь убедиться, что все проекты плагинов, которые генерируют настраиваемые синтаксические анализаторы, уведомлены об OpenPEG, и до того, как v1 реализует полный синтаксический анализатор ECMAScript 2015 в синтаксическом анализаторе грамматики PEG.js.

FWIW, я начал использовать для этого шаблонные литералы. Это также помогает мне с подсветкой синтаксиса JS моим текстовым редактором ...

exports = module.exports = functionBodies`${grammarScript}
...
objectText =
    head:word
    rest:(_txt_ word)*
    ${f=>{
        return new Txt(rest.reduce((a,b)=>([...a,...b]),[head]))
        }}
word = ch:(wordCharacter/escapedCharacter)+ ${chJoin}
...
`
function functionBodies(glue, ...fns){
    return glue.map( (str,i) => str + (fns[i]||'').toString().replace(/^[^{]*/,'').replace(/[^}]*$/, '') ).join('')
    }

function chJoin(ch){return ch.join('')}

Как насчет использования предложенного оператора конвейера (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Pipeline_operator)? Поскольку, по сути, вы просите передать данные по конвейеру?

{
  function extract(value) {
    return value;
  }
  function concat(head, tail) {
    return head ? [head].concat(tail) : [];
  }
  function toAddExpr(head, tail) {
    return { type: 'addExpr', expressions: concat(head, tail) };
  }
}

List
  = '(' _ head:Item? tail:( _ ',' _ value:Item |> extract )* _ ')' |> concat

// Another kind of list
Add
  = '(' _ head:Multiply? tail:( _ '+' _ value:Multiply |> extract  )* _ ')' |> toAddExpr

Ничего подобного не должно происходить. Не должно быть короткого синтаксиса.

Ничего из этого не требуется, если мы просто анализируем стрелки обычным образом, вместо того, чтобы пытаться вставить их вбок.

Хотя это изящная идея, она создает обширную грамматическую двусмысленность по сравнению с JavaScript. Любой, кто разбирал JS и помнит, какой была фиаско with знает, что это, по сути, убьет парсер.

Вместо того, чтобы пытаться создавать что-то новое, мы должны просто поддерживать Javascript. Стрелочные функции старше ES6, а ES6 - с 2015 года. Это было решено шесть лет назад. Здесь не должно быть никаких изобретений.

Оператор конвейера сильно ошибочен и, вероятно, на самом деле не попадет в Javascript, и как язык, на котором он изначально был (F #), так и язык, который его популяризировал (Elixir), отказываются от него. Кроме того, это ни в коем случае не трубопровод.

Причина такого успеха PEG заключалась в том, что он был минимальным и оставался близким к языку, что позволяло ему быть быстрым, маленьким и предсказуемым.

Стрелочные функции старше ES6, а ES6 - с 2015 года. Это было решено шесть лет назад. Здесь не должно быть никаких изобретений.

Эм-м-м. Для меня это новость. Хотите расширить?

Причина такого успеха PEG заключалась в том, что он был минимальным и оставался близким к языку, что позволяло ему быть быстрым, маленьким и предсказуемым.

Причина успеха PEG (как концепции, а не этой библиотеки) заключается в его способности упрощенно представлять сложные грамматики (рекурсивные и т. Д.). Пакрат не был изобретен с этой библиотекой; это не синтаксис. Это алгоритм.

Стрелочные функции старше ES6, а ES6 - с 2015 года. Это было решено шесть лет назад. Здесь не должно быть никаких изобретений.

Эм-м-м. Для меня это новость. Хотите расширить?

Я действительно не знаю, о чем вы спрашиваете.

Стрелочные функции старше ES6. Это была вторая по величине битва в ES6, это то, что подорвало ES4 и что подорвало ES5 +. В тот момент все просили о них с середины 90-х, потому что они на самом деле уже существовали в E4X, и их забрали из-за того, что Google и Apple начали кричать Хикси о том, что Microsoft когда-либо что-либо изобретала.

Теперь вы знаете E4X как React и думаете, что его изобрел Facebook. Facebook думает, что они сорвали Hyperscript. Парень с Hyperscript ясно, что он просто заново реализовал полезную вещь из старого IE.

Их собирались полностью исключить из ES6, как и строки шаблонов, но затем появился Coffeescript и дал сообществу JS и то, и другое, а затем сообщество JS кричало, пока люди из ECMA не сдвинулись с места. Всего 18 месяцев

Стрелочные функции делают все, что здесь должно происходить. Вы даже кажетесь тем человеком, который поднял их в этой теме еще в 2018 году, что делает ваше несогласие весьма поразительным; Я пытался тебя поддержать.

Что еще более важно для меня, если это сделано с помощью функции стрелки, ничего не было добавлено.

Отличия Peg от JS абсолютно минимальны. Поддержка этого просто выполнением вещей ES6 означает, что этот список не изменится.

Это очень ценно.


Причина успеха PEG (как концепции, а не этой библиотеки) заключается в его способности упрощенно представлять сложные грамматики (рекурсивные и т. Д.).

Я не согласен. Многие парсеры справляются с этим намного лучше и даже не пользуются особой популярностью, даже среди людей, которые о них знают (например, Эрли).

Традиционное объяснение - это сочетание качества сообщений об ошибках и скорости, но я тоже не согласен с этим, потому что многие парсеры быстрее выводят сообщения об ошибках лучше (опять же, как Эрли) и даже немного не популярны, даже среди людей. кто знает о них

Также обратите внимание, что у PEG есть три серьезных потолка сложности.

Во-первых, все, что вы хотите провести через грамматику привязки, должно иметь комбинаторное выражение, которое не перегружает кеш локального компьютера и пропускную способность оценки (в примере №623).

Две, многие общие задачи, такие как разбор BNF, в привязке часто чрезвычайно трудны (например, 489).

В-третьих, стоит отметить, что все остальные библиотеки JS PEG, даже значительно более мощные, потерпели неудачу. Я пытался переключиться и возвращался много раз. В частности, я несколько раз пытался переключиться на canopy , потому что это позволяет мне дополнительно настроить таргетинг на c , ruby и python в javascript

Конечно, все, о чем я могу говорить, это две дюжины или около того людей, которых я знаю, которые пользуются им. И я могу, потому что я спросил пару дней назад, когда я понял, что новый не-сопровождающий выбрасывает программное обеспечение и заменяет его чем-то, что он сделал с нуля, после многих лет отсутствия опубликованных изменений

Но каждый из них сказал мне, что либо им нужен синтаксический анализатор, который не имеет большого количества нативных концептуальных накладных расходов, либо что им нужно что-то быстрое и маленькое, поведение которого было бы надежным.

Невыпущенная версия 0.11 ведет себя по-разному в узлах и хром, а узел сделан из хрома. Попробуйте написать против него несколько тестов собственности. Честно говоря, это ужасно.

.

Пакрат не был изобретен с этой библиотекой; это не синтаксис. Это алгоритм.

Я ничего не сказал о Пакрате, друг. Я не уверен, что вы пытаетесь исправить.

Однако синтаксический анализ Packrat не является алгоритмом по той же причине, по которой сортировка не является алгоритмом. Парсинг Packrat - это задача, и есть много способов ее решить.

Действительно, в большинстве вводных книг haskell вы можете создать три или четыре разных парсера packrat, потому что они отличный способ по-настоящему увязнуть в проблемах производительности подхода haskell к монадам, и они хотят показать вам, как изменить подход к написанию packrats (то есть изменение алгоритма) дает лучшие результаты.

.

Пожалуйста, подумайте об этом. Эта библиотека мертва три года назад, и я хочу воскресить ее сейчас.

Одна из причин, по которой библиотека мертва, заключается в том, что люди продолжают пытаться изобретать новые функции вместо того, чтобы выполнять простое обслуживание, например, добавление функции модуля es() которая находилась в разработке в течение двух лет.

Мне нужно вручную изменить мои парсеры PEG, вырезав строки и прикрепив рукописный javascript к их концу.

Звездные глаза должны ненадолго закрываться, и должны появиться практичные сальные локти. PEG - единственная крупная библиотека NPM, которую я когда-либо видел, но ее использование все меньше. Учитывая, что я не знаю разумной замены, это странно и сбивает меня с толку.

image

У меня есть исправления, которые я хочу внести прямо сейчас, но не могу, потому что

  1. 0.10 не публиковался с тех пор, как покинул dmajda,
  2. 0.11 исполнилось три года, никогда не публиковалось, и месяц назад было объявлено, что оно никогда не будет опубликовано, и
  3. Замена, 0.12 , вовсе не привязка, а то, что другой парень написал с нуля на другом языке программирования, и никто из нас этого не видит.

Я знаю, что это невежливо, но мы должны признать, что эту библиотеку убивают

Пришло время признать, что нам нужно принять нормальный процесс разработки, если эта библиотека когда-либо снова увидит обновления. Это 2020 год. Мы ничего не видели с 2017 года.

Нет, ветка разработчика не считается. И новому сопровождающему придется заново открывать кучу проблем, потому что 0.11 недостаточно качественно, а начинать заново с 10 намного меньше, чем исправлять 11

Была ли эта страница полезной?
0 / 5 - 0 рейтинги