Сопоставить измененную версию первого совпадения только с одним выражением?

Я пишу кисть для Подсветки синтаксиса Алекса Горбачева, чтобы получить подсветку для кода Smalltalk. Теперь рассмотрим следующий код Smalltalk:

aCollection do: [ :each | each shout ]

Я хочу найти аргумент блока ": каждый", а затем сопоставлять "каждый" каждый раз, когда это происходит впоследствии (для простоты, скажем, каждое вхождение не только в скобках). Обратите внимание, что аргумент может иметь любое имя, например ": myArg".

Моя попытка сопоставить ": каждый":

\:([\d\w]+)

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

\:([\d\w]+)|\1

Но правая часть чередования кажется независимым выражением, поэтому обратная ссылка не работает.

Можно ли даже выполнить то, что я хочу, в одном выражении? Или мне придется использовать обратную ссылку во втором выражении (через другой вызов функции)?

2 ответа

Решение

Вы могли бы сделать это на языках, которые поддерживают просмотр переменной длины (AFAIK только языки платформы.NET, Perl 6 может). Там вы можете выделить слово, если оно соответствует (?<=:(\w+)\b.*)\1, Но JavaScript вообще не поддерживает просмотр назад.

Но в любом случае это регулярное выражение будет очень неэффективным (я только что проверил простой пример в RegexBuddy, и механизму регулярного выражения требуется более 60 шагов, чтобы почти каждый символ в документе мог выбирать между соответствием и несоответствием), так что это не очень хорошая идея если вы хотите использовать его для подсветки кода.

Я бы порекомендовал вам использовать упомянутый вами двухэтапный подход: первый матч :(\w+)\b (граница слова вставлена ​​для безопасности, \d подразумевается в \w), затем выполните буквальный поиск результата поиска \1,

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

Так что нет, я не думаю, что это возможно.

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