node label/key in XText when translating from grako - xtext

In grako one can use the following name:e to add the result of e to the AST using name as key. For example
var_def
=
var+:ID {',' var+:ID}*
What would be a good translation of this to Xtext?
I tried
var_def:
var=ID (',' var=ID)*;
which is not failing, but is raising the following warning
Multiple markers at this line
- The possibly assigned value of feature 'var' may be overridden
by subsequent assignments.
- This assignment will override the possibly assigned value of
feature 'var'.
I think I am trying to mimic the name behavior, but do not have much success.

With your solution only the last ID will be available in the AST. I assume var should be a multi-valued feature holding all IDs, not only the last one. This can be expressed as
var_def:
var+=ID (',' var+=ID)*;
In the resulting AST var is a list of IDs.

Related

Why we are unable to evaluate comprehension if we have defined it inside a rule body in OPA?

The following is my sample code: https://play.openpolicyagent.org/p/oyY1GOsYaf
Here when I try to evaluate names array, it is showing:
error occurred: 1:1: rego_unsafe_var_error: var names is unsafe
But when I define the same comprehension outside the allow rule definition : https://play.openpolicyagent.org/p/Xv0cF7FM8b, I am able to evaluate the selection
[
"smoke",
"dev"]
could someone help me to point out the difference and if I want to define the comprehention inside the rule is there any syntax I need to follow? Thanks in advance
Note: I am getting the final output as expected in both cases, only issue is with the names array evaluation.
The way the Rego Playground generates a query when evaluating a selection is much more simplistic than one might assume. A query will be generated from your selected text, without taking into account where in the document that text was selected. This means that even if you select a local variable inside a rule body, the query will simply contain that variable name (names, in your case); which will be perceived as a reference to a top-level variable in the document's body, even though a rule-local variable was selected. This is why your first sample returns an error, as there is no top-level variable names in the document; whereas the second sample does, and therefore succeeds.
You can test this quirk by selecting and evaluating the word hello on line 3 here: https://play.openpolicyagent.org/p/n5OPoFnlhx.
package play
# hello
hello {
m := input.message
m == "world"
}
Even though it's just part of a comment, it'll evaluate just as if you had selected the rule name on line 5.

Handling arbitrary text blocks in an Xtext grammar

