Xtext - how to use "import" in own grammar - dsl

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

Related

Odd ANTLR4 error handling behavior with very simply (trivial) behavior

Given the below super simple grammar:
ddlStatement
: defineStatement
;
defineStatement
: 'define' tableNameToken=Identifier ';'?
;
and the input "add 1 to bob"
I would expect to get an error. However, the parser matches the "defineStatement" rule with a missing "define" token. The following Listener will fire
#Override
public void exitDefineStatement(DDLParser.DefineStatementContext ctx) {
log.info(MessageFormat.format("Defining {0}", ctx.tableNameToken.getText()));
}
and log "Defining add".
I can assign 'define' to a variable and test that variable for NULL but that seems like work I shouldn't have to do.
BTW if the grammar becomes more complete - specifically with the addition of alternatives to the ddlStatement rule - error handling works as I would expect.
This ANTLR's error recovery in action.
In many cases, it's VERY beneficial for ANTLR to assume either a missing token, or ignore a token, if it allows parsing to continue. The missing "define" token should have been reported as an error.
Without this capability, ANTLR would frequently get "stumped" at the first sign of problems. With this, ANTLR is saying "Well, if I assume X, then I can make sense of your input. So I'm assuming X and reporting that as an error so I can continue on.
(Filling a few details to get this to build)
grammar Test
;
ddlStatement: defineStatement;
defineStatement: 'define' tableNameToken = Identifier ';'?;
Identifier: [a-zA-Z]+;
Number: [0-9]+;
WS: [ \r\n\t]+ -> skip;
if I run antlr on this and compile the Java output. The following command:
echo "add 1 to bob" | grun Test ddlStatement -gui
yields the error:
line 1:0 missing 'define' at 'add'
and produces the parse tree:
The highlighted node is the error node in the tree.
The reason it stops after "add" is that input (assuming a missing "define", would be a ddlStatement
ANTLR will stop processing input once it has recognized your stop rule.
To get it to "pay attention" to the entire input, add an EOF token to your start rule:
grammar Test
;
ddlStatement: defineStatement EOF;
defineStatement: 'define' tableNameToken = Identifier ';'?;
Identifier: [a-zA-Z]+;
Number: [0-9]+;
WS: [ \r\n\t]+ -> skip;
gives these errors:
line 1:0 missing 'define' at 'add'
line 1:4 mismatched input '1' expecting {<EOF>, ';'}
and this tree:

Antlr no viable alternative at input when the keyword is POINT

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.

Xtext validator - check all elements X for element Y validation

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.

Inconsistent token handling in ANTLR4

The ANTLR4 book references a multi-mode example
https://github.com/stfairy/learn-antlr4/blob/master/tpantlr2-code/lexmagic/ModeTagsLexer.g4
lexer grammar ModeTagsLexer;
// Default mode rules (the SEA)
OPEN : '<' -> mode(ISLAND) ; // switch to ISLAND mode
TEXT : ~'<'+ ; // clump all text together
mode ISLAND;
CLOSE : '>' -> mode(DEFAULT_MODE) ; // back to SEA mode
SLASH : '/' ;
ID : [a-zA-Z]+ ; // match/send ID in tag to parser
https://github.com/stfairy/learn-antlr4/blob/master/tpantlr2-code/lexmagic/ModeTagsParser.g4
parser grammar ModeTagsParser;
options { tokenVocab=ModeTagsLexer; } // use tokens from ModeTagsLexer.g4
file: (tag | TEXT)* ;
tag : '<' ID '>'
| '<' '/' ID '>'
;
I'm trying to build on this example, but using the « and » characters for delimiters. If I simply substitute I'm getting error 126
cannot create implicit token for string literal in non-combined grammar: '«'
In fact, this seems to occur as soon as I have the « character in the parser tag rule.
tag : '«' ID '>';
with
OPEN : '«' -> pushMode(ISLAND);
TEXT : ~'«'+;
Is there some antlr foo I'm missing? This is using antlr4-maven-plugin 4.2.
The wiki mentions something along these lines, but the way I read it that's contradicting the example on github and anecdotal experience when using <. See "Redundant String Literals" at https://theantlrguy.atlassian.net/wiki/display/ANTLR4/Lexer+Rules
One of the following is happening:
You forgot to update the OPEN rule in ModeTagsLexer.g4 to use the following form:
OPEN : '«' -> mode(ISLAND) ;
You found a bug in ANTLR 4, which should be reported to the issue tracker.
Have you specified the file encoding that ANTLR should use when reading the grammar? It should be okay with European characters less than 255 but...

Xtext cross referencing and scoping

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.

Resources