Skip to content
This repository has been archived by the owner on Apr 21, 2023. It is now read-only.

Serialization of parsed model leads to invalid code #1853

Closed
lukasf98 opened this issue Mar 4, 2022 · 9 comments
Closed

Serialization of parsed model leads to invalid code #1853

lukasf98 opened this issue Mar 4, 2022 · 9 comments

Comments

@lukasf98
Copy link

lukasf98 commented Mar 4, 2022

Given the following grammar:

grammar org.eclipse.xtext.example.fowlerdsl.Statemachine with org.eclipse.xtext.common.Terminals

generate statemachine "http://www.eclipse.org/xtext/example/fowlerdsl/Statemachine"

Statemachine :
	{Statemachine}
	(('events' ('{'
		events+=Event*
	'}'))? &
	('resetEvents' ('{'
		resetEvents+=[Event]*
	'}'))? &
	('commands' ('{'
		commands+=Command*
	'}'))? &
	states+=State* )
;

Event:
	name=ID code=ID
;

Command:
	name=ID code=ID
;

State:
	'state' name=ID
		('actions' '{' actions+=[Command]+ '}')?
		transitions+=Transition*
	'end'
;

Transition:
	event=[Event] '=>' state=[State]
;

If i parse and the serialize tho following code:

resetEvents {
	doorOpened
}

events {
	doorClosed		D1CL
	drawerOpened	D2OP
	lightOn			L1ON
	doorOpened		D1OP
	panelClosed		PNCL
}

commands {
	unlockPanel PNUL
	lockPanel	NLK
	lockDoor	D1LK
	unlockDoor	D1UL
}

state idle
	actions {unlockDoor lockPanel}
	doorClosed => active
end

state active
	drawerOpened => waitingForLight
	lightOn		 => waitingForDrawer
end

state waitingForLight
	lightOn => unlockedPanel
end

state waitingForDrawer
	drawerOpened => unlockedPanel
end

state unlockedPanel
	actions {unlockPanel lockDoor}
	panelClosed => idle
end

The serialization of the parsed model leads to invalid code:

resetEvents
	{
	doorOpened
}

resetEvents {
}

events
	{
	doorClosed   D1CL
	drawerOpened D2OP
	lightOn      L1ON
	doorOpened   D1OP
	panelClosed  PNCL
}

events {
}

commands
	{
	unlockPanel PNUL
	lockPanel   NLK
	lockDoor    D1LK
	unlockDoor  D1UL
}

state idle
	actions {unlockDoor lockPanel}
	doorClosed => active
end

state active
	drawerOpened => waitingForLight
	lightOn      => waitingForDrawer
end

state waitingForLight
	lightOn => unlockedPanel
end

state waitingForDrawer
	drawerOpened => unlockedPanel
end

state unlockedPanel
	actions {unlockPanel lockDoor}
	panelClosed => idle
end

Ass seen above the first to statements are duplicated with an empty statement.
Attached below is an example project to reproduce the issue.
See teste org.eclipse.xtext.example.fowlerdsl.tests.StatemachineParsingTest
IssueDuplicate.zip

@cdietrich
Copy link
Member

eclipse-xtext/xtext#2580
might be related.
throwing away the nodemodel seems to help here too

@lukasf98
Copy link
Author

lukasf98 commented Mar 7, 2022

eclipse-xtext/xtext#2580 might be related. throwing away the nodemodel seems to help here too

Thanks a lot for your reply. I tested it and it solves the problem I described above. However I ran into an issue with a comma seperated list. If I for example change the grammar for resetEvents to a comma seperated list:

('resetEvents' ('{'
	(resetEvents+=[Event] (',' resetEvents+=[Event])*)?
'}'))? &

And I execute the test org.eclipse.xtext.example.fowlerdsl.tests.StatemachineParsingTest (see attachement) I get two resetEvents Statements:

resetEvents { 
	doorOpened 
} 
resetEvents { 
	doorClosed 
}

IssueDuplicate2.zip

@cdietrich
Copy link
Member

If metamodel does not matter can you move each clause to extra rule

@lukasf98
Copy link
Author

lukasf98 commented Mar 7, 2022

If metamodel does not matter can you move each clause to extra rule

What do you mean exactly? Extracting (resetEvents+=[Event] (',' resetEvents+=[Event])*)? into a seperate rule?

@cdietrich
Copy link
Member

yes

@lukasf98
Copy link
Author

lukasf98 commented Mar 7, 2022

Thanks a lot. I tested it with the example I provided and changed the grammar:

Statemachine :
	{Statemachine}
	(('events' ('{'
		events+=Event*
	'}'))? &
	('resetEvents' ('{'
		resetEvents=ResetEvents
	'}'))? &
	('commands' ('{'
		commands+=Command*
	'}'))? &
	states+=State* )
;

ResetEvents:
	{ResetEvents} (resetEvents+=[Event] (',' resetEvents+=[Event])*)?;

While that works, I can't change the metamodel in my real project. Therfore we decided to make the comma optional and move to lists without commas in the future. In my example that means changing the grammar to the following:

('resetEvents' ('{'
	(resetEvents+=[Event] ','?)*
'}'))? &

@lukasf98
Copy link
Author

lukasf98 commented Mar 9, 2022

@cdietrich

I have one problem left:
If I throw away the nodemodel and then serialize my code I loose my comments.
Do you have an idea how I can retain them?

@cdietrich
Copy link
Member

cdietrich commented Mar 9, 2022

no, none besides make them explicit

@szarnekow
Copy link
Contributor

I don't see something here that's different from eclipse-xtext/xtext#2580. Closing

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants