Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » How to validate through all objects
How to validate through all objects [message #1804307] Fri, 22 March 2019 07:29 Go to next message
Željko Kovačević is currently offline Željko KovačevićFriend
Messages: 16
Registered: March 2019
Junior Member
Hi everyone! I just started learning Xtext and Xtend so please have patience with me :)

I have written a following grammar:

Model:
	'Program' name=ID ';'
	'START' 
		model+=(Student | Course | Enroll)* 
	'FINISH'
;
Student: 
	'Student' name=ID 
	// personal info
	'(' firstName=STRING lastName=STRING 'born' 'in' ageOfBirth=INT ')' 
	// student faculty - only fixed choices
	'studies' faculty=('Informatics' | 'Computing' | 'Electrotehnics') ';' 
; 
Course:
	'Course' name=ID '(' 'ECTS' ects=INT ')' (students+=[Student])?  ';'  
;
Enroll:
	'Enroll' students+=[Student](',' students+=[Student])* 'to' course=[Course] ';'
;


and I use the following validation to prevent duplicates:

	@Check
	def checkDuplicateCourseEnrollement(Enroll enroll) {
		val names = newHashSet;
		for(i : enroll.students)
			if(!names.add(i.name))
				error("Duplicate entry: " + "\'" + i.name + "\'!",   
					MyDslPackage.Literals.ENROLL__STUDENTS, enroll.students.lastIndexOf(i));			
	}
}


The problem is that my validation only works in this case:

Enroll John, Mark, Mark to Mathematics; // duplicate 'Mark'


but the following does not report an error:

Enroll John to English;
Enroll John, Mark to English;  // I would like to have error here since John is already enrolled to English course


