Problems with code generation [message #1749448] |
Tue, 06 December 2016 21:56  |
Luiz Paulo Franz Messages: 19 Registered: November 2016 |
Junior Member |
|
|
Hello guys.
I'm having a problem, I'm not getting information from the grammar tree in code generation. The situation is a bit unusual because my grammar is different.
What I need is to pass a valid entry in the grammar, such as:
The fridge SHALL detect and communicate information with AS MANY food packages AS POSSIBLE.
Capital letters are the operators of my grammar.
The output of this using the code generator should be:
SHALL (AS MANY AS POSSIBLE p)
p: The fridge detects and communicates information with food packages
However I am not able to use Xtend to generate this result.
My grammar was defined as:
//list of all requirements
Requirements:
requirements+=Requirement+;
//each requirement is finalized with ";"
Requirement:
(root+=General)+ ';';
//undefined types
terminal BOOLEAN returns ecore::EBoolean:'true'|'false';
terminal FREESTRING: (('\\')?('a'..'z'|'A'..'Z'|'_'|'0'..'9'|','|'.'))* ;
//Natural Language
NL hidden(WS): FREESTRING ( FREESTRING)*;
General:
rest = Rest =>({UntilOperator.left=current}('UNTIL'|'until') right=General)*;
//aqui se encontram as demais regras da gramatica
Rest:
Primitive|ShallOperator|MayOperator|EventuallyOperator|BeforeOperator|AfterOperator|InOperator|AsCloseOperator|AsOperator
;
Primitive:
BooleanValue | StringValue
;
//primitives
BooleanValue:value=BOOLEAN;
StringValue:value=NL;
ShallOperator:
('SHALL'|'shall') elements=General;
MayOperator:
("MAY"|'may') action1=General ('OR'|'or') action2=General;
EventuallyOperator:
('EVENTUALLY'|'eventually') element=General;
BeforeOperator:
('BEFORE'|'before') event=NL other=General;
AfterOperator:
('AFTER'|'after') event=NL other=General;
InOperator:
('IN'|'in') t=NL other=General;
AsCloseOperator:
('AS' 'CLOSE' 'AS' 'POSSIBLE' 'TO'|'as' 'close' 'as' 'possible' 'to') ForQ=NL;
AsOperator:
AsEarlyOperator|AsLateOperator|AsManyOperator|AsFewOperator;
AsEarlyOperator:
('AS' 'EARLY' 'AS' 'POSSIBLE'|'as' 'early' 'as' 'possible') value=General;
AsLateOperator:
('AS' 'LATE' 'AS' 'POSSIBLE'|'as' 'late' 'as' 'possible') value=General;
AsManyOperator:
('AS' 'MANY'|'as' 'many') (element=NL)? ('AS' 'POSSIBLE'|'as' 'possible') value=General;
AsFewOperator:
('AS' 'FEW'|'as' 'few') (element=NL)? ('AS' 'POSSIBLE'|'as' 'possible') value=General;
And on the generator, I was able to do the following:
override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) {
// criamos um arquivo em separado para cada requisito
var counter = 1
for (e : resource.allContents.toIterable.filter(Requirement)) {
fsa.generateFile("relaxExpressions" + counter + ".exp", e.compile)
counter++
}
}
def compile(Requirement r) '''
«FOR f : r.root»
«f.compileGeneral»
«ENDFOR»
'''
def compileGeneral(General g) '''
«IF g.rest != null»
«g.rest.compileRest »
«ENDIF»
'''
def compileRest(Rest r) '''
«IF r.eContainer.class.equals(Primitive) »
aa
«ENDIF»
'''
My doubts in the compileRest method, how do I deal with a "Rest" rule that does not have any internal variables in grammar, only directs to other rules?
Also, how do I get information from the left recursion treated in the General rule in grammar?
And last one, am I doing it the right way?
Thank you for your attention.
|
|
|
Re: Problems with code generation [message #1749469 is a reply to message #1749448] |
Wed, 07 December 2016 06:23   |
|
Hi,
i recommend you two things.
first have a look at the inferred metamodel classes and their type hierarchy
there you will see something like
Rest
- AsOperator
- ...
- Primitive
- StringValue
- BooleanValue
and
so with some instanceof-ing you would be able to the distinction
or have a look at the feature of Xtend that is called dispatch methods, that allows you to write something like
def dipatch compileGeneral(General g) '''
//TODO
'''
def dipatch compileGeneral(UntilOperator g) '''
//TODO
'''
def dipatch compileRest(Rest r) '''
// TODO
'''
def dipatch compileRest(BooleanValue r) '''
// TODO
'''
def dipatch xompileRest(StringValue r) '''
// TODO
'''
def dipatch compileRest(AsOperator r) '''
// TODO
'''
update: added missing dipatch keywords
Need professional support for Xtext, Xpand, EMF?
Go to: https://www.itemis.com/en/it-services/methods-and-tools/xtext
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
[Updated on: Wed, 07 December 2016 13:25] Report message to a moderator
|
|
|
Re: Problems with code generation [message #1749503 is a reply to message #1749469] |
Wed, 07 December 2016 13:22   |
|
Hi Luiz,
I also recommend the dispatch methods for your case.
To add to Christian's reply, they than have to look like
def dispatch compileRest(Rest r) '''
// TODO
'''
def dispatch compileRest(BooleanValue r) '''
// TODO
'''
def dispatch compileRest(StringValue r) '''
// TODO
'''
def dispatch compileRest(AsOperator r) '''
// TODO
'''
regards,
Christian
Christian Dietrich wrote on Wed, 07 December 2016 07:23Hi,
i recommend you two things.
first have a look at the inferred metamodel classes and their type hierarchy
there you will see something like
Rest
- AsOperator
- ...
- Primitive
- StringValue
- BooleanValue
and
so with some instanceof-ing you would be able to the distinction
or have a look at the feature of Xtend that is called dispatch methods, that allows you to write something like
def compileGeneral(General g) '''
//TODO
'''
def compileGeneral(UntilOperator g) '''
//TODO
'''
def compileRest(Rest r) '''
// TODO
'''
def compileRest(BooleanValue r) '''
// TODO
'''
def compileRest(StringValue r) '''
// TODO
'''
def compileRest(AsOperator r) '''
// TODO
'''
|
|
|
|
|
|
Powered by
FUDForum. Page generated in 0.02461 seconds