Pegjs: Форум или чат? Передача значений вниз / всплывающих значений?

Созданный на 23 мар. 2017  ·  7Комментарии  ·  Источник: pegjs/pegjs

pegjs прост и эффективен. Я люблю это! У меня есть несколько вопросов, которых нет в документации:

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

f = x => x * x

Если я делегирую ему слово «Оператор», нет возможности передавать значения вниз. Если я создаю ValuesOperators и или = и =>, это будет немного чище, но на верхнем уровне мне все равно нужно проверить, какой из них был. В примере JavaScript я вижу использование {type: "Literal", value: ...}. Это лучший способ передать информацию обратно?

  = values:Values body:(_ "=>" _ Expression)? assign:(_ "=" _ Expression)? {
      if (body && body.length > 0) {
        return new Function(values, body[3]);
      } else if (assign) {
        return new Assignment(values, assign[3]);
      } else {
        return values;
      }
    }

Спасибо!
Майк

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

Я исходил из предположения, что отсутствие отката и жадности означает, что вы должны работать «где бы вы ни находились», но это не так. Ура!

Жадный просто означает, что если он найдет совпадение, он его возьмет, верно? Но если все правило не совпадает, в следующем матче оно начнется заново. Это намного проще, чем то, как я пытался это сделать в первый раз.

x, y = 2 + 3.foo + "foo", 5 * 2

Это довольно просто, если присвоение можно сопоставить отдельно от регулярного выражения и т. Д.

  = Assignment
  / Expression

Assignment
  = vars:Variables _ "=" _ expr:Expression

Variables
  = head:Identifier tail:(_ "," _ Identifier)*

...

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

В грамматике важно понимать правила. А вы предоставляете только саб .. мне это непонятно, как это может быть машина понятна?
Грамматики LALR очень сложно писать, но они проще, чем LR, и легче, чем LL ..
Грамматику PEG легко написать, но сложнее всего написать эффективно.
Вы уверены, что используете правильную игрушку ? Если у вас хорошая грамматика PEG, вы сможете создать транспилятор или интерпретировать так же легко, как интерпретировать свои правила.

Вы знаете бокс / распаковку в виртуальных машинах?

Как вы можете иметь values слева от задания? потому что у вас есть это: body:(_ "=>" _ Expression)? закончилось ?

что означает values в вашей грамматике? Вы знаете, что такое L-значение ?

Вы должны придерживаться семантически точной грамматики. В некоторых случаях это сложно с PEG ... { type: "Literal", value: ... } - это именно то, что вам нужно в AST. Посмотрите на http://astexplorer.net/, как это может выглядеть

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

а = б
или
х => х * х

Что-то вроде этого уместнее сделать?

AssignmentOrFunction
= identity: Оператор идентификатора : IdentOperator {
if (operator.type === "Функция") {
...
}

IdentOperator
= "="! ">" {return {type: "Assignment"; }}
/ "=>" {...}

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

Спасибо за ваше время!

@mikeaustin Это на твоем :-)

Написание грамматик - это все о сокращениях . Самое главное заявление . Это похоже на sentense, знаете ли, у вас есть LL-грамматики :-)

Вы несете ответственность за определение грамматики в смысле (извините, у меня иногда возникают проблемы с английским :-D)

Как вы хотите обработать AssignmentOrFunction? Это в основном то же самое, что и выражение на многих языках, но также может иметь значение R.
С другой стороны

    = "=" !">" { return { type: "Assignment"; } }
    / "=>" { ... }

может быть лучше записано как

    = "=>" { ... }
    / "=" { return { type: "Assignment"; } }

Может я ошибаюсь .. но это похоже на то, что ты разбиваешь фразу на не столь важный фрагмент. Без контекста неважно, что вы это оцениваете ..

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

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

Вы не даете мне больше контекста в своем вопросе, поэтому очень сложно угадать, что вы действительно хотите построить, но я могу предположить, что вам следует больше поиграть с грамматиками, есть AntLR , отличный инструмент для обучения, GoldParser (LALR) (мой первая игрушка :-)), некоторые старые парсеры, которые хорошо протестированы, наиболее эффективны, но разделены на токенизатор / парсер (старые lex и yacc, новые flex и bison), многие их порты ..

ПЭГ выглядит наиболее простым. Это действительно так. Но это всегда будет опаснее всего ...