Help would be appreciated!
Re: How to validate through all objects [message #1804413 is a reply to message #1804307] Mon, 25 March 2019 19:15 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 13067
Registered: July 2009
Senior Member
i am not sure if i can follow you. but if you want to check multiple enrolls you should do so

	@Check
	def checkDuplicateCourseEnrollement(Model model) {
		val names = HashMultimap.<String,String>create;
		for (enroll : model.model.filter(Enroll))
			for (i : enroll.students)
				if (!names.put(enroll.course.name, i.name))
					error("Duplicate entry: " + "\'" + i.name + "\'!", enroll, MyDslPackage.Literals.ENROLL__STUDENTS,
						enroll.students.lastIndexOf(i));
	}


Need professional support for Xtext, Xpand, EMF?
Go to: https://www.itemis.com/en/xtext/
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: How to validate through all objects [message #1804418 is a reply to message #1804413] Mon, 25 March 2019 20:06 Go to previous messageGo to next message
Željko Kovačević is currently offline Željko KovačevićFriend
Messages: 16
Registered: March 2019
Junior Member
That's what I was looking for. Thanks!

[Updated on: Mon, 25 March 2019 20:07]

Report message to a moderator

Re: How to validate through all objects [message #1805189 is a reply to message #1804307] Tue, 09 April 2019 14:43 Go to previous messageGo to next message
Željko Kovačević is currently offline Željko KovačevićFriend
Messages: 16
Registered: March 2019
Junior Member
Hi!

I would like to ask for help regarding code generator for the grammar I already posted.

For generator, I wrote this method:

	override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) {
        fsa.generateFile("generator.txt", '''
            «FOR student : resource.allContents.filter(Student).toIterable»
            Student «student.name»("«student.firstName»", "«student.lastName»", «student.ageOfBirth», "«student.faculty»");
            «ENDFOR»
            «FOR course : resource.allContents.filter(Course).toIterable»
            Course «course.name»(«course.ects»«FOR student : course.students», «student.name»«ENDFOR»);
            «ENDFOR»
        ''')
	}

For the following application

Program StudentDSL_Test; 
START 
	Course English (ECTS 6);  
	Student John ("John" "Johnston" born in 2000) studies Computing;
	Course Mathematics (ECTS 0) enroll John; 
	Student Mark ("Mark" "Markston" born in 2002) studies Informatics;
FINISH

it will generate:

Student John("John", "Johnston", 2000, "Computing");
Student Mark("Mark", "Markston", 2002, "Informatics");
Course English(6);
Course Mathematics(0, John);

The result is as expected; first Student code is generated and then Course code. BUT, how do I rewrite my generator example to respect the order of created objects? In the DSL example above, I would like to have the following generated code:

Course English(6);
Student John("John", "Johnston", 2000, "Computing");
Course Mathematics(0, John);
Student Mark("Mark", "Markston", 2002, "Informatics");

I suspect I need to iterate through StudentDSL, but don't know how..

[Updated on: Tue, 09 April 2019 14:46]

Report message to a moderator

Re: How to validate through all objects [message #1805190 is a reply to message #1805189] Tue, 09 April 2019 15:45 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 13067
Registered: July 2009
Senior Member
simply follow the ast as you do it in the validation.

starting tipp

resource.contents.get(0) as Model
will give you the root


Need professional support for Xtext, Xpand, EMF?
Go to: https://www.itemis.com/en/xtext/
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de

[Updated on: Tue, 09 April 2019 15:46]

Report message to a moderator

Re: How to validate through all objects [message #1805192 is a reply to message #1805190] Tue, 09 April 2019 16:18 Go to previous messageGo to next message
Željko Kovačević is currently offline Željko KovačevićFriend
Messages: 16
Registered: March 2019
Junior Member
Ok. I did this:

	override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) {
		val root = resource.contents.get(0) as StudentDSL;
		fsa.generateFile("generator.txt", '''
            «FOR i : root.studentDSL»
            «i.eClass.name» 
            «ENDFOR»
            
        ''')
	}

This gives object types in correct order. But, I don't know how to access object name and its attributes like firstName, secondName etc.?

[Updated on: Tue, 09 April 2019 16:18]

Report message to a moderator

Re: How to validate through all objects [message #1805195 is a reply to message #1805192] Tue, 09 April 2019 17:37 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 13067
Registered: July 2009
Senior Member
i cannot follow you without a grammar.

the question is: which type is i of

depending you either can do

«i.someattr»
or
«IF i instanceof SomeSubType»
«i.someattr»
«ENDIF»



Need professional support for Xtext, Xpand, EMF?
Go to: https://www.itemis.com/en/xtext/
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: How to validate through all objects [message #1805199 is a reply to message #1805195] Tue, 09 April 2019 19:15 Go to previous messageGo to next message
Željko Kovačević is currently offline Željko KovačevićFriend
Messages: 16
Registered: March 2019
Junior Member
Please check my first post in this topic. It contains the grammar I use.
Re: How to validate through all objects [message #1805200 is a reply to message #1805199] Tue, 09 April 2019 19:20 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 13067
Registered: July 2009
Senior Member
(1) there is no studentDSL
(2) the model has model+=(Student | Course | Enroll)* , which want you to look at, maybe the enrolls as in the validation?
use a for loop

«IF e : model.model.filter(Enroll)»
// todo do something with e
«ENDFOR»


Need professional support for Xtext, Xpand, EMF?
Go to: https://www.itemis.com/en/xtext/
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: How to validate through all objects [message #1805201 is a reply to message #1805200] Tue, 09 April 2019 19:20 Go to previous messageGo to next message
Željko Kovačević is currently offline Željko KovačevićFriend
Messages: 16
Registered: March 2019
Junior Member
Yes. I just wanted to edit my post :) I renamed Model to StudentDSL in the meantime.
Re: How to validate through all objects [message #1805202 is a reply to message #1805201] Tue, 09 April 2019 19:31 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 13067
Registered: July 2009
Senior Member
again: i still dont know along which paths you want to traverse the model

Need professional support for Xtext, Xpand, EMF?
Go to: https://www.itemis.com/en/xtext/
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: How to validate through all objects [message #1805203 is a reply to message #1805201] Tue, 09 April 2019 19:33 Go to previous messageGo to next message
Željko Kovačević is currently offline Željko KovačevićFriend
Messages: 16
Registered: March 2019
Junior Member
Please let me revise:

Grammar:
StudentDSL:
	'Program' name=ID ';'
	'START' 
		studentDSL+=(Student | Course | Enroll)* 
	'FINISH'
;

Student: 
	'Student' name=ID 
	// personal info
	'(' firstName=STRING lastName=STRING 'born' 'in' ageOfBirth=INT ')' 
	// student faculty - only fixed choices
	'studies' faculty=('Informatics' | 'Computing' | 'Electrotehnics') ';' 
; 

Course:
	'Course' name=ID
	// how many ECTS? 
	'(' 'ECTS' ects=INT ')'
	// enroll students (optional)  
	('enroll' students+=[Student](',' students+=[Student])*)?  
	';'  
;

Enroll:
	'Enroll' students+=[Student](',' students+=[Student])* 'to' course=[Course] ';'
;


This is the test DSL application:

Program StudentDSL_Test; 
START 
	Student John ("John" "Johnston" born in 2000) studies Computing;
	Course English (ECTS 6);  
	Student Mark ("Mark" "Markston" born in 2002) studies Informatics;
	Course Mathematics (ECTS 0) enroll John; 
	Enroll John, Mark to Mathematics; 
FINISH


And this is what I am trying to get with the code generator:

    Student John("John", "Johnston", 2000, "Computing");
    Course English(6);
    Student Mark("Mark", "Markston", 2002, "Informatics");
    Course Mathematics(0, John);
    Mathematics.Enroll(John, Mark);


I appreciate your time & help :) Please let me know if you need me to clarify anything else.

[Updated on: Tue, 09 April 2019 19:34]

Report message to a moderator

Re: How to validate through all objects [message #1805204 is a reply to message #1805203] Tue, 09 April 2019 19:38 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 13067
Registered: July 2009
Senior Member
simply iterate over root.studentDSL
do instanceofs for Student else if instanceof Course else if instanceof Enroll


Need professional support for Xtext, Xpand, EMF?
Go to: https://www.itemis.com/en/xtext/
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: How to validate through all objects [message #1805206 is a reply to message #1805204] Tue, 09 April 2019 19:40 Go to previous messageGo to next message
Željko Kovačević is currently offline Željko KovačevićFriend
Messages: 16
Registered: March 2019
Junior Member
Thanks! Will be doing battles with this tonight :)
Re: How to validate through all objects [message #1805207 is a reply to message #1805204] Tue, 09 April 2019 19:41 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 13067
Registered: July 2009
Senior Member
'''
«FOR item : root.studentDSL»
«IF item instanceof Course»
Course: «item.name»
«ELSEIF item instanceof Student»
Student: «item.name»
«ELSEIF item instanceof Enroll»
«ELSE»
something bad happend. did not expect «item.eClass.name»
«ENDIF»
«ENDFOR»

'''


Need professional support for Xtext, Xpand, EMF?
Go to: https://www.itemis.com/en/xtext/
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: How to validate through all objects [message #1805208 is a reply to message #1805207] Tue, 09 April 2019 19:41 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 13067
Registered: July 2009
Senior Member
no battles. straight forward

Need professional support for Xtext, Xpand, EMF?
Go to: https://www.itemis.com/en/xtext/
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: How to validate through all objects [message #1805209 is a reply to message #1805208] Tue, 09 April 2019 19:45 Go to previous messageGo to next message
Željko Kovačević is currently offline Željko KovačevićFriend
Messages: 16
Registered: March 2019
Junior Member
Thanks again! :) Will now try to finish the rest myself.
Re: How to validate through all objects [message #1805212 is a reply to message #1805209] Tue, 09 April 2019 20:29 Go to previous message
Željko Kovačević is currently offline Željko KovačevićFriend
Messages: 16
Registered: March 2019
Junior Member
Did it!

	override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) {
		val root = resource.contents.get(0) as StudentDSL;
		fsa.generateFile("program_cpp.txt", '''
		«FOR item : root.studentDSL»
		«IF item instanceof Student»
		Student «item.name»("«item.firstName»", "«item.lastName»",«item.ageOfBirth»);
		«ELSEIF item instanceof Course»
		Course «item.name»(«item.ects»);
		«ELSEIF item instanceof Enroll»
		«item.course.name».Enroll(«FOR stud : item.students SEPARATOR ', '»«stud.name »«ENDFOR»);
		«ELSE»
		Unrecognized type: «item.eClass.name»
		«ENDIF»
		«ENDFOR»            
        ''')
	}
Previous Topic:Dynamic Elements of Language
Next Topic:Formatter is triggered on quickfix
Goto Forum:
  


Current Time: Wed Aug 21 18:07:02 GMT 2019

Powered by FUDForum. Page generated in 0.02640 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top