Как токенизировать текст, используя грамматики textmate в python?

Я хотел бы узнать, как использовать грамматики textmate для идентификации / извлечения / выбора областей из заданного текста.

Я не нашел ни одной библиотеки Python, готовой к использованию после многих часов поиска в Google... вместо этого я просто нашел несколько решений, написанных на других языках, таких как:

Я заинтересован в решении на python, и портирование перечисленных выше на python было бы вне области видимости... Я думаю, что мой лучший шанс будет напрямую пытаться понять, как реализовать эти алгоритмы области видимости с помощью msyelf.

Есть 2 метода, которые я хотел бы узнать, как реализовать самостоятельно (взят из API SublimeText, который я не могу использовать напрямую, так как код не представлен в виде библиотеки):

  • extract_scope(point)Возвращает экстент имени области синтаксиса, назначенного символу в данной точке.
  • scope_name(point)Возвращает имя области синтаксиса, назначенное символу в данной точке.

На данный момент у меня есть этот скелет (не реализованный, потому что я не знаю, как):

ini.json

{
    "fileTypes": [
        "ini",
        "INI",
        "inf",
        "INF",
        "reg",
        "REG",
        "lng",
        "cfg",
        "CFG",
        "url",
        "URL",
        ".editorconfig"
    ],
    "name": "INI",
    "patterns": [
        {
            "captures": {
                "1": {
                    "name": "punctuation.definition.comment.ini"
                }
            },
            "match": "^\\s*(;|#).*$\\n?",
            "name": "comment.line.semicolon.ini"
        },
        {
            "captures": {
                "1": {
                    "name": "punctuation.definition.section.ini"
                },
                "2": {
                    "name": "entity.section.ini"
                },
                "3": {
                    "name": "punctuation.definition.section.ini"
                }
            },
            "match": "^\\s*(\\[)(.*?)(\\])",
            "name": "meta.tag.section.ini"
        },
        {
            "captures": {
                "1": {
                    "name": "meta.property.ini"
                },
                "10": {
                    "name": "comment.declarationline.semicolon.ini"
                },
                "2": {
                    "name": "punctuation.definition.quote.ini"
                },
                "3": {
                    "name": "keyword.name.ini"
                },
                "4": {
                    "name": "punctuation.definition.quote.ini"
                },
                "5": {
                    "name": "punctuation.definition.equals.ini"
                },
                "6": {
                    "name": "meta.value.ini"
                },
                "7": {
                    "name": "punctuation.definition.quote.ini"
                },
                "8": {
                    "name": "string.name.value.ini"
                },
                "9": {
                    "name": "punctuation.definition.quote.ini"
                }
            },
            "match": "^(\\s*([\"']?)(.+?)(\\2)\\s*(=))?\\s*(([\"']?)(.*?)(\\7))\\s*(;.*)?$\\n?",
            "name": "meta.declaration.ini"
        }
    ],
    "scopeName": "source.ini",
    "uuid": "957acd74-6d7c-4732-a25b-5f66a1e637cd"
}

mcve.py

import json
import textwrap
from oniguruma import onigmo
from pathlib import Path


TMLANGUAGE = json.loads(Path("ini.json").read_text())

SAMPLE = textwrap.dedent("""\
    [title1]

    #=

    a=bcd

    #=

    e=11


    [title2]

    #=e=11
""")


def scope_name(text, pt):
    raise NotImplementedError


def extract_scope(text, pt):
    raise NotImplementedError


if __name__ == '__main__':
    for i, c in enumerate(SAMPLE):
        try:
            print("{:<20}{:<80}{}".format(
                repr(c),
                repr(extract_scope(SAMPLE, i))),
                scope_name(SAMPLE, i)
            )
        except NotImplementedError as e:
            print("{:<20}{:<80}{}".format(repr(c), "UNIMPLEMENTED", "UNIMPLEMENTED"))

Идея заключалась бы в использовании Onigmo в качестве движка регулярных выражений, как если бы я правильно понял, что Oniguruma используется этими файлами tmLanguage.

Чтобы полностью понять, чего я пытаюсь достичь, позвольте мне опубликовать то, что вы хотите получить, extract_scope а также scope_name функции должны быть в предоставленном SAMPLE тексте (когда они станут реализованными):

