I have some problems with xtext cross referencing
Here is a very simple grammer:
grammar org.xtext.example.mydsl1.Test with org.eclipse.xtext.common.Terminals
generate test "http://www.xtext.org/example/mydsl1/Test"
Model: block=Block? cs+=Company* ;
Block: '{' g=[Employee] '}';
Company: 'Company' name=ID
'{' es+= Employee* '}';
Employee: 'Employee' name=ID ';' ;
and it is my dsl :
{ Pooyan }
Company Sony{
Employee Pooyan;
Employee John;
}
It always shown that "Couldn't resolve reference to Employee 'Pooyan'."
Could anyone please help me?
I have no idea...
The fully qualified name of Pooyan is Sony.Pooyan. Since the cross reference 'g' in your block is defined in another contain, you have to do a minor customizing to put it onto the scope.
If your language always uses a flat namespace, you could enable the SimpleNamesFragment in the language generator and remove the QualifiedNamesFragment. This should do the trick.
Alternatively, you could customize the scoping for the concrete reference 'g' in your scope provider.
Adding to Sebastians' answer to make it more precise: you need to change "fragment = exporting.QualifiedNamesFragment auto-inject {}" to "fragment = exporting.SimpleNamesFragment" in the corresponding .mwe2 file of your xtext project.
Hope this helps.
Related
import org.antlr.v4.runtime.tree.ParseTree;
import org.apache.shardingsphere.sql.parser.core.parser.SQLParserExecutor;
import org.junit.Test;
import javax.xml.bind.SchemaOutputResolver;
public class T1 {
#Test
public void t1() {
ParseTree parseTree = new SQLParserExecutor("MySQL", "insert into T_NAME (POINT) values (?)").execute().getRootNode();
}
}
This code will report the following error:
line 1:20 no viable alternative at input '(POINT'
When I use other column names, it’s all right, but POINT doesn’t work. Why?
Java project, pom.xml:
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-namespace</artifactId>
<version>4.1.1</version>
</dependency>
I suspect that all (MySQL), or more, keywords would trigger this error (POLYGON probably also produces this error). The grammar probably is trying to match an identifier, but since the input POINTS is already matched as a keyword, it fails to match it properly.
Something like this:
insert_stat
: INSERT INTO? table_name '(' column_names ')' ...
;
column_names
: IDENTIFIER ( ',' IDENTIFIER )*
;
Looking at the Github issue, one of the maintainers indicated that the 5.0.0-alpha properly handles this, meaning they probably did something like this to fix it:
insert_stat
: INSERT INTO? table_name '(' column_names ')' ...
;
column_names
: identifier ( ',' identifier )*
;
identifier
: IDENTIFIER
| POINT
| POLYGON
| ...
;
I.e.: they extended the set of valid identifiers inside the parser.
Thanks for #Bart's comment Here. This bug has been fixed from 5.0.0-alpha.
BTW, ShardingSphere supports many mainstream RDBMS, like MySQL, PostgreSQL, SQLServer and Oracle. Therefore you will see a great many g4 files in this repo. Ideally, these definitions in Antlr g4 file are expected to be aligned with the corresponding official SQL docs. So if there is any mismatch, please report that at ISSUES. Thanks a lot.
I'm here trying to find out if anyone know how can I, in my grammar, make a validator that checks if my step only uses ingredients I have declared before hand in the 'ingredients+=Ingredient+'
I've tried many things but no success, I don't know how can I get all the Ingredients that are declared inside my validator function.
Ty all for your time.
Here is the relevant part of my grammar.
Model:
recipe+=Recipe*;
...
Ingredient:
'ingredient' (
(liquid_name=LIQUID_INGREDIENTS_NAME liquid_measure=LIQUID_TYPES_MEASURE)
|
(solid_Name=SOLID_INGREDIENTS_NAME solid_measure=SOLID_TYPES_MEASURE)
)
quantity=INT;
Step:
'['
action=ACTION_TYPES
('ingredient' ((ingredient_StepLiquid=LIQUID_INGREDIENTS_NAME)|(ingredient_StepSolid=SOLID_INGREDIENTS_NAME)) | 'place' place=TM_PLACES | 'utensil' utensil=TM_UTENSILS)
('time' minutes=INT ':' seconds=INT ',')?
('speed' velocidade=SPEED_TYPES ',')?
('temperature' temp=TM_TEMPS 'ºC')?
']';
Recipe:
'recipe' recipeName=STRING '{'
ingredients+=Ingredient+
steps+=Step+
'}';
Just like #Christian Deitrich said
I can use either eContainer, and get my recipe with a cast from my step or via my grammar with the help from cross references.
I have an own Xtext grammar definition:
grammar org.xtext.example.mydsl.MyOtherDsl with org.eclipse.xtext.common.Terminals
generate myOtherDsl "http://www.xtext.org/example/mydsl/MyOtherDsl"
OtherModel:
Foo | Bar;
Foo: 'foo' name=ID;
Bar: 'bar' name=ID;
Now, I want to use this grammar in the (standard example) Xtext grammar via an "import":
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
import "http://www.xtext.org/example/mydsl/MyOtherDsl" as other
Model:
greetings+=Greeting*
foobars+=FooBar*;
Greeting: 'Hello' name=ID '!' foo=[other::Foo];
FooBar: other::Foo | other::Bar;
While Greeting: 'Hello' name=ID '!' foo=[other::Foo]; is working, FooBar: other::Foo | other::Bar; throws an error: no viable alternative at input 'other'. In the Greeting rule I use the reference for an attribute (foo). In the FooBar rule I just want to use it as a type. How can I do it?
Any help appreciated.
Thanks,
Andreas
Xtext only Supports a Single Inhertiance Hierarchy
grammar org.xtext.example.mydsl.MyDslBase with org.eclipse.xtext.common.Terminals
grammar org.xtext.example.mydsl.MyDslGrandParent with org.xtext.example.mydsl.MyDslBase
grammar org.xtext.example.mydsl.MyDslParent with org.xtext.example.mydsl.MyDslGrandParent
grammar org.xtext.example.mydsl.MyDslChild with org.xtext.example.mydsl.MyDslParent
so it is not possible to spilt them up into several and group them togther in one dsl
This is another problem I am facing while migrating from antlr3 to antlr4. This problem is with the java action code for handling conditional components of rules. One example is shown below.
The following grammar+code worked in antlr3. Here, if the unary operator is not present, then a value of '0' is returned, and the java code checks for this value and takes appropriate action.
exprUnary returns [Expr e]
: (unaryOp)? e1=exprAtom
{if($unaryOp.i==0) $e = $e1.e;
else $e = new ExprUnary($unaryOp.i, $e1.e);
}
;
unaryOp returns [int i]
: '-' {$i = 1;}
| '~' {$i = 2;}
;
In antlr4, this code results in a null pointer exception during a run, because 'unaryOp' is 'null' if it is not present. But if I change the code like below, then antlr generation itself reports an error:
if($unaryOp==null) ...
java org.antlr.v4.Tool try.g4
error(67): missing attribute access on rule reference 'unaryOp' in '$unaryOp'
How should the action be coded for antlr4?
Another example of this situation is in if-then-[else] - here $s2 is null in antlr4:
ifStmt returns [Stmt s]
: 'if' '(' e=cond ')' s1=stmt ('else' s2=stmt)?
{$s = new StmtIf($e.e, $s1.s, $s2.s);}
;
NOTE: question 16392152 provides a solution to this question with listeners, but I am not using listeners, my requirement is for this to be handled in the action code.
There are at least two potential ways to correct this:
The "ANTLR 4" way to do it is to create a listener or visitor instead of placing the Java code inside of actions embedded in the grammar itself. This is the only way I would even consider solving the problem in my own grammars.
If you still use an embedded action, the most efficient way to check if the item exists or not is to access the ctx property, e.g. $unaryOp.ctx. This property resolves to the UnaryOpContext you were assuming would be accessible by $unaryOp by itself.
ANTLR expects you access an attribute. Try its text attribute instead: $unaryOp.text==null
I have the following Drools DSL "sentence":
[when]The field {field} in the module {module} contains value {value}=$a : {module} ( {field} != null)
String( this.equalsIgnoreCase("{value}") ) from $a.{field}
where the field is a Set of Strings.
Now, if I have two of these rules, it obviously won't work as the variable $a occurs twice. So I wanted to improve the rule to make the variable, well, variable:
[when]The field {field} in the module {module} contains value {value} as {a}={a} : {module} ( {field} != null)
String( this.equalsIgnoreCase("{value}") ) from {a}.{field}
This doesn't work, I can't use the part {a}., that breaks.
So, my questions are: Is there either a way to rewrite the rules or a way to allow the {variable}. notation to work? Alternatively, is there a contains operator which works case insensitive?
After I subscribed to the Drools-Users mailing list, I got an answer:
http://drools.46999.n3.nabble.com/rules-users-Using-from-x-field-in-DSL-tt4017872.html
Summary: Bug in DSL parser, as a workaround add an extra letter after the variable on the RHS: ... as {a}={a}x (...) ... from {a}x.{field}