Как использовать тот же шаблон, что и начало и конец в области синтаксиса vim?

Итак, я пытаюсь создать синтаксис для парсера Menhir. генератор для OCaml.

На этом языке файл состоит из трех разделов, разделенных %% (нет, это некрасиво; к сожалению, это унаследовано от древнего ocamlyacc.)

Я пытаюсь создать отдельную синтаксическую область для каждой из этих трех плюс одну для чего-либо после постороннего третьего %%:

this should be in `menhirDeclarations`
%%
this should be in `menhirRules`
%%
this should be in `menhirOcamlFooter`
%%
this should be in `menhirSeparatorError`
%%
this should still be in the same `menhirSeparatorError`

Сегодня я просматривал документы :h syn-define и дошел до определения группы, которая соответствует всему в первом объявлении:

syn region menhirDeclarations start=/\%^/ end=/%%/
    \ contains=@menhirComments

… но у меня большие проблемы с расширением этого, чтобы правильно соответствовать следующим разделам. Наивный подход не работает для меня, например:

" These break each document into the three sections of a Menhir parser definition:
syn region menhirSeparatorError start=/%%/ end=/%%/
    \ contained contains=@menhirComments
syn region menhirOcamlFooter start=/%%/ end=/%%/
    \ contained contains=@menhirCommentsnextgroup=menhirSeparatorError
syn region menhirRules start=/%%/ end=/%%/
    \ contained contains=@menhirComments nextgroup=menhirOcamlFooter
syn region menhirDeclarations start=/\%^/ end=/%%/
    \ contains=@menhirComments nextgroup=menhirRules

Как я могу заставить Vim разделить выделение синтаксиса файла на несколько разделов, как это?


person ELLIOTTCABLE    schedule 07.01.2019    source источник


Ответы (1)


Ваша проблема заключается в том, что разделители @@ включены как в начальный, так и в конечный шаблоны региона, поэтому конечное совпадение одного региона скрывает потенциальное начальное совпадение следующего региона. Другими словами, ваш код будет работать, если разделы будут разделены @@@@ вместо @@.

Поскольку вам необходимо утвердить обе стороны раздела, вы можете остановить сопоставление конечной области с помощью :help :syn-pattern-offset. Смещение me=s-1 (конец совпадения — это один символ до начала совпадения) по-прежнему утверждает, что раздел заканчивается на @@, но больше не использует эти два символа. При этом nextgroup может творить чудеса и начинать следующую группу сразу после окончания предыдущей:

syn region menhirDeclarations start=/\%^./ end=/%%/me=s-1 nextgroup=menhirRules
syn region menhirRules start=/%%/ end=/%%/me=s-1 contained nextgroup=menhirOcamlFooter
syn region menhirOcamlFooter start=/%%/ end=/%%/me=s-1 contained nextgroup=menhirSeparatorError
syn region menhirSeparatorError start=/%%/ end=/\%$/ contained

Обратите внимание, что мне каким-то образом пришлось сопоставить хотя бы один символ в начале буфера; /\%^/ у меня не работало (в Vim версии 8.1.536). Чтобы избежать реализации нескольких повторяющихся совпадений последней группы menhirSeparatorError (которые также можно решить с помощью того же подхода), я просто позволяю ей заканчиваться в конце буфера через /\%$/.

person Ingo Karkat    schedule 08.01.2019
comment
Незадолго до того, как вы опубликовали это, я попробовал с lc вместо me — я не могу понять, почему мой аналогичный подход не сработал! Кроме того, как ни странно, некоторые попытки, которые я предпринял без начального символа, совпадающего с start первого региона, сработали, но большинство из них не сработало. Это исправило многие мои предыдущие подходы, а также работу в вашей конкретной конфигурации. Спасибо! - person ELLIOTTCABLE; 13.01.2019