eclipse / epsilon

Epsilon is a family of Java-based scripting languages for automating common model-based software engineering tasks, such as code generation, model-to-model transformation and model validation, that work out of the box with EMF (including Xtext and Sirius), UML (including Cameo/MagicDraw), Simulink, XML and other types of models.
https://eclipse.org/epsilon
Eclipse Public License 2.0
55 stars 11 forks source link

Add support for ATL-style partial enumeration literals #41

Closed agarciadom closed 12 months ago

agarciadom commented 1 year ago

I have been working on an Epsilon solution to the TTC 2023 KMEHR to FHIR case, and while porting their ATL transformation to ETL, I noticed that they had these nice #enum literals which did not require fully specifying the model and type (E*L would normally need Model!Type#enum).

We had discussed two approaches:

  1. Treat it in the same way as type references, where we can give a warning if the partial reference is ambiguous.
  2. Make property setters smarter, by having them check these partially-specified enum literals against the type of the field being set.

I thought option 2 would result in fewer risks of ambiguous references, but @kolovos raised the issue wouldn't translate well to multi-valued enum-typed fields. Looks like option 1 would be best for now.

This will need adding some acceptance tests, tweaking the E*L grammar, and changing how those enum literals are evaluated.

agarciadom commented 1 year ago

I've got it to almost work, except for two HUTN tests where an internal EVL script is oddly parsed incorrectly.

There seems to be some parsing ambiguity between featureCall, pathName and the new enumLiteral rule. I've been trying various ways to tweak the parsing, but I haven't been able to get it to work yet.

I've added an EVL unparser test which reproduces the issue. This minimal EVL script is parsed like this:

image

agarciadom commented 1 year ago

I got this to work after a lot of debugging :-D. Turns out the parser was barreling into the enumLiteral rule and couldn't quite backtrack correctly if it hit a . instead of a #. I have used a bit of custom lookahead in the primitiveExpression, and now it is passing all tests:

primitiveExpression 
    :   literalSequentialCollection | literalMapCollection | literal
        | ((NAME '!')? packagedType? '#') => enumLiteral
        | featureCall | collectionType |
        pathName | specialType | logicalExpressionInBrackets | newExpression | variableDeclarationExpression
    ;

I'll submit a PR for it now.