Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Serialization Issue with Mathematical Expression(When serializing EObjects more the wrong rule is taken from my grammar)
Serialization Issue with Mathematical Expression [message #1273046] Wed, 19 March 2014 07:49 Go to next message
Marcus Höpfner is currently offline Marcus Höpfner
Messages: 20
Registered: February 2014
Junior Member
Hello,

I have a grammar for mathematical expressions (formula) generated from my Ecore model.
When serializing a certain expression from EObject it uses the wrong ParserRule which results in a wrong formula string.

I cutted it down to what is relevant.

Here is the grammar:
grammar org.xtext.example.math.Math with org.eclipse.xtext.common.Terminals

import "http://www.eclipse.org/emf/2002/Ecore" as ecore
generate math "http://www.eclipse.org/example/math/Math"

FormulaDefinition returns FormulaDefinition:
	{FormulaDefinition}
	formulaToken=FormulaToken?;

FormulaToken returns FormulaToken:
	Prio1Operation;

Prio1Operation returns FormulaToken: // like +
	InfixOperand ({FormulaOperator.childToken+=current} code=InfixOperatorPrio1
	childToken+=InfixOperand)*;

InfixOperand returns FormulaToken:
	'(' FormulaToken ')' | FormulaConstant | PrefixOperation2Operands;

PrefixOperation2Operands returns FormulaOperator:
	code=PrefixOperator2Operands '(' childToken+=FormulaToken ',' childToken+=FormulaToken ')';

InfixOperatorPrio1 returns ecore::EString:
	('+');
	
PrefixOperator2Operands returns ecore::EString:
	'MAX';	
	
FormulaConstant returns FormulaConstant:
	value=INT;


Here is the test which fails:
	@Test
	def void testTwoArgPrefixOperation() {
		val op = MathFactory.eINSTANCE.createFormulaOperator
		op.code = 'MAX'
		var arg1 = MathFactory.eINSTANCE.createFormulaConstant
		arg1.value = 5
		op.childToken += arg1
		var arg2 = MathFactory.eINSTANCE.createFormulaConstant
		arg2.value = 8
		op.childToken += arg2
		
		var formulaDef = MathFactory.eINSTANCE.createFormulaDefinition()
		formulaDef.formulaToken = op
		
		val formula = serializer.serialize(formulaDef)
		
		assertEquals("MAX ( 5 , 8 )", formula)
	}

The serializer returns
5 MAX 8
instead of expected
MAX ( 5, 8 )


Xtext is assuming an Prio1Operation instead of PrefixOperator2Operands.

BTW: I formula expressing 5 + 8 is working as expected!

I was already able to solve by either
1.) Create new EMF-Objects which inherit from FormulaOperator. These would be FormulaOperatorInfix and FormulaOperatorPrefix and adapt the test accordingly.
grammar org.xtext.example.math.Math with org.eclipse.xtext.common.Terminals

import "http://www.eclipse.org/emf/2002/Ecore" as ecore
generate math "http://www.eclipse.org/example/math/Math"

FormulaDefinition returns FormulaDefinition:
	{FormulaDefinition}
	formulaToken=FormulaToken?;

FormulaToken returns FormulaToken:
	Prio1Operation;

Prio1Operation returns FormulaToken: // like +
	InfixOperand ({FormulaOperatorInfix.childToken+=current} code=InfixOperatorPrio1
	childToken+=InfixOperand)*;

InfixOperand returns FormulaToken:
	'(' FormulaToken ')' | FormulaConstant | PrefixOperation2Operands;

PrefixOperation2Operands returns FormulaOperatorPrefix:
	code=PrefixOperator2Operands '(' childToken+=FormulaToken ',' childToken+=FormulaToken ')';

InfixOperatorPrio1 returns ecore::EString:
	('+');
	
PrefixOperator2Operands returns ecore::EString:
	'MAX';	
	
FormulaConstant returns FormulaConstant:
	value=INT;

2.) Instead of pointing to rule InfixOperatorPrio1 and PrefixOperator2Operands use the strings directly in Prio1Operation and PrefixOperation2Operands in respect. So the grammar would look like this
grammar org.xtext.example.math.Math with org.eclipse.xtext.common.Terminals

import "http://www.eclipse.org/emf/2002/Ecore" as ecore
generate math "http://www.eclipse.org/example/math/Math"

FormulaDefinition returns FormulaDefinition:
	{FormulaDefinition}
	formulaToken=FormulaToken?;

FormulaToken returns FormulaToken:
	Prio1Operation;

Prio1Operation returns FormulaToken: // like +
	InfixOperand ({FormulaOperator.childToken+=current} code=('+')
	childToken+=InfixOperand)*;

InfixOperand returns FormulaToken:
	'(' FormulaToken ')' | FormulaConstant | PrefixOperation2Operands;

PrefixOperation2Operands returns FormulaOperator:
	code='MAX' '(' childToken+=FormulaToken ',' childToken+=FormulaToken ')';


FormulaConstant returns FormulaConstant:
	value=INT;


But actally option 1.) I don't want to go.
For option 2.) I wonder why I need to do that. It decreases usability and reuse. I though that there is no difference whether I write a String directly or reference a parser rule (which indeed returns a unique return).

Is there any other solution or way I can force Xtext to kind of "follow" the rules containing the operators.

Thanks, Marcus
Re: Serialization Issue with Mathematical Expression [message #1287141 is a reply to message #1273046] Mon, 07 April 2014 08:57 Go to previous messageGo to next message
Pawel Pogorzelski is currently offline Pawel Pogorzelski
Messages: 26
Registered: July 2009
Junior Member
Marcus,
try looking here:

ISequenceAcceptor.acceptAssignedDatatype


Maybe these two require modifications as well:

ElementMatcherProvider.getAllStates
ElementMatcherProvider.matchNext


Cheers,
Paweł

Re: Serialization Issue with Mathematical Expression [message #1287153 is a reply to message #1287141] Mon, 07 April 2014 09:13 Go to previous message
Pawel Pogorzelski is currently offline Pawel Pogorzelski
Messages: 26
Registered: July 2009
Junior Member
Marcus,
one more thing. In general flattering your model with:

InfixOperatorPrio1 returns ecore::EString:
	('+');


is not the best idea. It creates more problems than solves. And the three pointers I gave you in the previous reply might not the only code that requires modifications. In this case I'd simply use a dedicated type for the operator.
Previous Topic:Importing implicit global scope
Next Topic:XtextCON
Goto Forum:
  


Current Time: Fri Aug 29 04:05:52 EDT 2014

Powered by FUDForum. Page generated in 0.01594 seconds