0

I'm new to working with Xtext and Xtend and I have stumbled upon a problem which I hope someone can help me solve. What I'm trying to achieve is to resolve variables from an external source rather than declaring them explicitly in the DSL. I got the following example to demonstrate: Here is the grammar:

grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.xbase.Xbase

generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"

Model:
configUrl=ConfigUrl
devices+=Device*
test=Test
;

ConfigUrl:
"ConfigURL=" url=STRING
;

Device:
'Device' name=ID
'has channels: ' (channels+=Channel (',' channels+=Channel)*)?
;

Channel:
name=ID
;

Test:
'DoSomething' channel=[Channel|QualifiedName]
;

and here is an example usage:

ConfigURL="http://localhost:8080/devices"
Device Light has channels: state
DoSomething Light.state

Instead of explicitly declaring the devices in the DSL I would like to resolve them from and external source (the ConfigURL variable). As far as I can tell, what I'm looking for is related to the scoping functionality of Xtend. I have looked at the documentation but haven't found much that can help me further. In addition, it seems that some things has changed and the examples that I've come across are outdated.

Thanks,

Matt Immer
  • 327
  • 1
  • 13

1 Answers1

0

Since your elements are not parsed by xtext you will need to create them, e.g. in the scope provider. For this, first create an ecore model that describes your Device and Channel classes. You will also need a reference in your DSL to these elements, e.g.

DeviceDesc:
  'Device' deviceRef=[Device|ID]
  'has channels: ' (channels+=[Channel] (',' channels+=[Channel])*)?;

Then you need an own scope provider which implements:

public IScope scope_DeviceDesc_deviceRef(final DeviceDesc context, EReference reference)

In this method you need to resolve the URL. You can get it via the context element:

String url = ((Model)context.eContainer()).getConfigUrl();

Use the URL to retrieve your external data and create Device elements from it. Then use Scopes.scopeFor(myDeviceList) to create a scope and return it in your scope provider.

You might want to consider caching the device elements instead of always recreating them when the scope provider is asked.