1

I try to show a minimal working example that describes my problem:

Grammar

This is the xtext grammar I created for this example. (The real grammar of course is much more complex and also involves an advanced expression-language)

grammar org.example.dsl.DSL with org.eclipse.xtext.common.Terminals

generate dsl "http://www.example.org/dsl/DSL"

Model:
  elements+=Declaration*
;

QualifiedName:
  ID ('.' ID)*
;

Declaration:
  SimpleTypeDeclaration |
  SectionDeclaration |
  FieldDeclaration
;

SimpleTypeDeclaration:
  "type" name=ID "=" primitive=IntegerType
;

IntegerType
  {IntegerType} "int"
;

SectionDeclaration:
  "section" name=ID "{"
    elements+=FieldDeclaration*
  "}"
;

TypeDeclaration:
  SimpleTypeDeclaration |
  SectionDeclaration
;

FieldDeclaration:
  name=ID ":" type=[TypeDeclaration|QualifiedName] ("=" value=ValueExpression)?
;

ValueExpression:
  FieldReference |
  SimpleValue
;

FieldReference:
  ref=[FieldDeclaration|QualifiedName]
;

SimpleValue:
  {SimpleValue} "sentinel"
;

Example-Code in Example-Language

This is some example code in the language I described above.

type Foo = int

section A {
  foo: Foo = sentinel
}

section B {
  a: A

  // here I want to assign the value of a subfield of `a`
  // to fubar
  fubar: Foo = a.foo // crucial point
} 

Global Index of the Example-Code snippet

The default Indexer of the Example-Code snippet would generate the following global-scope index for referencing:

[Foo, A, A.foo, B, B.a, B.fubar]

So with the correct scope I would be able to reference all those objects by these identifiers in my code on reference-resolution.

But the crucial point in the code snippet will not be resolved, because B.a.foo respectively a.foo will not be in the index.

What I thought of and tried so far (incomplete solutions)

  1. I thought of customizing the Index, so that it would additionally put B.a.foo into the index.

    • but that would pollute the index with potentially so many unnecessary resource URIs that I never would want to be referencing from the global scope.
    • (e.g. I just want to be able to reference a fields subfields from within the section I'm referencing it from)
  2. Create a new Rule in the grammar called Selection => make qualified selection of fields explicit by providing a custom ScopeProvider. But there are some Problems I encountered:

    • If I still provide the possibility to reference everything via QualifiedNames the grammar and resolution always think it is a typereference as before and will not ask my custom scopeprovider to provide the reference for the Selection rule, which overloads the dot-operator (.)
    • If I remove the referencing mechanism [TypeDeclaration|QualifiedName] replacing it with a [TypeDeclaration|ID] I would have to customize the scoping for every base type and subreference and would not leverage the powerful default qualified-name-resolution of xtext.

My Question now

Does anybody know about a standard or best solution to the problem I descibed?

Jan
  • 2,025
  • 17
  • 27
  • 1
    i am not sure if i understood your problem with scoping. where is the conflict with your new rule? the FieldReference will allways be a chain right? and never be a global qualified name? here is a blog how this is usually done https://dietrich-it.de/xtext/2013/05/18/xtext-and-dot/path-expressions/ – Christian Dietrich Aug 05 '20 at 14:05
  • Yes I need to clarify my problem, you're correct. But you understood it perfectly well. I was really close to the solution you show in your link. :D Thanks to you everything is working now as expected. Now I just have to see how to reimplement the `importedNamespace` stuff, that it works as expected again. Thanks a ton! – Jan Aug 05 '20 at 16:54
  • 1
    as the scoping cares about part 2-n of the chain the importedNamespace should perfectly file for the first element / other references – Christian Dietrich Aug 06 '20 at 05:29
  • Yes you're right of course. Also the `importedNamespace` is still working. The only thing that is really not working now is my qualified-package-definitions. I have a rule to define a qualified package at the top of a model file. Which of course now is not working anymore because I completely removed `QualifiedName` references from my language. I will try to formulate a question about that and link it here if I cannot see a solution (I'm thinking of a rule like `Package: Root {Qualified.lhs=current} "." rhs=Sub;` with according rules `Root` and `Sub`.. with a custom name provider then. – Jan Aug 06 '20 at 05:38
  • what i dont get: why dont you keep the qualified stuff as you had it for everything but FieldReference – Christian Dietrich Aug 06 '20 at 07:20
  • Because the referencing via `dot` qualified names is part of the expression-language. So there exists one rule like `Selection returns Expression: Instantiation ( {Selection.head=current} '.' tail=Instantiation)*` in the chain of permitted expressions. If in the atomic rules in the end, `Instantiation` could be replaced by a ref like `[Foo|QualifiedName]` then it would break the customized dot-selection because it would always first parse the dot-chain as a `QualifiedName` so e.g. `foo.bar` is resolved to a reference to `Foo` but should be a reference to some Field `foo` with subfield `bar`. – Jan Aug 06 '20 at 07:30
  • Or the other way around it would always parse `foo.bar` as `foo` being a reference to a `FieldDeclaration` but I wanted it to be a parsed as a `QualifiedName` reference `foo.bar` to some `TypeDeclaration` `bar` in a package named `foo` – Jan Aug 06 '20 at 07:41
  • i dont think this is easily possible. you would need come custom treatment for the dotexpression if a.b.C can be a->b->C and type a.b.C – Christian Dietrich Aug 06 '20 at 11:22
  • Ok thank you very much for all your input. I will try to work on the issue. – Jan Aug 07 '20 at 06:42

0 Answers0