How to deal with list return values in ANTLR - return-value

What is the correct way to solve this problem in ANTLR:
I have a simple grammar rule, say for a list with an arbitrary number of elements.
list
: '[]'
| '[' value (COMMA value)* ']'
If I wanted to assign a return value for list, and have that value be the actual list of returned values from the production, what is the proper way to do it? The alternatives I'm entertaining are:
create my own stack in the global scope to keep track of these lists
Try to inspect the tree nodes below me and extract information that way
Access it in some slick and cool way that I'm hoping to find out about in which I can get easy access to such a list from within the action associated with the rule.
I guess the question is: How do the cool kids do it?
(FYI I'm using the python API for ANTLR, but if you hit me with another language, I can handle that)

In C# it might look like this:
list returns [ List<string> ValueList ]
#init
{
$ValueList = new List<string>();
}
: '[]'
| '[' value {$ValueList.Add(value);} (COMMA value {$ValueList.Add(value);})* ']'
;

I guess a more straightforward way could be
list returns [ List values ]
: '[]'
| '[' vs+=value (COMMA vs+=value)* ']' {
$values = $vs;
}

Related

How to generate code from custom scoping through instances?

I'm trying to write a code generator using xtext. There are instances of types declared in the corresponding DSL, attributes can be referenced through those instances by custom scoping (see code for example). The linking is performed directly from referencing element to attribute, so that there is no information about the surrounding instance - but for code generation, I exactly need the qualified name that is added in the DSL file. Is there any other possibility so that I can figure out through which instance the actual feature is referenced?
My first idea was to recall the ScopeProvider at code generation, which works but does not react on two instances of same type because the first matching Attribute is chosen - so if there are multiple instances, the generator cannot distinguish which one is meant.
Second idea was to include information from the corresponding DSL file, but I don't have any idea how to get this work. I already searched a lot if it is possible to get the corresponding DSL-file from the current model, but could not find any helpful answer.
Third idea was to include the instance as a hidden field in the referencing element - but I could not find any solution for this approach too.
Small extract of Grammar (simplified):
Screen:
(features += ScreenFeature)*
;
ScreenFeature:
name=ID ':' type=[ClientEntity]
;
ClientEntity:
(features += Feature)*
;
Feature:
name=ID ':' type=DefaultValue
;
DefaultValue:
'String'|'int'|'double'|'boolean'
;
ChangeViewParam:
param=[ScreenFeature|QualifiedName] ':' value=[ScreenFeature|QualifiedName]
;
DSL-Example:
ClientEntity Car {
id : int
name : String
}
Screen Details {
car : Car
car2 : Car
[...]
car2.id : car.id
}
Generation output of first approach (line: car2.id : car.id) :
car.id : car.id
Expected:
car2.id : car.id
I hope you can understand my problem and have an idea how to solve it. Thanks for your help!
You can use
org.eclipse.xtext.nodemodel.util.NodeModelUtils.findNodesForFeature(EObject, EStructuralFeature) to obtain the nodes for YourDslPackage.Literals.CHANGE_VIEW_PARAM__PARAM (should be only one) and ask that one for its text.
Alternatively you could split your param=[ScreenFeature|QualifiedName] into two references

Refine a string to only certain values scala

Is there any way to refine a string to only a certain subset of values? For example, I have a list of 500 keys in a hash map. But I only want certain keys to be inserted. For example, "abcd" and "aaaa" are valid keys but "abdc" is invalid. Is there any way to refine the String to only one of the given 500 keys?
I'm guessing the way to do this is just a very long regexp that matches abcd|aaaa?
Edit: Using the fthomas/refined library specifically the MatchesRegex function. Want to know if there is a better approach that I'm missing out on.
Scala 3 seems to Allow Singletons in Unions #6299 like so
val refinedString: "abcd" | "aaaa" = "aaaa"
whilst abdc would result in the following error
val refinedString: "abcd" | "aaaa" = "abdc"
^^^^^^
Found: String("abdc")
Required: String("abcd") | String("aaaa")
It worked for me with Dotty Scala version 0.15.0-bin-20190517-fb6667b-NIGHTLY.
I ended up actually just using generated source code that has every known key inside a MatchesRegex (a|b..) construct for 500 keys. It works. It's not pretty but it's also generated source code that I don't have to deal with so it's okay, I guess.

Data factory lookup (dot) in the item() name

I am having lookup wherein salesforce query is there. I am using elements (item()) in subsequent activities. Till now i had item().name or item().email but now i have item().NVMStatsSF__Related_Lead__r.FirstName which has (dot) in the field name.
How should i parse it through body tag so that it reads it correctly?
So I have the following data in item()
{
"NVMStatsSF__Related_Lead__c": "00QE000egrtgrAK",
"NVMStatsSF__Agent__r.Name": "ABC",
"NVMStatsSF__Related_Lead__r.Email": "geggegg#gmail.com",
"NVMStatsSF__Related_Lead__r.FirstName": "ABC",
"NVMStatsSF__Related_Lead__r.OwnerId": "0025434535IIAW"
}
now when i use item().NVMStatsSF__Agent__r.Name it will not parse because of (dot) after NVMStatsSF__Agent__r. And it is giving me the following error.
'item().NVMStatsSF__Related_Lead__r.Email' cannot be evaluated because property 'NVMStatsSF__Related_Lead__r' doesn't exist, available properties are 'NVMStatsSF__Related_Lead__c, NVMStatsSF__Agent__r.Name, NVMStatsSF__Related_Lead__r.Email, NVMStatsSF__Related_Lead__r.FirstName, NVMStatsSF__Related_Lead__r.OwnerId'.",
"failureType": "UserError",
"target": "WebActivityToAddPerson"
this is because ADF uses '.' for object reading.
Could you find a way to rename the field name which contains '.'?
Seems like you need a built-in function to get the value of an object according to the key. Like getValue(item(), 'key.nestkey'). But unfortunately, seems there isn't such a function. You may need handle your key first.
Finally, it worked. I was being silly.
Instead of taking the value from the child table with the help of (dot) operator I just used subquery. Silly see.
And it worked.

XML Expression Binding - Proceed Code in conditional operator

I am currently working on a Fiori app. At the moment I try to set a title depending on the value of a property I get from my OData service. Therefore I want to use expression binding with the conditional operator.
So when ${PROPERTIY} has the value "EXAMPLE", it should print the value of OUTPUT_PROPERTY_1. Otherwise, it should print the value of OUTPUT_PROPERTY_2.
XML:
<ObjectListItem title="{= ${PROPERTIY} === 'EXAMPLE' ? '${OUTPUT_PROPERTY_1}' : '${OUTPUT_PROPERTY_2}'}">
Unfortunately, it just prints ${OUTPUT_PROPERTY_1} or ${OUTPUT_PROPERTY_2}, and does not proceed the code to get the actual value of the properties.
Is there any chance to solve this problem or even a good workaround in order to print the actual value of the related property?
Remove the apostrophes around the expression binding syntax:
title="{= ${PROPERTIY} === 'EXAMPLE' ? ${OUTPUT_PROPERTY_1} : ${OUTPUT_PROPERTY_2}}"
Otherwise, '${OUTPUT_PROPERTY_x}' will be treated as a string literal.

Xtext assign object in xtext file

Trying to make a meta model for Mongoose and MondoDb, using metamodeling concepts, eclipse and xtext.
I am trying to assign object that i created in my test.mydsl file to another object in the same file, but i get error in my test.mydsl file.
I am trying to assign created Schema(sc1) object to Collection(col) object, but currently getting an error
error message
the feature 'validate' of
'paket.impl.NCollectionImpl#67d76e14{platform:/resource/test/classes/test.mydsl#//#collections.0}'
contains an unresolved proxy
'paket.impl.SchemaImpl#361d8284{platform:/resource/test/classes/test.mydsl#|0}'
my grammar for Schema and Collection
Schema returns Schema:
{Schema}
('Schema' '<' Name=EString) '>'
'{'
(schemaExpression+=Expression ( "," schemaExpression+=Expression)*)?
(verificationDocumentElement+=VerDocElement ( "," verificationDocumentElement+=VerDocElement)*)?
'}';
NCollection returns NCollection:
{NCollection}
('Collection' '<' Name=EString) ',' (validate=[Schema|EString])? '>'
'{'
(document+=Document ( "," document+=Document)*)?
'}';
my test.mydsl
Database<db1>{
Schema<sc1>{
var ja=lp
ime:{
type:String,
min:123.0
}
}
Collection<col, sc1>
{
}
}
I tried all, but unsuccessful.
Any ideas what to do?
Thanks
EDIT:
Maybe I was not clear enough. The major problem is with "validate" attribute in NCollection rule.
When I create my Schema object(sc1 in test.mydsl) and then try to pass it to Collection(col in test.mydsl) as a "sc1", the "validate" attribute cannot accept it like string, and I don't know how to pass it like Schema object.
I hope this explanation helps.
Please try to use name=EStringinstead of Name=EString as Xtext imposes a special default semantics for the attribute name. Also I recommend to look into the documentation.
The code
validate=[Schema|EString]
says: I want a schema reference via a String, i.e. "sc1" instead of the name. Xtext doesn't know how to convert a string into a reference. Use this instead:
validate=[Schema]
which is short for
validate=[Schema|ID]
That will use the name of the Schema as reference. Note that you have to write
('Schema' '<' name=EString) '>'
i.e. lower case name to make it work. Xtext has special handling for properties called name.