|
|
Re: Context aware grammar help [message #1793102 is a reply to message #1793080] |
Tue, 31 July 2018 08:33 |
Mykola Makhin Messages: 50 Registered: July 2018 |
Member |
|
|
Thanks, Christian, for your answer.
However, it's not clear to me how scoping alone can help.
The question is - how can I define a model outside of a DSL to be used inside of a DSL (e.g. classes like person or location with their own properties that may hold instances of different classes etc). The examples of scoping I've seen so far (in official documentation, speech videos, books etc - I've checked a lot of them) are mostly focused on cases when model is defined within DSL, and then it is (cross-)referenced in same DSL.
But how can I define model externally? Should I use Ecore for that? Or can I somehow import POJO classes into DSL to be used? Is it at all possible implement some completion/scoping using reflection on POJO classes, and if it is - where do I even start?
If it is not possible - what are the alternatives? Only Ecore? How would I add an Ecore model to an Xtext project? Seems I have to modify workflow (mwe2) file to generate model from .ecore (or is it .genmodel?) file, but what else has to be done?
I'm sorry for so many questions, but the issue seems quite confusing and much more complex than I've originally anticipated.
[Updated on: Tue, 31 July 2018 08:35] Report message to a moderator
|
|
|
|
Re: Context aware grammar help [message #1793105 is a reply to message #1793103] |
Tue, 31 July 2018 08:41 |
Mykola Makhin Messages: 50 Registered: July 2018 |
Member |
|
|
I would like to define them statically in source code (so they would not change after build - no need to have any dynamic definitions in runtime). How do I do that - that is actually the question.
The best would be if I could just create a few Java classes to represent the model (e.g. class Address with string property city, class Person with Address property etc), and then somehow make them visible to an Xtext DSL (but only those specific classes).
However, I'm not sure if this is possible. And if it is - how can this be done.
I've found out that an Ecore model seems similar to what I want - I can define these classes with their properties and relations in an Ecore mode (.ecore file).
However, I'm not sure how do I proceed from there. Or should I even do that - or perhaps there is a better alternative.
[Updated on: Tue, 31 July 2018 08:42] Report message to a moderator
|
|
|
|
|
|
|
|
|
Re: Context aware grammar help [message #1793516 is a reply to message #1793131] |
Thu, 09 August 2018 12:17 |
Mykola Makhin Messages: 50 Registered: July 2018 |
Member |
|
|
I've run into a problem with the proposal provider when implementing completion for properties and subproperties of some entity.
Here's the example DSL text of what I'm trying to achieve:
for User as user find @user.name == "Mykola" && @user.address.city == "Lviv"
In my grammar I have a code like this for "fully qualified names":
Rule: 'for' entityRefDef=EntityReferenceDefinition 'find' conditions=Conditions;
FQN:
'@' entityReference=[EntityReferenceDefinition|EntityReferenceName] ('.' property+=ID)*;
EntityReferenceDefinition:
entityType=ID 'as' name= EntityReferenceName;
EntityReferenceName:
ID;
Conditions:
... bunch of logical conditions and comparison related code with left factoring etc
In my content proposal provider I've added something like this:
@Inject EntityMetadataProvider metaProvider
override dispatch createProposals(RuleCall ruleCall, ContentAssistContext context,
IIdeContentProposalAcceptor acceptor) {
if (context.currentModel instanceof FQN && ruleCall.rule.name == "ID" &&
ruleCall.eContainer instanceof Assignment && (ruleCall.eContainer as Assignment).feature == "property") {
val fqn = context.currentModel as FQN;
if (fqn.entityReference !== null) {
for (String propertyName : metaProvider.getPropertyNames(fqn.entityReference.entityType, fqn.property)) {
proposeString(propertyName, acceptor);
}
}
}
}
def protected proposeString(String proposalText, IIdeContentProposalAcceptor acceptor) {
val proposal = new ContentAssistEntry();
proposal.proposal = proposalText
acceptor.accept(proposal, proposalPriorities.getDefaultPriority(proposal));
}
The EntityMetadataProvider provides lists of properties given entity type (e.g. "User") and property path (["name", "address"] for empty property path, ["city", "street", "building", ...] for "address" etc - supporting any arbitrary depth).
It almost works, except for cases when I try to do completion when part of the text is already added.
E.g. for this text
for User as user find @user.name == "Mykola" && @user.address.city == "Lviv"
placing cursor after "@user." should provide completions ["name", "address"]. But it only does so if no property is already written afterwards (e.g. for input like "for User as user find @user." or "for User as user find @user. && @user.address.city == "Lviv"" if cursor is placed after first occurrence of "@user.", the one followed by a space and &&).
If I place cursor after "@user." in text like "... @user.address" I get completions ["city", "street", "building", ...] because (context.currentModel as FQN).property already contains address - even though I moved cursor behind it and I'm trying to replace it.
First of all, I haven't found any way to figure out which of (context.currentModel as FQN).property values are behind the cursor, and which are ahead of it.
Second, I'm not sure if implementing completion this way makes sense at all - or there is a simpler or more correct way to implement the same functionality.
In future I also want to add corresponding validation - so only properties that are appearing in completion are allowed.
So in view of this, is there a better approach for me to implement this completion? Or if there isn't - how can this particular issue be fixed?
[Updated on: Thu, 09 August 2018 12:21] Report message to a moderator
|
|
|
|
|
Re: Context aware grammar help [message #1793565 is a reply to message #1793558] |
Fri, 10 August 2018 09:28 |
Mykola Makhin Messages: 50 Registered: July 2018 |
Member |
|
|
P.S. I'm currently working with this option. This allows me to have hierarchy of Property objects, so I could walk up the tree to check parent properties only.
Seems like a viable fix, but I had to rewrite completion code with regard to changes in generated model:
Rule: 'for' entityRefDef=EntityReferenceDefinition 'find' conditions=Conditions;
FQN:
'@' entityReference=[EntityReferenceDefinition|EntityReferenceName] ('.' property=Property)?;
Property:
name=ID ('.' property=Property)?
EntityReferenceDefinition:
entityType=ID 'as' name= EntityReferenceName;
EntityReferenceName:
ID;
Conditions:
... bunch of logical conditions and comparison related code with left factoring etc
[Updated on: Fri, 10 August 2018 09:29] Report message to a moderator
|
|
|
Powered by
FUDForum. Page generated in 0.04534 seconds