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: 14661
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));
	}


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: 14661
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


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: 14661
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»



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: 14661
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»


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: 14661
Registered: July 2009
Senior Member
again: i still dont know along which paths you want to traverse the model

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: 14661
Registered: July 2009
Senior Member
simply iterate over root.studentDSL
do instanceofs for Student else if instanceof Course else if instanceof Enroll


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: 14661
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»

'''


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: 14661
Registered: July 2009
Senior Member
no battles. straight forward

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: Fri Mar 29 06:18:59 GMT 2024

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

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

Back to the top