因此,我正在尝试为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像这样将文件的语法高亮分割为多个部分?
答案 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
组的多个重复匹配(也可以用相同的方法解决),我只是通过/\%$/
让它在缓冲区的末尾结束。