Как правильно встроить другой язык в мое текущее определение языка?

У меня есть Файл возвышенного синтаксиса Smalltalk (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
%}
!

В Sublime text появилась новая функция embed (даже с пример).

Я пытался сделать что-то вроде этого:

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

Однако мне не удалось правильно включить его в свой текущий файл выделения.

Кто-нибудь знает, как правильно встроить один язык в другой?

Прекратите добавлять несвязанные теги. это явно не о языке Си, а о том, как настроить редактор.

too honest for this site 19.07.2018 20:48

@Olaf Ты прочитал вопрос? Речь идет о подсветке синтаксиса языка C, который встроен в Smalltalk, да в текстовый редактор Sublime. Как может выделение языка C не иметь отношения к C?

tukan 19.07.2018 21:11

Потому что неважно, на каком это языке. С таким же успехом может быть Brainfuck, это вопрос о том, как настроить редактор для смешивания двух стилей выделения в одном исходном коде. Я сильно сомневаюсь, что вы собираетесь полностью написать свой собственный файл подсветки. Даже в этом случае остается спорным, актуален ли тег C.

too honest for this site 19.07.2018 21:29

У нас уже есть накопившиеся теги, которые нужно записать, пожалуйста, не добавляйте больше ненужных. Создавать собственный тег только для этого вопроса не имеет смысла. Меньше, так как вы не добавляли некоторую информацию о том, о чем тег и как его использовать. Если быть более конкретным: это не поможет, вы уже отметили smalltalk и возвышенное, каждый, кто знает достаточно, чтобы, возможно, помочь, поймет, что вы имеете в виду.

too honest for this site 20.07.2018 01:23

@Olaf Во-первых - я добавил информацию о теге Smalltalk / X, но он должен быть одобрен некоторыми людьми, имеющими достаточно репутацию для этого. Вы должны проверить, прежде чем писать "..вы не добавляли какую-то информацию, что за тег ...". Тег smalltak-x будет использоваться в моих будущих вопросах, поскольку он имеет некоторые довольно специфические особенности среди сред Smalltalk; ваше удаление не имеет смысла. Во-вторых, это может быть Brainfuck, но это не C, поэтому тег не имеет значения (я бы отметил его Brainfuck). С другой стороны, вы правы в том, что это можно рассматривать как руководство для кого-то со схожими потребностями.

tukan 20.07.2018 09:07

@Olaf Из любопытства, если не имеет значения, на каком языке вы оставили тег smalltalk? (Чтобы понять ваш алгоритм). Надеюсь, мне не придется переписывать информацию о smalltalk-x.

tukan 20.07.2018 09:47
вздох Поскольку я доверял вам, код - это своего рода небольшой разговор. Это установленный тег. Прочтите мой предыдущий комментарий еще раз внимательно и полностью.
too honest for this site 20.07.2018 11:16

@ Олаф Хорошо. Последний пункт. Код - это Smalltalk и Inline C, который уникален в мире Smalltalk. Я не знаю другой реализации Smalltalk, в которой вы могли бы видеть / работать с кодом C непосредственно из среды. Спасибо, что поделились своим мнением. Хорошего дня / ночи.

tukan 20.07.2018 13:13
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
8
288
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Этот вопрос немного сложен, потому что вы предоставили образец определения синтаксиса и образец некоторого исходного кода 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

Однако это не дает желаемого результата; выделение неверно:

Incorrect Highlighting

Очевидно, что выделение идет неправильно, начиная по крайней мере с начала комментария 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) для обработки содержимого тела класса (или блока, или чего-то еще).

Анонимный контекст содержит правило, которое выскакивает, когда он видит закрывающий символ ], два разных совпадения для поиска имени функции, затем include в контекстах для block, comment и block-body соответственно.

Когда вы используете include, Sublime берет все правила match из этого контекста и вставляет их копию в том месте, где вы делаете вставку, как если бы вы только что вручную ввели их туда.

Вдобавок, когда в context есть несколько правил, которые потенциально могут совпадать, первое правило match в контексте является тем, которое применяется (т.е. оно «выигрывает» в счете).

Область действия keyword.other применяется в правилах из контекста pragma, а также из контекста selector, и контекст selector может соответствовать одному символу % в качестве ключевого слова.

Таким образом, проблема здесь в том, что, поскольку include c-block появляется после selector в списке включения для контекста block-body, контекст selector находит и сопоставляет символ % до того, как правило для блока C.

Тогда решением было бы сместить расположение include c-block до этого элемента, чтобы убедиться, что он совпадает первым:

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

После этого блок выделяется больше, чем мы ожидали:

Correct Highlighting

Вы правы насчет того, что «... предоставленный код не выделяется предоставленным синтаксисом, потому что он не структурирован должным образом ...» Ну, это было частью моей проблемы. Я также пометил это с помощью "Smalltalk-x" (Олаф (теперь называемый: "Отточить для этого сайта" не согласился и удалил его), что является уникальным в этом вопросе. Он смешивает код Smalltalk с C (который затем генерирует смешанный код Ваше объяснение безупречно и отвечает на мой вопрос. Вы даже заставили меня задуматься о том, чтобы исправить мой неисправный файл syntax.

tukan 26.07.2018 12:39

Я улучшу тестовый файл и определение.

tukan 26.07.2018 12:43

Я воссоздал файл выделения, и он работает правильно. Не могли бы вы помочь мне с моим новым вопросом: superuser.com/questions/1345947/…? Мне пришлось разместить его на суперпользователе, так как он не включает никакого программирования.

tukan 03.08.2018 20:36

Мне удалось обойти аналогичную проблему с помощью Regex lookahead и lookbehind.

    - match: ' (?=\{")'
      embed: scope:source.json
      escape: '(?<=\})$'

Другие вопросы по теме