Двигатель 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-парсерах это обычная идиома, чтобы двигаться вперед таким образом. Я узнал идею из древовидной документации для сопоставления строки.