textX: Как генерировать имена объектов с помощью ObjectProcessors?

У меня есть простой пример модели, где я хотел бы генерировать имена для объектов Position правило, которому не дали имя с as <NAME>, Это необходимо для того, чтобы я мог найти их позже с помощью встроенного поставщика области FQN.

Моя идея состоит в том, чтобы сделать это в position_name_generator объектный процессор, но он будет вызван только после анализа всей модели. Я не очень понимаю причину этого, так как к тому времени мне понадобится Position объект в Projectобъекты уже созданы, но обработчик объектов вызываться не будет.

Другая идея заключается в том, чтобы сделать это в провайдере настраиваемой области для Position.location который сначала будет производить генерацию имени, а затем использовать встроенный FQN, чтобы найти Location объект. Хотя это сработает, я считаю это хакерским и предпочел бы избежать этого.

Каков будет textX способ решения этой проблемы?

(Пожалуйста, примите во внимание, что это только небольшой пример. На самом деле аналогичная функциональность требуется для довольно большой и сложной модели. Изменить это поведение с помощью сгенерированных имен невозможно, так как это требование.)

import textx


MyLanguage = """
    Model
        :   (locations+=Location)*
            (employees+=Employee)*
            (positions+=Position)*
            (projects+=Project)*
        ;

    Project
        :   'project' name=ID
            ('{'
                ('use' use=[Position])*
            '}')?
        ;

    Position
        :   'define' 'position' employee=[Employee|FQN] '->' location=[Location|FQN] ('as' name=ID)?
        ;

    Employee
        :   'employee' name=ID   
        ;

    Location
        :   'location' name=ID
            ( '{'
                (sub_location+=Location)+
            '}')?
        ;

    FQN
        :   ID('.' ID)*
        ;

    Comment:
      /\/\/.*$/
    ;                
"""

MyCode = """
    location Building
    {
        location Entrance
        location Exit
    }

    employee Hans
    employee Juergen

    // Shall be referred to with the given name: "EntranceGuy"
    define position Hans->Building.Entrance as EntranceGuy 
    // Shall be referred to with the autogenerated name: <Employee>"At"<LastLocation>
    define position Juergen->Building.Exit                  

    project SecurityProject
    {
        use EntranceGuy
        use JuergenAtExit
    }
"""


def position_name_generator(obj):
    if "" == obj.name:
        obj.name = obj.employee.name + "At" + obj.location.name


def main():
    meta_model = textx.metamodel_from_str(MyLanguage)
    meta_model.register_scope_providers({
        "Position.location": textx.scoping.providers.FQN(),
    })

    meta_model.register_obj_processors({
        "Position": position_name_generator,
    })

    model = meta_model.model_from_str(MyCode)
    assert model, "Could not create model..."


if "__main__" == __name__:
    main()

0 ответов

Каков способ textx решить эту проблему...

Описываемый вами вариант использования - это определение имени объекта на основе других элементов модели, включая ссылку на другие элементы модели. В настоящее время это не является частью каких-либо тестов и сценариев использования, включенных в наш набор тестов и документ textx.

Обработчики объектов выполняются на определенных этапах во время построения модели (см. http://textx.github.io/textX/stable/scoping/). В описываемой настройке они выполняются после эталонного разрешения. Так как само имя, которое должно быть определено / выведено, требуется для разрешения ссылок, объектные процессоры здесь не могут использоваться (даже если мы позволяем контролировать, когда процессоры объектов выполняются, до или после разрешения области видимости, описанная настройка все равно не будет работать).

Учитывая динамику загрузки модели (см. http://textx.github.io/textX/stable/scoping/), решение находится внутри поставщика области видимости. (как вы предложили). Здесь мы позволяем контролировать порядок разрешения ссылок, так что ссылки на объект, названный настраиваемой процедурой, откладываются до тех пор, пока ссылки, необходимые для вывода / определения имени, не будут разрешены.

Возможный обходной путь

Предварительный набросок того, как можно решить ваш вариант использования, обсуждается в https://github.com/textX/textX/pull/194 (с прикрепленной проблемой https://github.com/textX/textX/issues/193). Этот PR textx содержит версию scoping.py, которую вы, вероятно, могли бы использовать для своего проекта (просто скопируйте и переименуйте модуль). Полноценное решение могло бы быть частью textx TEP-001, где мы планируем сделать область видимости более управляемой для конечного пользователя.

Игра с этой очень интересной проблемой открыла мне новые аспекты фреймворка textx.

  • имена, зависящие от содержимого модели (включая неразрешенные ссылки). Это разрешение имен, которое может быть отложено (в указанном PR, см. Ниже) с точки зрения нашей логики разрешения ссылок.
  • Еще более интересны последствия этого: что происходит со ссылками, указывающими на места, где обнаруживаются неразрешенные имена? Здесь мы должны отложить процесс разрешения ссылок, потому что мы не можем знать, может ли имя совпадать при разрешении...

Ваш пример включен: https://github.com/textX/textX/blob/analysis/issue193/tests/functional/test_scoping/test_name_resolver/test_issue193_auto_name.py

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