Отступает ли движок Peg.js после просмотра вперед, как это делают регулярные выражения?

Согласно регулярным выражениям.info об обходах, движок делает шаг назад после просмотра вперед:

Давайте еще раз заглянем внутрь, чтобы убедиться, что вы понимаете последствия просмотра вперед. Применим q(?=u)i для выхода. Упреждающий просмотр теперь положительный, и за ним следует еще один токен. Опять же, q соответствует q, а u соответствует u. Опять же, совпадение из упреждающего поиска должно быть отброшено, поэтому механизм переходит от i в строке к u. Упреждающий просмотр был успешным, поэтому двигатель продолжает работу с i. Но я не могу сравниться с тобой. Таким образом, эта попытка матча не удалась. Все оставшиеся попытки также терпят неудачу, потому что в строке больше нет q.

Однако в Peg.js КАЖЕТСЯ, что движок все еще перемещается, минуя & или !, так что на самом деле это не просмотр вперед в том же смысле, что и регулярные выражения, а решение о потреблении, и есть никакого отступления и, следовательно, настоящего взгляда вперед.

Так ли это?

(Если это так, то некоторые парсеры даже невозможны, например этот?)


person TheRealWinnebagoMan    schedule 19.10.2018    source источник


Ответы (1)


Lookahead работает так же, как в движке регулярных выражений.

Этот запрос не соответствует, потому что следующая буква должна быть 'u', а не 'i'.

word = 'q' &'u' 'i' 't'

Этот запрос выполнен успешно:

word = 'q' &'u' 'u' 'i' 't'

Этот запрос выполнен успешно:

word = 'q' 'u' 'i' 't'

Что касается вашего примера, попробуйте что-то в этом роде, вам вообще не нужно использовать просмотр вперед:

expression
    = termPair ( _ delimiter _ termPair )*

termPair
    = term ('.' term)? ' ' term ('.' term)?

term "term"
    = $([a-z0-9]+)

delimiter "delimiter"
    = "."

_ "whitespace"
    = [ \t\n\r]+

EDIT: добавлен еще один пример для комментариев ниже.

expression
    = first:term rest:delimTerm* { return [first].concat(rest); }

delimTerm
    = delimiter t:term { return t; }

term "term"
    = $((!delimiter [a-z0-9. ])+)

delimiter "delimiter"
    = _ "." _

_ "whitespace"
    = [ \t\n\r]+

EDIT: добавлено дополнительное объяснение термина выражение.

Я попытаюсь немного разобрать правило термина $((!delimiter [a-z0-9. ])+).

$() преобразует все внутри в один текстовый узел, например [].join('').

Один «символ» термина — это любой символ [a-z0-9. ], если бы мы хотели упростить его, мы могли бы вместо этого сказать .. Прежде чем сопоставлять символ, мы хотим искать delimiter, если мы находим delimiter, мы перестаем сопоставлять этот символ. Поскольку нам нужно несколько символов, мы делаем все это несколько раз с +.

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

person Josh Voigts    schedule 19.10.2018
comment
Суть, однако, в том, что в термин включается ограничительное значение. Итак, если разделитель . (пробел точка пробел) вы также можете иметь такие термины, как: term1.a term1.b. Примером выражения может быть term1.a term1.b . term2.a term2.b Для человека это легко разобрать, точка, окруженная пространством, является четким разделителем, но Peg.js делает это, это вопрос. - person TheRealWinnebagoMan; 22.10.2018
comment
Оба этих примера анализируются в ответе выше. Я не уверен, о чем конкретно вы спрашиваете. - person Josh Voigts; 22.10.2018
comment
Извините за отсутствие ясности. Хотя он не динамичный. Термин должен быть любой комбинацией любого количества букв, точек, пробелов. Затем разделитель пробел-точка-пробел и еще один подобный термин. Пространства в вашем примере не являются динамическими. Таким образом, в качестве термина также должно быть разрешено следующее: a.1 b cde.1 cde2 . все это предложение, включая его конечную точку, также является термином. После 'cde2' есть два термина и один разделитель. Это имеет больше смысла? - person TheRealWinnebagoMan; 23.10.2018
comment
Я предпринял еще одну попытку в EDIT выше. Вы можете использовать отрицательный прогноз для delimiter в вашем term, чтобы избежать чрезмерной жадности при захвате периодов. - person Josh Voigts; 24.10.2018
comment
Ух ты. Я пытался сделать это 1000 раз. Спасибо, что доказали, что это был я, а не парсер, и что дали мне что-то для изучения. Невероятный! - person TheRealWinnebagoMan; 25.10.2018
comment
Можете ли вы добавить краткое описание термина правило? РЕДАКТИРОВАТЬ: как вы пришли к этому? - person TheRealWinnebagoMan; 25.10.2018
comment
Надеюсь, это поможет, я добавил немного больше информации. - person Josh Voigts; 25.10.2018