如何在文档的最开头开始一个 Vim 语法区域,同时还允许在同一位置进行关键字匹配?

How do I start a Vim syntax-region at the very start of the document, while also allowing a keyword-match in that same position?

感谢文档, I've managed to assign a syntax-region to my document that starts at the very start (\%^):

syn region menhirDeclarations start=/\%^./rs=e-1 end=/%%/me=s-1

为了让它工作,起始模式必须匹配文档的第一个字符。也就是说,以上内容仅适用于 start=/\%^/;它需要最后一个 . (匹配,当成功时,然后 排除 那个字符;但它必须在那之前实际匹配......)

问题是,任何 :syn-keyword match at the same location — even one lower in :syn-priority — 都会抢占我上面的区域匹配。基本上,这意味着我不能让 任何 keyword 允许在文档的开头匹配,或者那个关键字,当这样放置时,会阻止上面的 "whole-top-of-the-document" 完全不匹配的区域。

具体例子。使用以下语法:

syn keyword menhirDeclarationKeyword %parameter %token " ...
syn region menhirDeclarations start=/\%^./rs=e-1 end=/%%/me=s-1

…文档…

%token <blah> blah
blah blah blah

… 将不包含必需的 menhirDeclarations 区域,因为 menhirDeclarationKeyword 在第一个字符处匹配,消耗它,并阻止 menhirDeclarations 匹配。

我可以通过在语法定义中将 everything 声明为 :syn-match or :syn-region 并在最后定义上述区域来绕过这个……但这可能是一个性能问题,并且更重要的是,真的很难管理。

tl;dr: 有没有办法在文档的最开头匹配一个区域,允许关键字匹配在同一个位置?

要保留关键字,您必须创建它们 contained。否则,Vim 的语法规则将始终给予它们优先权,它们将不允许您的区域匹配。如果我从你上一个问题中没记错的话,整个文档被解析为一系列不同的区域;那太好了。否则,您必须为文档中尚未涵盖但也可能包含关键字的部分创建新区域或匹配项。

syn keyword menhirDeclarationKeyword contained %parameter %token
syn region menhirDeclarations start=/\%^%token\>/rs=e-1 end=/%%/me=s-1 contains=menhirDeclarationKeyword

如果那不可行,您确实必须改用 :syntax match

syn match menhirDeclarationKeyword "\<%token\>"

不要假设这会变慢;通过 :help :syntime 对各种复杂的输入文件进行测量。

"difficult to manage" 部分可以通过 Vim 脚本元编程来解决。例如,您可以将所有关键字保存在一个列表中并使用循环动态构建定义:

for s:keyword in ['parameter', 'token']
    execute printf('syntax match menhirDeclarationKeyword "\<%%%s\>"', s:keyword)
endfor