(Xtext) How to change the scoping of imported resources via importURI? - xtext

I have a DSL that allows to explicitly import resources (via importURI attribute). Everything is working just fine, except the fact that I would like to refer to imported elements directly by their ID (not by fully qualified name).
I am not using importedNamespace, because I've limited the GlobalScope to only what is explicitly imported and for each resource I need all elements (like ModelName.*).
So, right now I'm able to refer to imported elements like this:
ModelName.OuterElement.InnerElement
but I would like to have something like this:
OuterElement or InnerElement.
Of course, the general context is more complex and a bit different, but I've tried to simplify everything just around this question. So, please refer to the following grammar:
Model:
name=ID ':'
(include+=Include)?
(outerElems+=OuterElement ';')*
(uses+=Use ';')*;
Include:
'import' importURI=STRING ;
OuterElement:
'def' name=ID
'(' (innerElements+=InnerElement (',' innerElements+=InnerElement)* )? ')' ;
InnerElement:
name=ID;
Element:
OuterElement | InnerElement;
Use:
'use' use =[Element|FQN];
FQN:
ID('.'ID)* ;

if you want to refer to elements by their simple name you have to bind
SimpleNameProvider
as IQualifiedNameProvider
public Class<? extends IQualifiedNameProvider> bindIQualifiedNameProvider() {
return SimpleNameProvider.class;
}
respectively
override bindIQualifiedNameProvider() {
SimpleNameProvider
}

Related

Extending XFeatureCall scope

This has been puzzling me for a while... I have done research, tried lots of things but failed miserably. The time has come to ask here.
My grammar has this rule to define types:
MyTypeDeclaration returns XExpression:
=>({MyTypeDeclaration} type=JvmTypeReference name=ValidID '(')
(params+=FullJvmFormalParameter (',' params+=FullJvmFormalParameter)*)?
')' block=XBlockExpression
;
Of course, in the inferrer, I map it to a class (with a supertype MySupertype to differentiate from other Java classes)
members += f.toClass(f.fullyQualifiedName) [
superTypes += typeRef(MySupertype)
...
members += f.toConstructor [
for (p : f.params)
parameters += p.toParameter(p.name, p.parameterType)
body = f.block
]
...
]
What I need is to invoke this class as a function, e.g. using XFeatureCall. XFeatureCall::feature is a JvmIdentifiableElement and so is MyTypeDeclaration when mapped (in the compiler I will add a "new" prefix to call the class constructor). However, naturally, XFeatureClass does not include Java classes in its default scope.
So the question is, how to change this behavior? I need to include MyTypeDeclaration instances (or, more generally, Java classes with MySupertype as superclass) in XFeatureClass scope. I looked at the type computer, getLinkingCandidates and al but it looks too arcane for me.
I use version 2.15 as I need GWT...
Please help as I am really stuck at this point...
Thanks,
Martin

Xtext: How to implement IQualifiedNameProvider to return file name

I have rule like this in my grammar:
`CLASS: 'extends' '=' superClass=[CLASS];`
As You can see my class don't have any name like name=ID and I would like to reference by a file name that contains CLASS declaration. To achieve this I created custom QualifiedNameProvider that extends DefaultDeclarativeQualifiedNameProviderwith:
def QualifiedName qualifiedName(CLASSDeclaration cd) {
var fileName = ???????
return QualifiedName::create(fileName)
}
This works fine when I'm returning hardcoded string but I don't know how to obtain file name where a class is defined.
Thanks for ideas
You can use the eResource of an EObject to get an URI that you can process to get a file name. Please note: [Class] is short for [Class|ID] which means that a ID is parsed.
If you want to allow a dot for the file name there you may need something like [Class|FQN]
And you may useIQualifiedNameConverter
To create the qualified name

Crossreferencing in xtext - also for native types

I'm trying to set up a xtext grammar that has the following characteristics.
Sketch(!):
Class:
properties += Property*
;
Resource:
properties += Property*
;
Link :
// no classes here, so no common for Resource and Class
[Resource] <-> [Resource]
;
BasicType:
'int' | 'long'
;
Property:
// this is not supported
name ':' BasicType | [Resource] | [Class]
// i tried
// name ':' EObject
;
My question is:
How can i solve this situation, to crossreference a property type to 'Resource' or 'Class' or a BasicType?
I tried with EObject as BaseType and resolve the crossreferences in a custom ScopeProvider ,
but then i dont know how to use BasicTypes (int or long) as Type for properties.
first you can introduce common supertypes by defining a rule that you dont call
Parent: Child1 | Child2
then you can reference only things that are defined somewhere else.
thus you have to define them explicitely or change the grammar
XText entity example, primitive type

XTEXT2- validation error after migration to XTEXT2

I met a strange error after migration to XTEXT2.
When I write three elements, one IfEffectivePackageBlock and define one class and its subclass extends it.
The code I wrote is very simple to replay the error. But it is fine in XTEXT 1.0
IfEffectivePackageBlock xxx{
}
class xx{
}
class xxxx extends xx{
}
The grammer I using is listed below, it will popup the error I met.
IfEffectivePackageBlock:
'ifEffective' effectivityId=ID '{'
(elements+=AbstractElement)*
'}'
;
ClassDeclaration:
'class' name=ID ('extends' superType=[ClassDeclaration])? '{'
(statements+=(
FunctionDef |
ConfigurationEntryPoint
)
)*
'}'
;
It will popup an window that warning me there is an internal error.
You can see it below.
Any advice?
I think your qualified name provider has to be updated. You'll have to return a qualified name instead of a string.

In yacc, how to put a definition into a variable?

In my yacc file I have the following code:
fun_declaration : type_specifier ID '(' params ')'
{$2->type = "function";
$2->args = params; }
params : param_list | VOID ;
Do you see what I'm trying to do?
args is a string. I'm trying to put the function parameters into this string. How to do that?
You need to have 'params' return the string you want in $$, much like ID is returning a pointer to some struct with 'type' and 'args' fields. This means you'll need a %type declaration for it saying which element of the %union to use.
There are lots of books and online tutorials for how to use yacc like this.
Just refer to with $n it as you would refer to any semantic value component in the rule. Something like this:
$2->args = strdup($4);

Resources