У меня есть простой пример модели, где я хотел бы сгенерировать имена для объектов правила 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()