Спасибо много! О, я нашел группу Google для pegjs, но не заметил ее, потому что она была в разделе разработки. Если у меня возникнут другие вопросы, я обязательно пойду туда.

Да, присвоение «x = y» - это _statement_, но «x => x * x» может быть частью _expression_, а также «x == y» и т. Д. «=» - это особый случай, и поэтому равно "=>" в том смысле, что они не являются обычными операторами. Я буду больше практиковаться и более внимательно посмотрю на примеры. Я действительно хотел бы, чтобы были примеры, которые были больше, чем калькулятор, но меньше, чем другие примеры. Может, если я добьюсь прогресса, это будет примером :)

Для своего проекта я хотел бы написать простой язык для преобразования в JS. Основы - это внешние методы с лексической областью видимости (без исправлений обезьяны, как Dylan или CLOS, но без мультиметодов), аргументы ключевых слов, ADT, возможно, даже необязательная статическая типизация. «Простой» означает, что все работает вместе, и есть только один способ сделать что-то. Сделать что-то простое может быть сложно.

Кроме того, существуют библиотеки, такие как adt и multimethods, которым может быть полезен собственный синтаксис. На самом деле это может быть достигнуто с помощью sweet , но sweet может только расширить JS, а не сделать его проще. TypeScript имеет такие параметры, как «--strictNullChecks», и поддерживает встроенные типы объединения, но, опять же, он расширяет JS, поэтому он оставляет все плохое (неявное приведение, «+» для конкатенации строк, подъем области видимости и т. Д.).

Еще раз спасибо за помощь!
Майк

Я исходил из предположения, что отсутствие отката и жадности означает, что вы должны работать «где бы вы ни находились», но это не так. Ура!

Жадный просто означает, что если он найдет совпадение, он его возьмет, верно? Но если все правило не совпадает, в следующем матче оно начнется заново. Это намного проще, чем то, как я пытался это сделать в первый раз.

x, y = 2 + 3.foo + "foo", 5 * 2

Это довольно просто, если присвоение можно сопоставить отдельно от регулярного выражения и т. Д.

  = Assignment
  / Expression

Assignment
  = vars:Variables _ "=" _ expr:Expression

Variables
  = head:Identifier tail:(_ "," _ Identifier)*

...

PEG @mikeaustin имеют упорядоченный выбор, что означает, что первый шаблон, который будет соответствовать в выражении, будет автоматически совпадать. Пример @langpavel - хороший способ выразить предпочтение => сравнению с = . Возможно, вы захотите больше подумать о том, каким может быть выражение в терминах «одной из этих вещей», а не «возьмите весь этот текст, который может быть выражением, и выясните его позже»

  = FunctionExpression
  / Assignment
  / Value

Для демонстрации я создал тестовую грамматику, с которой вы можете поиграть. Это немного шумно, но я старался сделать это довольно простым, игнорируя некоторые вещи, такие как добавление дополнительных пробелов и операторов. Обратите внимание на блок Expression котором происходит волшебство. Кроме того, я использовал такие вещи, как SubExpression и ExpressionList как способы обработки "многих из этих" ситуаций; этот шаблон хорошо работает для меня, когда я разделяю разделители списков и элементы.

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

Посмотрю тестовую грамматику, спасибо! Это помогает увидеть минимальное подмножество языка, поскольку грамматика JavaScript довольно велика.

@dmsnell В последнее время я многому научился, удалив правила и добавив несколько новых в грамматику JavaScript, последнее можно увидеть здесь: impulse.pegjs . Я удалил синтаксис исключения [,,], некоторые операторы, выражения последовательности и т.д. и добавил синтаксис кортежа (1, 2) и синтаксис диапазона 1..5. Числа с плавающей запятой требуют наличия десятичных знаков с обеих сторон, чтобы упростить синтаксический анализ диапазонов литералов.

В последнее время я много работал над средой выполнения, но хочу вернуться к синтаксическому анализатору, чтобы фактически испустить JavaScript. Я в перерывах между заданиями, так что у меня есть немного времени :) Некоторые идеи для очищенного диалекта JavaScript с методами расширения, именованными параметрами, трейтами и миксинами, перегрузкой операторов и синтаксисом буквальных кортежей и диапазонов.

Спасибо еще раз!
Майк

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