代码之家  ›  专栏  ›  技术社区  ›  tukan

如何正确地将另一种语言嵌入到我当前的语言定义中?

  •  2
  • tukan  · 技术社区  · 8 年前

    我有 Smalltalk sublime-syntax file (YAML) 对于Sublime Text 3,我想添加对嵌入式C代码的突出显示支持。

    这个 inline C (总是以 ^%\{ 结束于 %\}$ )smalltalk代码中的代码。

    一个简单的例子(不多 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
    %}
    !
    

    有新功能 embed 在崇高的文本中(甚至 example )

    我试着这样做:

    - match: '^%\{'
      embed: scope:source.c
      embed_scope: meta.environment.embedded.c.smalltalk source.c.embedded
      escape: '%\}$'
    

    但是,我无法将它正确地纳入我的 current highlighting file 是的。

    有人知道如何正确地将一种语言嵌入到另一种语言中吗?

    1 回复  |  直到 7 年前
        1
  •  1
  •   OdatNurd    7 年前

    这个问题有点棘手,因为您提供了一个示例语法定义和一些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 在你的语法中的上下文,所以我们坚持 包括 在它的末尾包括这个新的上下文:

    block-body:
      - include: pragma
      - include: selector
      - include: literal
      - include: block
      - include: comment
      - include: c-block
    

    但是,这并没有达到预期的结果;突出显示不正确:

    Incorrect Highlighting

    很明显,至少从c注释开始,可能更早,突出显示就出错了。如果你使用 Tools > Developer > Show Scope Name 当光标在注释上时,可以看到指定的范围是 source.smalltalk entity.name.function ,这意味着语法将C comment start视为方法名。

    它看起来也像 %{ 构造未正确突出显示,并且检查显示 % 字符是 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 )处理类主体(或块或其他)的内容。

    匿名上下文包含在看到关闭时弹出的规则 ] 字符,两个不同的匹配项来查找函数名,然后 包括 关于 block 我是说, comment 块体 分别是。

    当你 包括 ,Sublime将 match 从该上下文中的规则,并在执行插入操作时插入它们的副本,就好像您刚刚在那里手动输入了它们一样。

    此外,当 上下文 可能会匹配,第一个 比赛 上下文中的规则是应用的规则(即它“赢得”平局)。

    范围 keyword.other 在规则中应用 pragma 上下文以及 selector 上下文,以及 选择器 上下文可以匹配单个 % 字符作为关键字。

    因此这里的问题是 include c-block 出现在 选择器 在包含列表中 块体 上下文,the 选择器 上下文正在查找并匹配 % 在C块的规则找到它之前的字符。

    解决方法是移动 包括C块 在该项目之前确保它首先匹配:

    block-body:
      - include: c-block
      - include: pragma
      - include: selector
      - include: literal
      - include: block
      - include: comment
    

    在这个位置上,块的突出显示更像我们所期望的:

    Correct Highlighting