<< git: get short hash of remote repo | Home | cmake,emscripten and c++17 >>

text(X)text or 'textX - lightweight xtext alternative for python'

Just stumpled over textX an xText inspired python-toolbox for creating DSLs. Super simple to use. I love xText but it can be really a pain in the ass here an there. Mainly because you (at least me) always forget about the internal concept and/or structure. Especially how to wire what and how to get the dependency injection working.... :D

I actually wanted to give the xText Theia-Workflow a go but instead stumpled over textX. It is a super lightweight DSL generator and AST-Parser and seems to have an addon to create Visual Studio Code addons via Language Server Protocol. Didn't tried that, yet.

A grammar would look like this (very similiar to xText):

/*
  Entity DSL grammar.
*/

EntityModel:
    types*=SimpleType       // At the beginning of model we can define
                            // zero or more simple types.
    entities+=Entity        // Each model has one or more entities.
;

Entity:
    'entity' name=ID '{'
        properties+=Property // Each entity has one or more properties.
    '}'
;

Property:
    name=ID ':' type=[Type]     // type is a reference to Type instance.
                                // There are two built-in simple types 
                                // registered on meta-model in entity_test.py
;

// Type can be SimpleType or Entity
Type:
    SimpleType | Entity
;

SimpleType:
    'type' name=ID
;

// Special rule for comments. Comments start with //
Comment:
    /\/\/.*$/
;

A sample Model using this grammar:

entity Person {
  name : string       // A comment is everything after // to the end of line
  address: Address    // It is defined by the Comment rule in the grammar
  age: integer        // integer and string are built-in objects
}                     // See entity_test.py

entity Address {
  street : string
  city : string
  country : string
}

And to let it work. This couple of lines including custom type (SimpleType),predefined data, obviously parsing and and simple generation:

from os import mkdir
from os.path import exists, dirname, join
from textx import metamodel_from_file

this_folder = dirname(__file__)


class SimpleType(object):
    def __init__(self, parent, name):
        self.parent = parent
        self.name = name

    def __str__(self):
        return self.name


def get_entity_mm():
    """
    Builds and returns a meta-model for Entity language.
    """
    type_builtins = {
            'integer': SimpleType(None, 'integer'),
            'string': SimpleType(None, 'string')
    }
    entity_mm = metamodel_from_file(join(this_folder, 'entity.tx'),
                                    classes=[SimpleType],
                                    builtins=type_builtins)

    return entity_mm


def main(debug=False):

    # Instantiate the Entity meta-model
    entity_mm = get_entity_mm()

    def javatype(s):
        """
        Maps type names from SimpleType to Java.
        """
        return {
                'integer': 'int',
                'string': 'String'
        }.get(s.name, s.name)

    # Create the output folder
    srcgen_folder = join(this_folder, 'srcgen')
    if not exists(srcgen_folder):
        mkdir(srcgen_folder)

    # Build a Person model from person.ent file
    person_model = entity_mm.model_from_file(join(this_folder, 'person.ent'))

    # Generate Java code
    for entity in person_model.entities:
        # For each entity generate java file
        with open(join(srcgen_folder,
                      "%s.java" % entity.name.capitalize()), 'w') as f:
            f.write("%s.java" % entity.name)


if __name__ == "__main__":
    main()

Would have to port my own templating engine, but I guess with python that would be super easy. Definitely interesting...

More examples: https://github.com/textX/textX/tree/master/examples
Documentation: http://textx.github.io/textX/stable/

Home