/**
*
*/
package com.sap.furcas.parsergenerator.tcs.t2m.grammar;
import static com.sap.furcas.parsergenerator.testutils.RuleComparisonHelper.assertEqualTokens;
import static com.sap.furcas.test.testutils.StringListHelper.list;
import static org.junit.Assert.assertEquals;
import java.util.List;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.junit.BeforeClass;
import org.junit.Test;
import com.sap.furcas.metamodel.FURCAS.TCS.Associativity;
import com.sap.furcas.metamodel.FURCAS.TCS.Operator;
import com.sap.furcas.metamodel.FURCAS.TCS.OperatorTemplate;
import com.sap.furcas.metamodel.FURCAS.TCS.Priority;
import com.sap.furcas.metamodel.FURCAS.TCS.stubs.LiteralStub;
import com.sap.furcas.metamodel.FURCAS.TCS.stubs.OperatorListStub;
import com.sap.furcas.metamodel.FURCAS.TCS.stubs.OperatorStub;
import com.sap.furcas.metamodel.FURCAS.TCS.stubs.OperatorTemplateStub;
import com.sap.furcas.metamodel.FURCAS.TCS.stubs.PriorityStub;
import com.sap.furcas.parsergenerator.tcs.t2m.grammar.handlerStub.ANTLR3WriterStub;
import com.sap.furcas.parsergenerator.tcs.t2m.grammar.handlerStub.TemplateNamingHelperStub;
import com.sap.furcas.parsergenerator.tcs.t2m.grammar.rules.AbstractAntlr3Rule;
import com.sap.furcas.parsergenerator.tcs.t2m.grammar.rules.ClassProductionRule;
import com.sap.furcas.runtime.tcs.TemplateNamingHelper;
/**
* Tests the operatorHandler class.
* Due to the complexity of the task, tests are difficult to understand. Use them mostly as regressionTests, not as documentation.
* Just consider that the OperatorHandler's output generally are a number of rules "priority_0" to "priority_n" where n
* is the number of priorities defined in the Syntax. And within each rule, the operatored class template rule is called on
* the left side of the operator, and the operatorTemplate is called on the right side of the operator.
* Also, this shall allow associativity, meaning a +b + c + d .... That's why the rulebody should loook like this
* : classTemplate ( (Operator) OperatorTemplate ) *
* so that the second bit can be repeated several times.
*/
public class TestOperatorHandler {
@BeforeClass
public static void setup() {
ObservationDirectivesHelper.doAddObserverParts = ObservationDirectivesHelper.NONE;
}
@Test
public void testAddElement() throws Exception {
// This test is not a real world scenario, no syntax should define an operatorList without operators
// This test though might reveal bugs on a very basic level, so it is included.
ANTLR3WriterStub writerStub = new ANTLR3WriterStub();
TemplateNamingHelper<?> namingStub = new TemplateNamingHelperStub<Object>();
// Class under test
OperatorHandler ophandler = new OperatorHandler(writerStub, namingStub, null);
String classTemplateName = "testClassTemplate";
OperatorListStub opList = new OperatorListStub();
EList<Priority> prioList = new BasicEList<Priority>();
PriorityStub priority1 = new PriorityStub();
prioList.add(priority1);
opList.priorities = prioList ;
ophandler.addOperatorList(opList , classTemplateName , true, null, null);
assertEquals(1, writerStub.rules.size());
ClassProductionRule result = (ClassProductionRule) writerStub.rules.get(0);
String expected = "priority_0 returns[Object ret2] @init{java.lang.String opName=null; org.antlr.runtime.Token firstToken=input.LT(1); Object semRef=null;} " +
" : (ret=primary_testclasstemplate) " +
"{ " +
"this.setLocationAndComment(ret, firstToken); " +
"ret2=ret; " +
" } ; " +
"catch [Exception e] {handleExceptionInTemplateRule(e, firstToken, ret);}";
assertEqualTokens(expected, result.toString());
}
@Test
public void testAddElementOnePriorityOneOperator() throws Exception {
ANTLR3WriterStub writerStub = new ANTLR3WriterStub();
TemplateNamingHelper<?> namingStub = new TemplateNamingHelperStub<Object>();
// Class under test
OperatorHandler ophandler = new OperatorHandler(writerStub, namingStub, null);
String classTemplateName = "testClassTemplate";
/****** Main driver for expected result ****/
OperatorListStub opList = getMockOperatorList(list("TestOp"));
/******/
ophandler.addOperatorList(opList , classTemplateName , true, null, null);
assertEquals(1, writerStub.rules.size());
ClassProductionRule result = (ClassProductionRule) writerStub.rules.get(0);
String expected = "priority_0 returns[Object ret2] @init{java.lang.String opName=null; org.antlr.runtime.Token firstToken=input.LT(1); Object semRef=null;}\r\n" +
" : ( ( ret=primary_testclasstemplate((TESTOP)=>(TESTOP {opName = \"TestOp\";}((ret=template[opName, ret, firstToken]))))*)) " +
"{ " +
"this.setLocationAndComment(ret, firstToken); " +
"ret2=ret; " +
" } ; " +
"catch [Exception e] {handleExceptionInTemplateRule(e, firstToken, ret);}";
assertEqualTokens(expected, result.toString());
}
@Test
public void testAddElementOneOperatorDisambiguated() throws Exception {
ANTLR3WriterStub writerStub = new ANTLR3WriterStub();
TemplateNamingHelper<?> namingStub = new TemplateNamingHelperStub<Object>();
// Class under test
OperatorHandler ophandler = new OperatorHandler(writerStub, namingStub, null);
String classTemplateName = "testClassTemplate";
/****** Main driver for expected result ****/
OperatorListStub opList = getMockOperatorList(list("TestOp"));
/******/
OperatorStub operator = (OperatorStub) opList.priorities.get(0).getOperators().get(0);
OperatorTemplateStub optemplate = (OperatorTemplateStub) operator.templatesList.get(0);
optemplate.disambiguateV3 = "DISAMBIGUATE";
ophandler.addOperatorList(opList , classTemplateName , true, null, null);
assertEquals(1, writerStub.rules.size());
ClassProductionRule result = (ClassProductionRule) writerStub.rules.get(0);
String expected = "priority_0 returns[Object ret2] @init{java.lang.String opName=null; org.antlr.runtime.Token firstToken=input.LT(1); Object semRef=null;}\r\n" +
" : ( ( ret=primary_testclasstemplate((TESTOP((DISAMBIGUATE)))=>(TESTOP {opName = \"TestOp\";}((DISAMBIGUATE)=>(ret=template[opName, ret, firstToken]))))*)) " +
"{ " +
"this.setLocationAndComment(ret, firstToken); " +
"ret2=ret; " +
" } ; " +
"catch [Exception e] {handleExceptionInTemplateRule(e, firstToken, ret);}";
assertEqualTokens(expected, result.toString());
}
@Test
public void testAddElementOnePriorityTwoOperators() throws Exception {
ANTLR3WriterStub writerStub = new ANTLR3WriterStub();
TemplateNamingHelper<?> namingStub = new TemplateNamingHelperStub<Object>();
// Class under test
OperatorHandler ophandler = new OperatorHandler(writerStub, namingStub, null);
String classTemplateName = "testClassTemplate";
/****** Main driver for expected result ****/
OperatorListStub opList = getMockOperatorList(list("TestOp", "OtherTestOp"));
/******/
ophandler.addOperatorList(opList , classTemplateName , true, null, null);
assertEquals(1, writerStub.rules.size());
ClassProductionRule result = (ClassProductionRule) writerStub.rules.get(0);
String expected = "priority_0 returns[Object ret2] @init{java.lang.String opName=null; org.antlr.runtime.Token firstToken=input.LT(1); Object semRef=null;} " +
" : ( ( ret=primary_testclasstemplate((TESTOP)=>(TESTOP {opName = \"TestOp\";}((ret=template[opName, ret, firstToken]))) " +
"| (OTHERTESTOP)=>(OTHERTESTOP {opName = \"OtherTestOp\";}((ret=template[opName, ret, firstToken]))))*)) " +
"{ " +
"this.setLocationAndComment(ret, firstToken); " +
"ret2=ret; " +
" } ; " +
"catch [Exception e] {handleExceptionInTemplateRule(e, firstToken, ret);}";
assertEqualTokens(expected, result.toString());
}
@Test
public void testAddElementThreePriorityTwoOperators() throws Exception {
ANTLR3WriterStub writerStub = new ANTLR3WriterStub();
TemplateNamingHelper<?> namingStub = new TemplateNamingHelperStub<Object>();
// Class under test
OperatorHandler ophandler = new OperatorHandler(writerStub, namingStub, null);
String classTemplateName = "testClassTemplate";
/****** Main driver for expected result ****/
OperatorListStub opList = getMockOperatorList(list("TestOp", "OtherTestOp"), list("TestOp222", "OtherTestOp222"), list("TestOp333", "OtherTestOp333"));
/******/
ophandler.addOperatorList(opList , classTemplateName , true, null, null);
assertEquals(3, writerStub.rules.size());
ClassProductionRule result = (ClassProductionRule) writerStub.rules.get(0);
String expected = "priority_0 returns[Object ret2] @init{java.lang.String opName=null; org.antlr.runtime.Token firstToken=input.LT(1); Object semRef=null;} " +
" : ( ( ret=primary_testclasstemplate((TESTOP)=>(TESTOP {opName = \"TestOp\";}((ret=template[opName, ret, firstToken]))) " +
"| (OTHERTESTOP)=>(OTHERTESTOP {opName = \"OtherTestOp\";}((ret=template[opName, ret, firstToken]))))*)) " +
"{ " +
"this.setLocationAndComment(ret, firstToken); " +
"ret2=ret; " +
" } ; " +
"catch [Exception e] {handleExceptionInTemplateRule(e, firstToken, ret);}";
assertEqualTokens(expected, result.toString());
// test next priority as well
result = (ClassProductionRule) writerStub.rules.get(1);
expected = "priority_1 returns[Object ret2] @init{java.lang.String opName=null; org.antlr.runtime.Token firstToken=input.LT(1); Object semRef=null;} " +
" : ( ( ret=priority_0((TESTOP222)=>(TESTOP222 {opName = \"TestOp222\";}((ret=template[opName, ret, firstToken]))) " +
"| (OTHERTESTOP222)=>(OTHERTESTOP222 {opName = \"OtherTestOp222\";}((ret=template[opName, ret, firstToken]))))*)) " +
"{ " +
"this.setLocationAndComment(ret, firstToken); " +
"ret2=ret; " +
" } ; " +
"catch [Exception e] {handleExceptionInTemplateRule(e, firstToken, ret);}";
assertEqualTokens(expected, result.toString());
}
@Test
public void testAddElementUnary() throws Exception {
// This test is not a real world scenario, no syntax should define an operatorList without operators
// This test though might reveal bugs on a very basic level, so it is included.
ANTLR3WriterStub writerStub = new ANTLR3WriterStub();
TemplateNamingHelper<?> namingStub = new TemplateNamingHelperStub<Object>();
// Class under test
OperatorHandler ophandler = new OperatorHandler(writerStub, namingStub, null);
String classTemplateName = "testClassTemplate";
OperatorListStub opList = new OperatorListStub();
EList<Priority> prioList = new BasicEList<Priority>();
PriorityStub priority1 = new PriorityStub();
prioList.add(priority1);
opList.priorities = prioList ;
EList<Operator> operatorsList = new BasicEList<Operator>();
OperatorStub unaryOperator = new OperatorStub();
unaryOperator.arity = 1;
LiteralStub operatorLiteral = new LiteralStub();
operatorLiteral.value = "value";
operatorLiteral.name = "name";
operatorLiteral.representation = "REP";
unaryOperator.literal = operatorLiteral;
OperatorTemplateStub opTemplate = new OperatorTemplateStub();
opTemplate.names = list("optemplate");
unaryOperator.templatesList.add(opTemplate );
operatorsList.add(unaryOperator );
priority1.operators = operatorsList ;
ophandler.addOperatorList(opList , classTemplateName , true, null, null);
assertEquals(1, writerStub.rules.size());
AbstractAntlr3Rule result = writerStub.rules.get(0);
String expected = "priority_0 returns[Object ret2] @init{java.lang.String opName=null; org.antlr.runtime.Token firstToken=input.LT(1); Object semRef=null;} " +
" : " +
" (((NAME)=>(NAME {opName = \"value\";}((ret=optemplate[opName, null, firstToken]right=primary_testclasstemplate {setProperty(ret, \"null\", right); " +
"this.setLocationAndComment(ret, firstToken); " +
"})))) " +
"| " +
" ( ret=primary_testclasstemplate)) " +
"{ " +
"this.setLocationAndComment(ret, firstToken); " +
"ret2=ret; " +
" } " +
" ; " +
"catch [Exception e] {handleExceptionInTemplateRule(e, firstToken, ret);}";
assertEqualTokens(expected, result.toString());
}
@Test
public void testAddElementUnaryRightAssociative() throws Exception {
// This test is not a real world scenario, no syntax should define an operatorList without operators
// This test though might reveal bugs on a very basic level, so it is included.
ANTLR3WriterStub writerStub = new ANTLR3WriterStub();
TemplateNamingHelper<?> namingStub = new TemplateNamingHelperStub<Object>();
// Class under test
OperatorHandler ophandler = new OperatorHandler(writerStub, namingStub, null);
String classTemplateName = "testClassTemplate";
OperatorListStub opList = new OperatorListStub();
EList<Priority> prioList = new BasicEList<Priority>();
PriorityStub priority1 = new PriorityStub();
priority1.associativity = Associativity.RIGHT;
prioList.add(priority1);
opList.priorities = prioList ;
EList<Operator> operatorsList = new BasicEList<Operator>();
OperatorStub unaryOperator = new OperatorStub();
unaryOperator.arity = 1;
LiteralStub operatorLiteral = new LiteralStub();
operatorLiteral.value = "value";
operatorLiteral.name = "name";
operatorLiteral.representation = "REP";
unaryOperator.literal = operatorLiteral;
OperatorTemplateStub opTemplate = new OperatorTemplateStub();
opTemplate.names = list("optemplate");
unaryOperator.templatesList.add(opTemplate );
operatorsList.add(unaryOperator );
priority1.operators = operatorsList ;
ophandler.addOperatorList(opList , classTemplateName , true, null, null);
assertEquals(1, writerStub.rules.size());
AbstractAntlr3Rule result = writerStub.rules.get(0);
String expected = "priority_0 returns[Object ret2] @init{java.lang.String opName=null; org.antlr.runtime.Token firstToken=input.LT(1); Object semRef=null;} " +
" : " +
" (((((ret=optemplate[opName, null, firstToken]NAME {opName = \"value\";}right=priority_0 {setProperty(ret, \"null\", right); " +
"this.setLocationAndComment(ret, firstToken); " +
"})))) " +
"| " +
" ( ret=primary_testclasstemplate)) " +
"{ " +
"this.setLocationAndComment(ret, firstToken); " +
"ret2=ret; " +
" } " +
" ; " +
"catch [Exception e] {handleExceptionInTemplateRule(e, firstToken, ret);}";
assertEqualTokens(expected, result.toString());
}
@Test
public void testAddElementUnaryPostfix() throws Exception {
// This test is not a real world scenario, no syntax should define an operatorList without operators
// This test though might reveal bugs on a very basic level, so it is included.
ANTLR3WriterStub writerStub = new ANTLR3WriterStub();
TemplateNamingHelper<?> namingStub = new TemplateNamingHelperStub<Object>();
// Class under test
OperatorHandler ophandler = new OperatorHandler(writerStub, namingStub, null);
String classTemplateName = "testClassTemplate";
OperatorListStub opList = new OperatorListStub();
EList<Priority> prioList = new BasicEList<Priority>();
PriorityStub priority1 = new PriorityStub();
prioList.add(priority1);
opList.priorities = prioList ;
EList<Operator> operatorsList = new BasicEList<Operator>();
OperatorStub unaryOperator = new OperatorStub();
unaryOperator.arity = 1;
LiteralStub operatorLiteral = new LiteralStub();
operatorLiteral.value = "value";
operatorLiteral.name = "name";
operatorLiteral.representation = "REP";
unaryOperator.literal = operatorLiteral;
unaryOperator.isPostFix = true;
OperatorTemplateStub opTemplate = new OperatorTemplateStub();
opTemplate.names = list("optemplate");
unaryOperator.templatesList.add(opTemplate );
operatorsList.add(unaryOperator );
priority1.operators = operatorsList ;
ophandler.addOperatorList(opList , classTemplateName , true, null, null);
assertEquals(1, writerStub.rules.size());
AbstractAntlr3Rule result = writerStub.rules.get(0);
String expected = "priority_0 returns[Object ret2] @init{java.lang.String opName=null; org.antlr.runtime.Token firstToken=input.LT(1); Object semRef=null;} " +
" : " +
" ( ( ret=primary_testclasstemplate )(" +
" ((NAME)=>(NAME {opName = \"value\";}((ret=optemplate[opName, ret, firstToken]{this.setLocationAndComment(ret, firstToken); })))) " +
"| )) " +
"{ " +
"this.setLocationAndComment(ret, firstToken); " +
"ret2=ret; " +
" } " +
" ; " +
"catch [Exception e] {handleExceptionInTemplateRule(e, firstToken, ret);}";
assertEqualTokens(expected, result.toString());
}
/**
* helps with setting up operatorlists. An operatorList has n priorities,
* and each priority has operators, and operator each has a literal and a template.
*
* That's the basic concept, though there is also associativity and arity to consider. (TODO)
* @param priorities
* @return
*/
private OperatorListStub getMockOperatorList(List<String>... priorities) {
OperatorListStub opList = new OperatorListStub();
EList<Priority> prioList = new BasicEList<Priority>();
for (int i = 0; i < priorities.length; i++) {
List<String> operatorsList = priorities[i];
EList<Operator> opsList = new BasicEList<Operator>();
PriorityStub loopPriority = new PriorityStub();
loopPriority.value = i;
prioList.add(loopPriority);
opList.priorities = prioList ;
for (Object element : operatorsList) {
String nextString = (String) element;
LiteralStub operatorLiteral = new LiteralStub();
operatorLiteral.value = nextString;
operatorLiteral.name = nextString;
operatorLiteral.representation = nextString;
OperatorStub op = new OperatorStub();
op.literal = operatorLiteral;
EList<OperatorTemplate> templList = new BasicEList<OperatorTemplate>();
OperatorTemplateStub template = new OperatorTemplateStub();
template.names = list("template");
templList.add(template);
op.templatesList = templList;
opsList.add(op );
loopPriority.operators = opsList ;
}
}
return opList;
}
@Test
public void testAddElementOnePriorityTwoOperatorsTwoTemplates() throws Exception {
ANTLR3WriterStub writerStub = new ANTLR3WriterStub();
TemplateNamingHelper<?> namingStub = new TemplateNamingHelperStub<Object>();
// Class under test
OperatorHandler ophandler = new OperatorHandler(writerStub, namingStub, null);
String classTemplateName = "testClassTemplate";
/****** Main driver for expected result ****/
OperatorListStub opList = getMockOperatorList(list("TestOp", "OtherTestOp"));
Priority prio0 = opList.getPriorities().iterator().next();
OperatorTemplateStub template2 = new OperatorTemplateStub();
template2.names = list("template2");
prio0.getOperators().get(0).getTemplates().add(template2);
/******/
ophandler.addOperatorList(opList , classTemplateName , true, null, null);
assertEquals(1, writerStub.rules.size());
ClassProductionRule result = (ClassProductionRule) writerStub.rules.get(0);
String expected = "priority_0 returns[Object ret2] @init{java.lang.String opName=null; org.antlr.runtime.Token firstToken=input.LT(1); Object semRef=null;} " +
" : ( ( ret=primary_testclasstemplate((TESTOP)=>(TESTOP {opName = \"TestOp\";}((ret=template[opName, ret, firstToken]) " +
"| (ret=template2[opName, ret, firstToken]))) " +
"| (OTHERTESTOP)=>(OTHERTESTOP {opName = \"OtherTestOp\";}((ret=template[opName, ret, firstToken]))))*)) " +
"{ " +
"this.setLocationAndComment(ret, firstToken); " +
"ret2=ret; " +
" } ; " +
"catch [Exception e] {handleExceptionInTemplateRule(e, firstToken, ret);}";
assertEqualTokens(expected, result.toString());
}
@Test
public void testAddElementOnePriorityTwoOperatorsWithSyntacticPredicates() throws Exception {
ANTLR3WriterStub writerStub = new ANTLR3WriterStub();
TemplateNamingHelper<?> namingStub = new TemplateNamingHelperStub<Object>();
// Class under test
OperatorHandler ophandler = new OperatorHandler(writerStub, namingStub, null);
String classTemplateName = "testClassTemplate";
/****** Main driver for expected result ****/
OperatorListStub opList = getMockOperatorList(list("TestOp", "OtherTestOp"));
Priority prio0 = opList.getPriorities().iterator().next();
prio0.getOperators().get(0).getTemplates().get(0).setDisambiguateV3("disambiguate1");
OperatorTemplateStub template2 = new OperatorTemplateStub();
template2.disambiguateV3 = "disambiguate2";
template2.names = list("template2");
prio0.getOperators().get(0).getTemplates().add(template2);
/******/
ophandler.addOperatorList(opList , classTemplateName , true, null, null);
assertEquals(1, writerStub.rules.size());
ClassProductionRule result = (ClassProductionRule) writerStub.rules.get(0);
String expected = "priority_0 returns[Object ret2] @init{java.lang.String opName=null; org.antlr.runtime.Token firstToken=input.LT(1); Object semRef=null;} " +
" : ( ( ret=primary_testclasstemplate((TESTOP((disambiguate1)|(disambiguate2)))=>(TESTOP {opName = \"TestOp\";}((disambiguate1)=>(ret=template[opName, ret, firstToken]) " +
"| (disambiguate2)=>(ret=template2[opName, ret, firstToken]))) " +
"| (OTHERTESTOP)=>(OTHERTESTOP {opName = \"OtherTestOp\";}((ret=template[opName, ret, firstToken]))))*)) " +
"{ " +
"this.setLocationAndComment(ret, firstToken); " +
"ret2=ret; " +
" } ; " +
"catch [Exception e] {handleExceptionInTemplateRule(e, firstToken, ret);}";
assertEqualTokens(expected, result.toString());
}
// TODO test other arities and associativities
@Test
public void testPrefix() throws Exception {
assertEquals("", OperatorHandler.getPriorityPrefix(null));
OperatorListStub opList = new OperatorListStub();
assertEquals("", OperatorHandler.getPriorityPrefix(opList));
opList.name = "test";
assertEquals("test_", OperatorHandler.getPriorityPrefix(opList));
opList.name = "TEST";
assertEquals("test_", OperatorHandler.getPriorityPrefix(opList));
opList.name = "Test";
assertEquals("test_", OperatorHandler.getPriorityPrefix(opList));
}
}