如何在vim语法区域中使用与begin和end相同的模式?

时间:2019-01-07 00:57:05

标签: vim vim-syntax-highlighting

因此,我正在尝试为OCaml的Menhir解析器生成器构建语法。

在该语言中,文件分为三个部分,用%%分隔(不,它并不漂亮;不幸的是,它是从古老的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像这样将文件的语法高亮分割为多个部分?

1 个答案:

答案 0 :(得分: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组的多个重复匹配(也可以用相同的方法解决),我只是通过/\%$/让它在缓冲区的末尾结束。