In an effort to better understand Xtext, I'm working on writing a grammar and have hit a roadblock. I've boiled it down to the following scenario. I have some input such as this:
thing {abc}
{def}
There may be keywords (e.g.'thing') followed by other language elements (e.g. ID) in braces. Or, there can just be a block of content inside braces. This content should simply be passed along to the parser en masse.
If I try something like this:
Model: (things+=AThing | blocks+=ABlock)*;
AThing : 'thing' '{' name = ID '}';
ABlock : block=BLOCK;
terminal BLOCK:'{' -> '}';
and parse the sample text above, I get an error:
'mismatched input '{abc}' expecting '{'' on ABlock, offset 6, length 5
So, '{abc}' is being matched by the BLOCK terminal rule, which I understand. But how do I alter the grammar to properly handle the sample input? I've been wrestling with this problem for a while and have come up empty. So it's either something very simple that I've missed, or the problem is really complex and I don't realize it. Any enlightenment would be greatly appreciated.
Parsing happens in two stages: tokenizer and lexical. In the first one the text input is divided into tokens, in the second one the tokens are matched against lexical rules. Broadly something like (with some arbitrary language):
1st phase:
text: class X { this ; }
----- --- --- ---- --- ---
tokens: ID ID LB ID SC RB
2nd phase:
Is there a rule that starts with a 'class' string?
YES: Is the next expected token an ID?
YES: Is the next expected token a LB?
...
NO: Is there another rule that starts with 'class'?
...
NO: Is there a rule that starts with an ID token?
...
The lexer implementation is a bit more complex, but I hope you get the idea.
The issue with your grammar is that your termial BLOCK rule is used during the first phase, hence you get
thing {abc} {def}
----- ----- -----
ID BLOCK BLOCK
That is why the error message says if found '{abc}' and not a '{'. The lexer matched the thing and was expecting the next token to be a '{' but it got a BLOCK.
If you want arbitrary text inside the block, I don't think you can use '{' to identify the name of things.
This looks like what is mentioned here:
A quite common case requiring backtracking is when your language uses the same delimiter pair for two different semantics
So the simplest solution seems to use different delimiters. Otherwise you may have to look into enabling backtracking.

Validating unique names for strings and optional reference

New to XText, I am struggling with two issues with the following MWE grammar.
Metamodel:
(classes += Type)*
;
Type:
Enumeration | Class
;
Enumeration:
'enumeration' name = ValidID '{' (literals += EnumLiteral ';')+ '}'
;
EnumLiteral:
ValidID
;
Class:
'class' name = ValidID '{'
(references += Reference)*
'}'
;
Reference:
'reference' name = ValidID ':' type = Class ('#' opposite = [Reference])?
;
So my questions are:
Since the enumeration literals list is ValidID, it seems to be represented by EStrings. The documentation does not seem to deal with the case of primitive types in ECore. How is it possible to check for non-duplicates in literals, and report it adequately in the editor (i.e., the error should be at the first occurence of a repeated literal)?
Despite my best efforts, I was unable to write a custom scope for the opposite reference. Since XText uses reflection for retrieving the scoping methods, I suspect I don't have the correct one: I tried def scope_Reference_opposite(Reference context, EReference r), is it correct? An example would be really appreciated, from which I am confident I can easily adapt to my "real" DSL.
Thanks a lot for the help, you will save me a lot of time looking again and again for a solution in documentation...
Errors can be attached to a certain index of a many-values feature. Write a validation for the type Enumeration and check the the list of literals for duplicates. Attach the error to the index in the list.
The signature is correct. Did you import the correct 'Reference' or did you use some other class with the same simple name by accident. Also please not that your grammar appears to be wrong for the type of the reference. This should be type=[Class] or more likely type=[Class|ValidID].
If you plan to use or do already use Xbase, things may look different. Xbase doesn't use the reflective scope provider.

xext grammar with chosen predicates

I am trying to understand a xtext grammar I have found (below). I have two questions:
The XFeatureCall has return Type XExpression but this is overruled by {XFeatureCall} so I could set "returns XFeatureCall" as well?. Or is it actually necessary to do it this way?
Line 8 and 14 start with "=>". Are these "chosen predicates" or something else that did not come to my attention so far? I could not find this variation of chosen predicates in the xtext documentation. So I would appreciate clarification in its application.
xtext grammar:
StaticEquals:':=';
XFeatureCall returns XExpression:
// Same as Xbase...
{XFeatureCall}
(declaringType=[JvmDeclaredType|StaticQualifier])?
('<' typeArguments+=JvmArgumentTypeReference (',' typeArguments+=JvmArgumentTypeReference)* '>')?
(feature=[JvmIdentifiableElement|IdOrSuper]|'class')
(=>explicitOperationCall?='('
(
featureCallArguments+=XShortClosure
| featureCallArguments+=XExpression (',' featureCallArguments+=XExpression)*
)?
')')?
=>featureCallArguments+=XClosure?
// ... Except with this additional optional clause that allows static members to be set with := operator
({XAssignment.assignable = current} StaticEquals value = XAssignment)?;
First question: In fact in this case your rule returns a XFeatureCall but XFeatureCall has XExpression as its supertype. It is useful for example if you have:
SomeRule: (parts+=XFeatureCall)* (parts+=XOtherFeatureCall)*
Let XOtherFeatureCall also extend XExpression, and parts be a list of XExpressions.
Second question: it is a priority operator and means that what follows should be parsed now, even if there are other parsing solutions. See this classic example:
if a
if b
do;
else
doelse;
else could be parsed for the inner if or the outer if. Of course we want it in the inner if. Setting a rule such as:
=>'else' else=ElseExpression
forces the grammar to parse the else as soon as it finds it instead of returning to the outer rule that could consume a else too. So it solves an ambiguity.

Grammar errors in Xtext

I have a grammar rule
factoid:
Element Place
;
That depends on another rule:
Place:
name = ('sea' | 'air')
;
The factoid rule seems to contain identify errors associated with Place:
Multiple markers at this line
- Cannot change type twice within a rule
- An unassigned rule call is not allowed, when the 'current'
was already created.
I have no idea what this means. Can someone explain what this is and how to fix it?
I think the Element rule generates an object. Since there is no assignment this becomes the current one. The second unassigned rule call to Place would also return an object. But the current pointer contains already the Element type class and can not contain the class Place as well. So what you can try is assigning the Place to a member of factoid, here called location :
factoid:
item=Element location=Place
;
I am not sure if the assignment of Element to item is required. If Element is not assigned to member then I expect that location would become member of Element or something similar.

Resources