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

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

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

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

Это тот случай?

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

1 ответ

Решение

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

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

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

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

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

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

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

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

expression
    = termPair ( _ delimiter _ termPair )*

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

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

delimiter "delimiter"
    = "."

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

РЕДАКТИРОВАТЬ: Добавлен еще один пример в комментариях ниже.

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]+

РЕДАКТИРОВАТЬ: Добавлено дополнительное объяснение термина выражения.

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

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

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

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

Другие вопросы по тегам