textx

Read literal from meta model


I want to ask if it is possible to read - from my Python code - a literal which I have defined in the meta model. This may be best explained with an example. Lets say this is my meta model (inspired by the Entitiy example):

EntityModel:
  entities+=Entity
;

Entity:
  EntityKeyword name=ID '{'
    attributes+=Attribute
  '}'
;

EntityKeyword:
  'entity'
;

Now, if I parse this I will have access to whatever entities which were defined in the input file. But what I also want to be able to is to read the 'entity' literal which is defined in the EntityKeyword rule. I am trying to do this in order to avoid having to hardcode the value ('entity') in my own code.

I have not been able to find a way to do this. Is it possible?

I have read through the documentation and also tried with build-in objects. I did not have any luck.

I hope I make any sense.

Thanks.

UPDATE:

Thanks for the answers - and sorry for my late respons.

I see now that my example was bad. I am sorry for that.

I have toyed around with textX and read some more of the documentation, and came across this section:

"textX integrates with Python typing system. In textX there is no keyword returns. The class used for the rule will be dynamically created Python class for all non-match rules. Language designer can provide class using user classes registration on meta-model. If the rule is of [match type] than it will always return Python string or some of base Python types for BASETYPES inherited rules." Types used for rules

The part bolded out sounds a lot like what I am trying to achieve. I will try and do this but would otherwise greatly appreciate an example of this - if you have got the time for it.

Regards DonHaugaard


Solution

  • So, I found a solution to my issue.

    What was my issue? I wanted to avoid hardcoding any literal in my meta model. E.g.

    EntityKeyword:
      'entity'
    ;
    

    is a simple match type class that tries to match the literal 'entity'. If this keyword is the name of an optional parameter to an object, then I would have to hardcode the keyword in my Python source code when doing a lookup "hasattr(obj, 'entity')". This means I have a keyword value to maintain in 2 places - in my meta model and in my source code.

    The solution I found to this is simple, really. I just load the meta model from a string using "metamodel_from_str()". How would this look?:

    from string import Template
    from textx.metamodel import metamodel_from_str
    
    EXTEND_KEYWORD = 'entity'  
    GRAMMAR=Template("""
    EntityKeyword:
        '$ext_keyword'
    ;
    """).substitute(ext_keyword=EXTEND_KEYWORD)
    
    stackoverflow_mm = metamodel_from_str(GRAMMAR)
    

    What I do here is define my meta model as a string and use string.Template (https://docs.python.org/3/library/string.html#template-strings) to substitute any keywords. Afterwards I am able to load the meta model as a string. Now I only have to maintain a single literal (the attribute "EXTEND_KEYWORD") and I am free to do "hasattr(obj, EXTEND_KEYWORD)".

    A downside to this approach is of course that the meta language can be polluted with various escapes ($$) since I am using string.Template to substitute any keywords.

    If the meta language is big it might make more sense to write it in a separate file and load it as a string.