如何正确地将另一种语言嵌入到我当前的语言定义中?
How to correctly embed another language into my current language defintion?
我有 Sublime Text 3 Smalltalk sublime-syntax file (YAML),我想为嵌入式 C 代码添加突出显示支持。
smalltalk代码中的inline C
(总是以^%\{
开始,以%\}$
结束)代码
一个简单的例子(不多C
但想要一个简单的例子):
sigABRT
"return the signal number for SIGABRT - 0 if not supported by OS
(the numeric value is not the same across unix-systems)"
%{ /* NOCONTEXT */
#ifdef SIGABRT
RETURN ( __mkSmallInteger(SIGABRT) );
#else
RETURN ( __mkSmallInteger(0) );
#endif
%}
!
Sublime text 中有新功能 embed
(甚至还有一个 example)。
我试过这样做:
- match: '^%\{'
embed: scope:source.c
embed_scope: meta.environment.embedded.c.smalltalk source.c.embedded
escape: '%\}$'
但是,我无法将它正确地合并到我的 current highlighting file 中。
有谁知道如何正确地将一种语言嵌入到另一种语言中?
这个问题有点棘手,因为您提供了一个示例语法定义和一些 Smalltalk 源代码示例,但是提供的代码没有被提供的语法突出显示,因为它的结构不正确。
为了我们的目的,我们假设您提供的 Smalltalk 示例是以下示例。这可能有效也可能无效(自从我使用 Smalltalk 以来已经有很长时间了)但它突出显示了您的语法,所以让我们称其足够好以用于测试目的。
Object subclass: Test [
sigABRT
"return the signal number for SIGABRT - 0 if not supported by OS
(the numeric value is not the same across unix-systems)"
%{ /* NOCONTEXT */
#ifdef SIGABRT
RETURN ( __mkSmallInteger(SIGABRT) );
#else
RETURN ( __mkSmallInteger(0) );
#endif
%}
!
].
你上面提供的语法匹配是正确的,所以我猜你的问题出在你把它放在语法中的什么地方。
所以我们假设在语法定义中我们可能希望在多个地方匹配这些 C 块之一;在这种情况下,我们可能希望在包含匹配项的语法中创建一个新的 context
,以便我们可以在需要的地方 include
:
c-block:
- match: '%\{'
embed: scope:source.c
embed_scope: meta.environment.embedded.c.smalltalk source.c.embedded
escape: '%\}$'
这与您在上面提供的摘录相同,但置于上下文中。因此,假设像这样的块可以出现的第一个地方是块的主体。您的语法中有一个 block-body
上下文,因此我们将 include
粘贴到它的末尾以包含这个新上下文:
block-body:
- include: pragma
- include: selector
- include: literal
- include: block
- include: comment
- include: c-block
然而,这并没有达到预期的效果;突出显示不正确:
很明显,至少从 C 注释开始,可能更早,突出显示就出错了。如果在光标位于注释上时使用 Tools > Developer > Show Scope Name
,您可以看到分配的范围是 source.smalltalk entity.name.function
,这意味着语法将 C 注释开头视为方法名称。
%{
结构似乎也没有正确突出显示,检查显示 %
字符的范围是 source.smalltalk keyword.other
。
所以实际上目前的问题是,有了上面的定义,而不是将 %{
视为开始 C 块,它被视为关键字,如果它是关键字,那么规则匹配 C 块根本不会触发。
如果您查看语法,main
上下文如下所示:
main:
- match: '([a-zA-Z][a-zA-Z0-9]*)\s*(subclass:)\s*([a-zA-Z][a-zA-Z0-9]*)\s*\['
captures:
1: entity.other.inherited-class
2: keyword.other
3: entity.name.type
push:
- match: '\]'
pop: true
- include: pragma
- match: '(([a-zA-Z][a-zA-Z0-9]*:)|[+\-\/\*~<>=@%|&?!.,:;^]+)\s*([a-zA-Z][a-zA-Z0-9]*)'
captures:
1: entity.name.function
3: variable.other
- match: "([a-zA-Z][a-zA-Z0-9]*)"
scope: entity.name.function
- include: block
- include: comment
- include: block-body
这些规则表明,当我们看到以 BaseClass subclass: SubClass [
开头的行时,我们正在进入一个匿名上下文(通过 push
)来处理 [=91] 的内容=] 正文(或块或其他)。
匿名上下文包含当它看到结束 ]
字符时弹出的规则,两个不同的匹配项以查找函数名称,然后是 [=30= 的上下文中的 include
]、comment
和 block-body
。
当您 include
时,Sublime 从该上下文中获取所有 match
规则,并在您执行插入的位置插入它们的副本,就像您刚刚手动输入它们一样那里。
此外,当 context
中有多个规则可能匹配时,上下文中的第一个 match
规则将被应用(即它 "wins"领带)。
范围keyword.other
适用于来自pragma
上下文和selector
上下文的规则,selector
上下文可以匹配单个%
字符作为关键字。
因此这里的问题是,由于 include c-block
出现在 block-body
上下文的包含列表中的 selector
之后,selector
上下文正在查找并匹配%
C 块规则前的字符可以找到它。
然后解决方案是将 include c-block
的位置移动到该项目之前,以确保它首先匹配:
block-body:
- include: c-block
- include: pragma
- include: selector
- include: literal
- include: block
- include: comment
有了这个,块突出显示更像我们期望的那样:
我能够使用 Regex 前瞻和后视解决类似的问题
- match: ' (?=\{")'
embed: scope:source.json
escape: '(?<=\})$'
我有 Sublime Text 3 Smalltalk sublime-syntax file (YAML),我想为嵌入式 C 代码添加突出显示支持。
smalltalk代码中的inline C
(总是以^%\{
开始,以%\}$
结束)代码
一个简单的例子(不多C
但想要一个简单的例子):
sigABRT
"return the signal number for SIGABRT - 0 if not supported by OS
(the numeric value is not the same across unix-systems)"
%{ /* NOCONTEXT */
#ifdef SIGABRT
RETURN ( __mkSmallInteger(SIGABRT) );
#else
RETURN ( __mkSmallInteger(0) );
#endif
%}
!
Sublime text 中有新功能 embed
(甚至还有一个 example)。
我试过这样做:
- match: '^%\{'
embed: scope:source.c
embed_scope: meta.environment.embedded.c.smalltalk source.c.embedded
escape: '%\}$'
但是,我无法将它正确地合并到我的 current highlighting file 中。
有谁知道如何正确地将一种语言嵌入到另一种语言中?
这个问题有点棘手,因为您提供了一个示例语法定义和一些 Smalltalk 源代码示例,但是提供的代码没有被提供的语法突出显示,因为它的结构不正确。
为了我们的目的,我们假设您提供的 Smalltalk 示例是以下示例。这可能有效也可能无效(自从我使用 Smalltalk 以来已经有很长时间了)但它突出显示了您的语法,所以让我们称其足够好以用于测试目的。
Object subclass: Test [
sigABRT
"return the signal number for SIGABRT - 0 if not supported by OS
(the numeric value is not the same across unix-systems)"
%{ /* NOCONTEXT */
#ifdef SIGABRT
RETURN ( __mkSmallInteger(SIGABRT) );
#else
RETURN ( __mkSmallInteger(0) );
#endif
%}
!
].
你上面提供的语法匹配是正确的,所以我猜你的问题出在你把它放在语法中的什么地方。
所以我们假设在语法定义中我们可能希望在多个地方匹配这些 C 块之一;在这种情况下,我们可能希望在包含匹配项的语法中创建一个新的 context
,以便我们可以在需要的地方 include
:
c-block:
- match: '%\{'
embed: scope:source.c
embed_scope: meta.environment.embedded.c.smalltalk source.c.embedded
escape: '%\}$'
这与您在上面提供的摘录相同,但置于上下文中。因此,假设像这样的块可以出现的第一个地方是块的主体。您的语法中有一个 block-body
上下文,因此我们将 include
粘贴到它的末尾以包含这个新上下文:
block-body:
- include: pragma
- include: selector
- include: literal
- include: block
- include: comment
- include: c-block
然而,这并没有达到预期的效果;突出显示不正确:
很明显,至少从 C 注释开始,可能更早,突出显示就出错了。如果在光标位于注释上时使用 Tools > Developer > Show Scope Name
,您可以看到分配的范围是 source.smalltalk entity.name.function
,这意味着语法将 C 注释开头视为方法名称。
%{
结构似乎也没有正确突出显示,检查显示 %
字符的范围是 source.smalltalk keyword.other
。
所以实际上目前的问题是,有了上面的定义,而不是将 %{
视为开始 C 块,它被视为关键字,如果它是关键字,那么规则匹配 C 块根本不会触发。
如果您查看语法,main
上下文如下所示:
main:
- match: '([a-zA-Z][a-zA-Z0-9]*)\s*(subclass:)\s*([a-zA-Z][a-zA-Z0-9]*)\s*\['
captures:
1: entity.other.inherited-class
2: keyword.other
3: entity.name.type
push:
- match: '\]'
pop: true
- include: pragma
- match: '(([a-zA-Z][a-zA-Z0-9]*:)|[+\-\/\*~<>=@%|&?!.,:;^]+)\s*([a-zA-Z][a-zA-Z0-9]*)'
captures:
1: entity.name.function
3: variable.other
- match: "([a-zA-Z][a-zA-Z0-9]*)"
scope: entity.name.function
- include: block
- include: comment
- include: block-body
这些规则表明,当我们看到以 BaseClass subclass: SubClass [
开头的行时,我们正在进入一个匿名上下文(通过 push
)来处理 [=91] 的内容=] 正文(或块或其他)。
匿名上下文包含当它看到结束 ]
字符时弹出的规则,两个不同的匹配项以查找函数名称,然后是 [=30= 的上下文中的 include
]、comment
和 block-body
。
当您 include
时,Sublime 从该上下文中获取所有 match
规则,并在您执行插入的位置插入它们的副本,就像您刚刚手动输入它们一样那里。
此外,当 context
中有多个规则可能匹配时,上下文中的第一个 match
规则将被应用(即它 "wins"领带)。
范围keyword.other
适用于来自pragma
上下文和selector
上下文的规则,selector
上下文可以匹配单个%
字符作为关键字。
因此这里的问题是,由于 include c-block
出现在 block-body
上下文的包含列表中的 selector
之后,selector
上下文正在查找并匹配%
C 块规则前的字符可以找到它。
然后解决方案是将 include c-block
的位置移动到该项目之前,以确保它首先匹配:
block-body:
- include: c-block
- include: pragma
- include: selector
- include: literal
- include: block
- include: comment
有了这个,块突出显示更像我们期望的那样:
我能够使用 Regex 前瞻和后视解决类似的问题
- match: ' (?=\{")'
embed: scope:source.json
escape: '(?<=\})$'