LINUX.ORG.RU

Как правильно делать правила для генератора парсеров?


2

2

Пробовал Jison (LARL(1), на нем еще кофескрипт сделан) и PEGjs

На первом исходник мгновенно скатывается в УГ. Во втором - в километровые перечисления кодов для символьных классов.

Что-то я не так делаю. Есть какие-нибудь умные книжки, где рассказывают, как набор правил конвертнуть в то, что парсер схавает? PEG для моих задач достаточно, но хотелось бы и LARL(1) освоить - он более интересный код генерит.

PS. Парсеры жабаскриптовые.

★★★★★

PEG намного более мощный и общий. Не советую связываться с LALR. Умных книжек не надо, достаточно статьи того же Форда про Packrat.

Если в коде появляется много boilerplate, то код надо генерить макросами. В JS для этого есть eval().

anonymous
()

А вы какой язык парсите, если не секрет? Какой-то из известных или свой?

На первом исходник мгновенно скатывается в УГ

УГ в каком разрезе? Запутанный код? Много кода? Если да, то все более-менее реальные парсеры (ну, посложнее калькулятора) они такие, УГ. Вроде бы нет никаких строгих теорий, народ программирует правила пролетарским чутьем.

Вот я бегло просмотрел про PEG в википедии - там лексер и парсер вместе? Смело, с одной стороны, с другой - непривычно. Традиционный путь (лексер->парсер) как-то сразу модульнее и располагает к более тщательным раздумьям.

А в bison/lemon вы для этого языка правила писали? Если получается красивее, может на сервер-сайде бы и делать?

Deleted
()
Ответ на: комментарий от anonymous

Мммм... PEG несомненно более удобный, и предсказуемый. Но вот по ресурсам он не самый оптимальный. В большинстве мест это не имеет значения. Но вот например для парсера YAML - имеет.

Vit ★★★★★
() автор топика
Ответ на: комментарий от Deleted

- https://github.com/nodeca/babelfish/blob/master/src/parser.pegjs - это правила для парсинга вот таких выражений https://github.com/nodeca/babelfish#phrases-syntax

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

- https://github.com/nodeca/ndoc/blob/master/src/js-parser.y - это тихий песец для pdoc-овского синтаксиса генерации документации (в корне проекта есть все ссылки). Т.к. скорость не важна, есть желание перегнать все на PEG. Он действительно на порядок удобнее, когда речь не идет о выжимании максимума из ресурсов.

Vit ★★★★★
() автор топика
Ответ на: комментарий от Vit

правила для парсинга вот таких выражений
I have #{count} ((nail|nails)):count

Это вот такие выражения?

Там же «грамматики» особой нет? Не проще ли «парсить регекспами»? Ну, мне кажется это как из пушки по воробьям.

И тут нет никакой избыточности? Можно ли это фразу записать как «I have ((nail|nails))» ? Тогда можно натурально регекспом распарсить. Или переменные нужны и используются где-то дальше?

тихий песец для pdoc-овского синтаксиса генерации документации

Тут ниасилел, пятница же, моск уже отключается. Но выглядит и правда так себе. А у вас есть это в виде (полу-)формальной спецификации? Дайте ссылку, пожалуйста, если есть, может быть завтра посмотрю

Deleted
()
Ответ на: комментарий от Deleted

тихий песец для pdoc-овского синтаксиса генерации документации

А, все, увидел ссылки

Deleted
()
Ответ на: комментарий от Deleted

Там же «грамматики» особой нет? Не проще ли «парсить регекспами»? Ну, мне кажется это как из пушки по воробьям.

Just for lulz. Хочется освоить генератор парсеров. IMHO, пеговский сорец читать точно легче, чем самопальный. Даже на таком тривиальном синтаксисе, как у переводилки.

И тут нет никакой избыточности?

Там точно нет избыточности, если учесть все фичи переводилки. Посмотрите всю спеку. Вариант, который вы предлагали - частный случай, который тоже работает.

Vit ★★★★★
() автор топика
Ответ на: комментарий от Vit

Хочется освоить генератор парсеров

А. Я попробовал Jison, у него есть он-лайн пробовалка

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

/* lexical grammar */
%lex
%%

\s+                   /* skip whitespace */
"#{"[a-zA-Z_.]+"}"       return 'VAR'
"(("                     return 'PLURBEGIN'
"))"                     return 'PLUREND'
"|"                      return 'VBAR'
":"                      return 'COLON'
[a-zA-Z.а-яА-Я_-]+       return 'WORD'
[0-9]+("."[0-9]+)?\b     return 'NUMBER'
<<EOF>>                  return 'EOF'
.                        return 'INVALID'

/lex

%start text

%% /* language grammar */

text
    : words EOF
        {return $1;}
    ;

words
    : word
    | words word
    ;


plur
    : PLURBEGIN plurs PLUREND
    | plur COLON WORD
    ;

plurs
    : WORD
    | plurs VBAR WORD
    ;

var
    : VAR
    ;


word
    : WORD
    | NUMBER
    | var
    | plur
    ;

Хотя я остаюсь при мнении что вот именно здесь проще парсить вручную. Такое - разве что для саморазвития :-)

Deleted
()
Ответ на: комментарий от Deleted

Тут вопрос больше в методике, как наборы правил правильно строить.

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

Vit ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.