'['                 '[title1'                                                                       source.ini meta.tag.section.ini punctuation.definition.section.ini 
't'                 'title1'                                                                        source.ini meta.tag.section.ini entity.section.ini 
'i'                 'title1'                                                                        source.ini meta.tag.section.ini entity.section.ini 
't'                 'title1'                                                                        source.ini meta.tag.section.ini entity.section.ini 
'l'                 'title1'                                                                        source.ini meta.tag.section.ini entity.section.ini 
'e'                 'title1'                                                                        source.ini meta.tag.section.ini entity.section.ini 
'1'                 'title1'                                                                        source.ini meta.tag.section.ini entity.section.ini 
']'                 'title1]'                                                                       source.ini meta.tag.section.ini punctuation.definition.section.ini 
'\n'                '[title1]\n\n#=\n\na=bcd\n\n#=\n\ne=11\n\n\n[title2]\n\n#=e=11'                 source.ini 
'\n'                '\n'                                                                            source.ini meta.declaration.ini 
'#'                 '#=\n'                                                                          source.ini comment.line.semicolon.ini punctuation.definition.comment.ini 
'='                 '#=\n'                                                                          source.ini comment.line.semicolon.ini 
'\n'                '#=\n'                                                                          source.ini comment.line.semicolon.ini 
'\n'                '\na=bcd\n\n'                                                                   source.ini meta.declaration.ini 
'a'                 'a='                                                                            source.ini meta.declaration.ini meta.property.ini keyword.name.ini 
'='                 'a='                                                                            source.ini meta.declaration.ini meta.property.ini punctuation.definition.equals.ini 
'b'                 '=bcd'                                                                          source.ini meta.declaration.ini meta.value.ini string.name.value.ini 
'c'                 '=bcd'                                                                          source.ini meta.declaration.ini meta.value.ini string.name.value.ini 
'd'                 '=bcd'                                                                          source.ini meta.declaration.ini meta.value.ini string.name.value.ini 
'\n'                '\na=bcd\n\n'                                                                   source.ini meta.declaration.ini 
'\n'                '\na=bcd\n\n'                                                                   source.ini meta.declaration.ini 
'#'                 '#=\n'                                                                          source.ini comment.line.semicolon.ini punctuation.definition.comment.ini 
'='                 '#=\n'                                                                          source.ini comment.line.semicolon.ini 
'\n'                '#=\n'                                                                          source.ini comment.line.semicolon.ini 
'\n'                '\ne=11\n\n\n'                                                                  source.ini meta.declaration.ini 
'e'                 'e='                                                                            source.ini meta.declaration.ini meta.property.ini keyword.name.ini 
'='                 'e='                                                                            source.ini meta.declaration.ini meta.property.ini punctuation.definition.equals.ini 
'1'                 '=11'                                                                           source.ini meta.declaration.ini meta.value.ini string.name.value.ini 
'1'                 '=11'                                                                           source.ini meta.declaration.ini meta.value.ini string.name.value.ini 
'\n'                '\ne=11\n\n\n'                                                                  source.ini meta.declaration.ini 
'\n'                '\ne=11\n\n\n'                                                                  source.ini meta.declaration.ini 
'\n'                '\ne=11\n\n\n'                                                                  source.ini meta.declaration.ini 
'['                 '[title2'                                                                       source.ini meta.tag.section.ini punctuation.definition.section.ini 
't'                 'title2'                                                                        source.ini meta.tag.section.ini entity.section.ini 
'i'                 'title2'                                                                        source.ini meta.tag.section.ini entity.section.ini 
't'                 'title2'                                                                        source.ini meta.tag.section.ini entity.section.ini 
'l'                 'title2'                                                                        source.ini meta.tag.section.ini entity.section.ini 
'e'                 'title2'                                                                        source.ini meta.tag.section.ini entity.section.ini 
'2'                 'title2'                                                                        source.ini meta.tag.section.ini entity.section.ini 
']'                 'title2]'                                                                       source.ini meta.tag.section.ini punctuation.definition.section.ini 
'\n'                '[title1]\n\n#=\n\na=bcd\n\n#=\n\ne=11\n\n\n[title2]\n\n#=e=11'                 source.ini 
'\n'                '\n'                                                                            source.ini meta.declaration.ini 
'#'                 '#=e=11'                                                                        source.ini comment.line.semicolon.ini punctuation.definition.comment.ini 
'='                 '#=e=11'                                                                        source.ini comment.line.semicolon.ini 
'e'                 '#=e=11'                                                                        source.ini comment.line.semicolon.ini 
'='                 '#=e=11'                                                                        source.ini comment.line.semicolon.ini 
'1'                 '#=e=11'                                                                        source.ini comment.line.semicolon.ini 
'1'                 '#=e=11'                                                                        source.ini comment.line.semicolon.ini 

Я выбрал.ini tmLanguage, так как он кажется одним из самых простых в мире, но в идеале я хотел бы иметь возможность загружать и использовать любой тип tmLanguage.

ВОПРОС: Не могли бы вы предоставить реализацию (или точное правильное объяснение, которое я смог реализовать самостоятельно) обоих scope_name а также extract_scope функции? Реализации должны давать разумный аналогичный результат, чем опубликованный выше.

0 ответов

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