blob: 49b2b05a64bcafe36698eb8c248f5f74294e9fd2 [file] [log] [blame]
package org.eclipse.gymnast.generators.ecore.convert;
import static org.eclipse.gymnast.generators.ecore.convert.ShorthandJava.jDOT;
import static org.eclipse.gymnast.generators.ecore.convert.ShorthandJava.jLPAREN;
import static org.eclipse.gymnast.generators.ecore.convert.ShorthandJava.jPLUS;
import static org.eclipse.gymnast.generators.ecore.convert.ShorthandJava.jRPAREN;
import static org.eclipse.gymnast.generators.ecore.convert.ShorthandJava.jSEMI;
import static org.eclipse.gymnast.generators.ecore.convert.ShorthandJava.jStrBLANK;
import static org.eclipse.gymnast.generators.ecore.convert.ShorthandJava.jStrWithQuoteEscaped;
import java.util.List;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EEnum;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.gymnast.generators.ecore.cst.AltRuleAltsKind;
import org.eclipse.gymnast.generators.ecore.cst.AltRuleCS;
import org.eclipse.gymnast.generators.ecore.cst.ListRuleCS;
import org.eclipse.gymnast.generators.ecore.cst.RootCS;
import org.eclipse.gymnast.generators.ecore.cst.RuleCS;
import org.eclipse.gymnast.generators.ecore.cst.SeqExprCS;
import org.eclipse.gymnast.generators.ecore.cst.SeqExprKind;
import org.eclipse.gymnast.generators.ecore.cst.SeqRuleCS;
import org.eclipse.gymnast.generators.ecore.cst.TokenRuleCS;
public class GenUnparseInhaleAndMMForSeqRules {
private EClass ecorizer = null;
private RootCS c = null;
private String unparseMethodBody = "";
private static final String newLine = System.getProperty("line.separator");
public static final String jPPPackage = "org.eclipse.gymnast.prettyprinting";
public static final String jPPBox = jPPPackage + ".Box";
public static final String jPPPrettyPrintable = jPPPackage
+ ".PrettyPrintable";
public static final String jPPSL = jPPPackage + ".SL";
public static final String jPPBoxLanguage = jPPPackage + ".BoxLanguage";
public static final String jPPBoxStack = jPPPackage + ".BoxStack";
Grammar2Ecore g2e = null;
private String ecorizeMethodBody = "";
private String ecorizeArgName = null;
private String ecorizeResultName = null;
private String unparseBufferName = null;
private String ppStackName = null;
private String ppStackStmts = "";
private String jPPCommand = jPPPackage + ".PPCommand";
public GenUnparseInhaleAndMMForSeqRules(EClass ecorizer2, RootCS c2,
Grammar2Ecore g2e) {
this.ecorizer = ecorizer2;
this.c = c2;
this.g2e = g2e;
if (g2e.genEcorizer) {
createEcorizersForSeqRulesAndAltWithSeqOnlyRules();
}
for (SeqRuleCS srCS : c.seqRules) {
assert (srCS.eClass != null);
/*
* here names can be chosen for (ecorize, unparse) java methods so
* as not to collide with fields
*/
ecorizeArgName = "astNode";
ecorizeResultName = "res";
unparseBufferName = "buf";
ppStackName = "ppBoxStack";
/*
* For example, the first executable stmt of an ecorize method can
* be like:
*
* SubPackageDecl res =
* EmfaticFactory.eINSTANCE.createSubPackageDecl();
*
* Such instance is going to be given values for its attributes and
* references taking them from the AST node returned by the parser.
*/
ecorizeMethodBody = srCS.getAsJavaComment();
ecorizeMethodBody += newLine + srCS.eClass.getName() + " "
+ ecorizeResultName + " = " + c.languageFactoryImpl(srCS)
+ ".eINSTANCE.create" + srCS.eClass.getName() + "();";
unparseMethodBody = srCS.getAsJavaComment();
unparseMethodBody += newLine + "StringBuffer " + unparseBufferName
+ " = new StringBuffer();";
ppStackStmts = srCS.getAsJavaComment();
ppStackStmts += newLine
+ String.format(" %1s %2s = new %3s();", jPPBoxStack,
ppStackName, jPPBoxStack);
List<SeqExprCS> items = srCS.seqexprs;
for (SeqExprCS item : items) {
SeqExprKind k = item.getKind();
switch (k) {
case CONSTANT_CONTENT:
// a) isBuiltInToken, isSurroundedByQuotes. May be optional
caseConstantContent(item);
break;
case REFERS_TO_RULE_WITH_ECLASS:
case REFERS_TO_RULE_WITH_EENUM:
/*
* b) the item refers to a rule having an EClassifier as
* counterpart
*/
caseInvokesRuleWithEClassifier(item);
break;
case KEEP_AS_STR:
case KEEP_AS_CHR:
case KEEP_AS_INT:
// c) can be converted to str or int
caseSFStrOrInt(item, k);
break;
case REFERS_TO_LIST_RULE:
// d) the item stands for an invocation of a list rule
caseConstituentIsListRule(item);
break;
}
}
if (g2e.genUnparser) {
if (g2e.genPrettyPrinter) {
unparseMethodBody = newLine
+ "return prettyPrint().toString();";
} else {
unparseMethodBody += newLine + "return "
+ unparseBufferName + ".toString();";
}
Grammar2Ecore.newUnparseOperation(srCS.eClass,
unparseMethodBody);
}
if (g2e.genEcorizer) {
ecorizeMethodBody += newLine + "return " + ecorizeResultName
+ ";";
Grammar2Ecore.newMethodBodyAnnotation(srCS.ecorizeEOp,
ecorizeMethodBody);
}
if (g2e.genPrettyPrinter) {
String ppMethodBody = ppStackStmts;
ppMethodBody += newLine
+ String
.format(
"return %1s.packHorizUpToWidth(35, 1, %2s.stack.size());",
ppStackName, ppStackName);
srCS.prettyPrintEOp = Grammar2Ecore.newPrettyPrintOperation(
srCS.eClass, ppMethodBody);
}
}
}
private void createEcorizersForSeqRulesAndAltWithSeqOnlyRules() {
for (SeqRuleCS srCS : c.seqRules) {
/*
* The create of "ecorize" operations (to perform Gymnast AST Node
* -> Ecore-based one) takes place now so as to populate for each
* SeqRuleCS its field ecorizeEOp. The method body itself will be
* computed afterwards.
*/
srCS.ecorizeEOp = Grammar2Ecore.newEcorizeOperation(ecorizer, srCS,
srCS.eClass);
}
/*
* Precondition: createEmptyClassesForAltRulesWithSeqItemsOnly() has
* been called already.
*/
for (AltRuleCS arCS : c.altRules) {
if (arCS.getKindOfAlts() == AltRuleAltsKind.CONTAINSSEQ) {
assert arCS.eClass != null;
arCS.ecorizeEOp = Grammar2Ecore.newEcorizeOperation(ecorizer,
arCS, arCS.eClass);
Grammar2Ecore.newGrammarRuleAnnotation(arCS.ecorizeEOp,
"AltRule", arCS.toString());
/*
* Adding the Java method body to arCS.ecorizeEOp is done as
* part of creating the ecorize "big switch", during the
* execution of the constructor EcorizeOperation(EClass
* ecorizer, RootCS c2)
*/
}
}
}
/**
* c) can be converted to str or int
*/
private void caseSFStrOrInt(final SeqExprCS item, final SeqExprKind k) {
assert ((k == SeqExprKind.KEEP_AS_INT)
|| (k == SeqExprKind.KEEP_AS_STR) || (k == SeqExprKind.KEEP_AS_CHR));
// --------- (1) MM -------------------------------------------
EStructuralFeature val = null;
EDataType t = null;
EClass eC = item.srCS.eClass;
if (k == SeqExprKind.KEEP_AS_STR) {
t = EcorePackage.eINSTANCE.getEString();
} else if (k == SeqExprKind.KEEP_AS_CHR) {
t = EcorePackage.eINSTANCE.getEChar();
} else {
t = EcorePackage.eINSTANCE.getELong();
}
val = MyEcoreUtil.newAttribute(item.suggestedName(), eC, t);
val.setUnsettable(item.isOptional);
val.setLowerBound(item.isOptional ? 0 : 1);
val.setUpperBound(1);
// --------- (2) stms for inhale (ecorize) ---------------------
String jOptionalCheck = ecorizeArgName + jDOT
+ item.gymnastGeneratedGetter() + " != null";
String rhs = ecorizeArgName + "." + item.gymnastGeneratedGetter()
+ ".getText()";
if (k == SeqExprKind.KEEP_AS_CHR) {
rhs = rhs + ".charAt(0)";
}
if (k == SeqExprKind.KEEP_AS_INT) {
rhs = "Long.valueOf(" + rhs + ")";
}
String jSetterInvocation = ecorizeResultName + jDOT + jSetter(val)
+ "(" + rhs + ") ; ";
String jStmtUnset = null;
boolean unsetIfNotInInput = item.isOptional;
if (item.isOptional) {
jStmtUnset = ecorizeResultName + jDOT + jUnsetter(val) + "; ";
}
ecorizeMethodBody = wrapWithCheckIfOptional(ecorizeMethodBody, item,
jOptionalCheck, jSetterInvocation, unsetIfNotInInput,
jStmtUnset);
// --------- (3) stms for unparse ------------------------------
if (item.isOptional) {
jOptionalCheck = jIsSet(val);
}
String jAppendStmt = unparseBufferName + ".append(" + jGetter(val)
+ jPLUS + jStrBLANK + jRPAREN + jSEMI;
unparseMethodBody = wrapWithCheckIfOptional(unparseMethodBody, item,
jOptionalCheck, jAppendStmt, false, null);
// --------- (4) stms for unparse ------------------------------
if (item.isOptional) {
jOptionalCheck = jIsSet(val);
}
jAppendStmt = ppStackName + ".add(" + jGetter(val) + jRPAREN + jSEMI;
unsetIfNotInInput = true;
jStmtUnset = ppStackName + ".add( null );";
ppStackStmts = wrapWithCheckIfOptional(ppStackStmts, item,
jOptionalCheck, jAppendStmt, unsetIfNotInInput, jStmtUnset);
}
private String jIsSet(EStructuralFeature eSF) {
String res = "isSet" + RootCS.camelCase(eSF.getName()) + "()";
return res;
}
/**
* With trailing "()"
*
* @param eSFName
* @return
*/
private String jUnsetter(EStructuralFeature eSF) {
String res = "unset" + RootCS.camelCase(eSF.getName()) + "()";
return res;
}
/**
* Without trailing "()"
*
* @param eSFName
* @return
*/
private String jSetter(EStructuralFeature eSF) {
String res = "set" + RootCS.camelCase(eSF.getName());
return res;
}
/**
* With trailing "()"
*
* @param eSFName
* @return
*/
private String jGetter(EStructuralFeature eSF) {
boolean fieldIsBoolean = false;
if (eSF.getEType().equals(EcorePackage.eINSTANCE.getEBoolean())) {
fieldIsBoolean = true;
}
if (eSF.getEType().equals(EcorePackage.eINSTANCE.getEBooleanObject())) {
fieldIsBoolean = true;
}
String res = fieldIsBoolean ? "is" : "get";
res += RootCS.camelCase(eSF.getName()) + "()";
return res;
}
private String wrapWithCheckIfOptional(String methodBody, SeqExprCS item,
String jOptionalCheck, String jStmt, boolean unsetIfNotInInput,
String jStmtUnset) {
assert unsetIfNotInInput ? !jStmtUnset.equals("") : true;
if (item.isOptional) {
methodBody += newLine + "if (" + jOptionalCheck + ") {";
}
methodBody += newLine + jStmt;
if (item.isOptional) {
methodBody += newLine + "}";
if (unsetIfNotInInput) {
methodBody += " else { " + jStmtUnset + " } ";
}
}
return methodBody;
}
/**
* d) the item stands for an invocation of a list rule
*
* TODO what if the separator is not a constant value but one among many
* (e.g. qIdSeparator)
*
* the elements are to be printed using .getLiteral() , .unparse , or as is
* (implicit toString)
*
*/
private void caseConstituentIsListRule(SeqExprCS item) {
// --------- (1) MM -------------------------------------------
/*
* add always a list for the items, and possibly another for the
* separators if these are not constant.
*/
ListRuleCS lrCS = c.findListRuleCSByName(item.value);
String suggestedName = item.optFieldName.equals("") ? lrCS
.getPreferredItemName() : item.optFieldName;
EClassifier refedEType = c.getETypeForRuleName(lrCS.e1);
EStructuralFeature val = null;
SeqExprKind k = lrCS.getKindOfItem();
String iteratorItemType = null;
EClass eC = item.srCS.eClass;
if (refedEType != null) {
val = addStructuralFeatureForRuleInvocation(suggestedName,
lrCS.lowerBound == 0, refedEType, item.srCS.eClass);
} else {
EDataType t = null;
k = lrCS.getKindOfItem();
if (k == SeqExprKind.KEEP_AS_STR
|| k == SeqExprKind.CONSTANT_CONTENT) {
t = EcorePackage.eINSTANCE.getEString();
iteratorItemType = "String";
} else if (k == SeqExprKind.KEEP_AS_CHR) {
t = EcorePackage.eINSTANCE.getEChar();
iteratorItemType = "Char";
} else {
t = EcorePackage.eINSTANCE.getELong();
iteratorItemType = "Long";
}
val = MyEcoreUtil.newAttribute(
turnIntoPlural(item.suggestedName()), eC, t);
val.setLowerBound(item.isOptional ? 0 : 1);
}
val.setUpperBound(-1);
val.setUnique(false);
val.setOrdered(true);
item.eSFListForRefedItems = val;
boolean bSeparatorsHaveNodes = !lrCS.separator.equals("");
boolean bRecordSeparators = bSeparatorsHaveNodes
&& !lrCS.hasConstantSeparator();
if (bRecordSeparators) {
EStructuralFeature valSeparators = MyEcoreUtil.newAttribute(item
.suggestedName()
+ "Separators", eC, EcorePackage.eINSTANCE.getEString());
valSeparators.setLowerBound(item.isOptional ? 0 : 1);
valSeparators.setUpperBound(-1);
valSeparators.setUnique(false);
valSeparators.setOrdered(true);
item.eSFListForSeparators = valSeparators;
} else {
item.eSFListForSeparators = null;
}
// --------- (2) stms for inhale (ecorize) ---------------------
boolean itemCanBeSerialized = item.eSFListForRefedItems.getEType() instanceof EDataType;
String gymnastGetter = item.gymnastGeneratedGetter();
/*
* This getter returns an instance of the list, whose children are items
* proper and separators.
*/
String jIsSeparatorLocalVarName = "isSeparator" + val.getName();
ecorizeMethodBody += newLine
+ String.format("if ( %1s != null) {", ecorizeArgName + "."
+ gymnastGetter);
if (bSeparatorsHaveNodes) {
ecorizeMethodBody += newLine
+ String.format("boolean %1s = false;",
jIsSeparatorLocalVarName);
}
ecorizeMethodBody += newLine
+ "for (org.eclipse.gymnast.runtime.core.ast.ASTNode itemOrSeparator : "
+ ecorizeArgName + "." + gymnastGetter + ".getChildren() ) {";
String rhs = null;
if (itemCanBeSerialized) {
// no need to call ecorize
rhs = "itemOrSeparator.getText()";
if (k == SeqExprKind.KEEP_AS_INT) {
rhs = "Long.valueOf(" + rhs + ")";
}
} else {
// downcasts included
String jFQNAST = c.getOption_astPackageName() + "."
+ c.getOption_astBaseClassName();
rhs = "ecorize( (" + jFQNAST + ") itemOrSeparator)";
rhs = "( " + item.eSFListForRefedItems.getEType().getName() + " )"
+ rhs;
}
if (bSeparatorsHaveNodes) {
ecorizeMethodBody += newLine + " if (!"
+ jIsSeparatorLocalVarName + ") { ";
}
ecorizeMethodBody += ecorizeResultName + "."
+ jGetter(item.eSFListForRefedItems) + ".add(" + rhs + "); ";
if (bSeparatorsHaveNodes) {
ecorizeMethodBody += newLine + "} /* close if separator */";
}
if (bRecordSeparators) {
ecorizeMethodBody += newLine
+ String
.format(
"else { %1s.%2s.add( itemOrSeparator.getText() ); }",
ecorizeResultName,
jGetter(item.eSFListForSeparators));
}
if (bSeparatorsHaveNodes) {
ecorizeMethodBody += newLine + jIsSeparatorLocalVarName + " = !"
+ jIsSeparatorLocalVarName + ";";
}
ecorizeMethodBody += newLine + "} /* close for */";
ecorizeMethodBody += newLine + "} /* close if */";
// --------- (3) stmts for unparse ------------------------------
String iterName = "iter" + item.eSFListForRefedItems.getName();
String iterNameSeparators = null;
if (bRecordSeparators) {
iterNameSeparators = "iter" + item.eSFListForSeparators.getName();
}
rhs = iterName + ".next()";
if (!itemCanBeSerialized) {
rhs = rhs + ".unparse()";
}
if (!itemCanBeSerialized) {
iteratorItemType = item.eSFListForRefedItems.getEType().getName();
}
unparseMethodBody += newLine + "java.util.Iterator<" + iteratorItemType
+ "> " + iterName + " = " + jGetter(item.eSFListForRefedItems)
+ ".iterator();";
if (bRecordSeparators) {
unparseMethodBody += newLine + "java.util.Iterator<String> "
+ iterNameSeparators + " = "
+ jGetter(item.eSFListForSeparators) + ".iterator();";
}
unparseMethodBody += newLine + "while (" + iterName + ".hasNext() ) { ";
unparseMethodBody += newLine + unparseBufferName + ".append(" + rhs
+ ");";
String rhsIter = null;
if (bRecordSeparators) {
rhsIter = String.format(" ( %1s.hasNext() ? %2s.next() : %3s) ",
iterNameSeparators, iterNameSeparators, jStrBLANK);
} else {
rhsIter = "\"" + lrCS.unparseConstantSeparator() + "\"" + jPLUS
+ jStrBLANK;
rhsIter = String.format(" ( %1s.hasNext() ? %2s : %3s) ", iterName,
rhsIter, jStrBLANK);
}
unparseMethodBody += newLine + unparseBufferName + ".append(" + rhsIter
+ ");";
unparseMethodBody += newLine + "} /* close while */";
// --------- (4) stms for prettyPrint ------------------------------
String jGetterItems = jGetter(item.eSFListForRefedItems);
String jGetterSeps = null;
String jAppendExpr = null;
if (bRecordSeparators) {
jGetterSeps = jGetter(item.eSFListForSeparators);
jAppendExpr = String
.format(jPPBoxLanguage + ".interleaveH(%1s, %2s, 0, 0)",
jGetterItems, jGetterSeps);
} else {
if (lrCS.unparseConstantSeparator().trim().equals("")) {
jAppendExpr = jGetterItems;
} else {
jGetterSeps = jStrWithQuoteEscaped
+ lrCS.unparseConstantSeparator()
+ jStrWithQuoteEscaped;
jAppendExpr = String.format(jPPBoxLanguage
+ ".interleaveHSepConstant(%1s, %2s, 0, 0)",
jGetterSeps, jGetterItems);
}
}
ppStackStmts += newLine + ppStackName + ".add(" + jAppendExpr + jRPAREN
+ jSEMI;
}
private String turnIntoPlural(String suggestedName) {
return suggestedName.endsWith("s") ? suggestedName : suggestedName
+ "s";
}
/**
* b) the item refers to a rule having an EClassifier as counterpart
*
* a (possibly optional) eSF is added as counterpart to item
*
* when inhaling, (detect if present) and set, otherwise set to null (and
* not to the default value of enums)
*
* when unparsing, invoke with .unparse() for non-enums and with
* .getLiteral() for enums
*
* @param k
*
*
*/
private void caseInvokesRuleWithEClassifier(SeqExprCS item) {
// --------- (1) MM -------------------------------------------
String suggestedName = item.suggestedName();
EClassifier refedEType = c.getETypeForRuleName(item.value);
assert refedEType != null;
item.eSF = addStructuralFeatureForRuleInvocation(suggestedName,
item.isOptional, refedEType, item.srCS.eClass);
/*
* An enum can be assigned null in Java, but EMF intercepts that (in the
* setter for the EStructuralFeature) and assigns the default instead
*/
boolean optionalForEnumRequired = item.isOptional
&& item.eSF.getEType() instanceof EEnum;
if (optionalForEnumRequired) {
item.eSF.setUnsettable(true);
}
// --------- (2) stms for inhale (ecorize) ---------------------
String rhs = ecorizeArgName + jDOT + item.gymnastGeneratedGetter();
String jOptionalCheck = rhs + " != null";
RuleCS refed = item.getRefedRuleIfAny();
assert refed != null;
String quotedFirstAlternative = "";
String quotedSecondAlternative = "";
if (refed.canBeRegardedAsBoolean()) {
if (refed instanceof AltRuleCS) {
AltRuleCS arCS = (AltRuleCS) refed;
quotedFirstAlternative = arCS.getFirstAlternative();
quotedSecondAlternative = arCS.getSecondAlternative();
}
if (refed instanceof TokenRuleCS) {
TokenRuleCS trCS = (TokenRuleCS) refed;
quotedFirstAlternative = trCS.alts.get(0);
quotedSecondAlternative = trCS.alts.get(1);
}
String jBooleanExpr = String.format(" %1s.getText().equals(%2s) ",
rhs, quotedFirstAlternative );
rhs = jLPAREN + jBooleanExpr + jRPAREN;
} else {
String jEcorizerForRefed = "ecorize" + RootCS.camelCase(refed.name);
rhs = jEcorizerForRefed + jLPAREN + rhs + jRPAREN;
}
String jSetterInvocation = ecorizeResultName + jDOT + jSetter(item.eSF)
+ "(" + rhs + ") ; ";
String jSetToNull = null;
final boolean addAssignNullStmtIfNotInInput = item.isOptional;
if (optionalForEnumRequired) {
jSetToNull = " /* The EMF-generated setter intercepts null assignments and sets the enum to its default value. That's why the unsetting below is needed. */ ";
jSetToNull += newLine + ecorizeResultName + jDOT
+ jUnsetter(item.eSF) + "; ";
} else {
jSetToNull = ecorizeResultName + jDOT + jSetter(item.eSF)
+ "( null ) ; ";
}
ecorizeMethodBody = wrapWithCheckIfOptional(ecorizeMethodBody, item,
jOptionalCheck, jSetterInvocation,
addAssignNullStmtIfNotInInput, jSetToNull);
// --------- (3) stms for unparse ------------------------------
String jGetter = null;
if (refedEType instanceof EEnum) {
jGetter = jGetter(item.eSF) + ".getLiteral()";
if (item.isOptional) {
jOptionalCheck = jIsSet(item.eSF);
}
} else if (refed.canBeRegardedAsBoolean()) {
jGetter = String.format("( %1s ? %2s : %3s )", jGetter(item.eSF) , quotedFirstAlternative , quotedSecondAlternative);
} else {
jGetter = jGetter(item.eSF) + ".unparse()";
jOptionalCheck = jGetter(item.eSF) + " != null ";
}
String jAppendStmt = unparseBufferName + ".append(" + jGetter + jPLUS
+ jStrBLANK + jRPAREN + jSEMI;
unparseMethodBody = wrapWithCheckIfOptional(unparseMethodBody, item,
jOptionalCheck, jAppendStmt, false, null);
// --------- (4) stms for prettyPrint ------------------------------
jGetter = null;
if (refedEType instanceof EEnum) {
jGetter = jGetter(item.eSF) + ".getLiteral()";
if (item.isOptional) {
jOptionalCheck = jIsSet(item.eSF);
}
} else if (refed.canBeRegardedAsBoolean()) {
jGetter = String.format("( %1s ? %2s : %3s )", jGetter(item.eSF) , quotedFirstAlternative , quotedSecondAlternative);
} else {
jGetter = jGetter(item.eSF) + ".prettyPrint()";
jOptionalCheck = jGetter(item.eSF) + " != null ";
}
jAppendStmt = ppStackName + ".add(" + jGetter + jRPAREN + jSEMI;
boolean unsetIfNotInInput = true;
String jStmtUnset = ppStackName + ".add( null );";
ppStackStmts = wrapWithCheckIfOptional(ppStackStmts, item,
jOptionalCheck, jAppendStmt, unsetIfNotInInput, jStmtUnset);
}
/**
* a) This case is due to isBuiltInToken or isSurroundedByQuotes. There are
* two subcases:
*
* a.1) optional -> a boolean eSF. To be set when inhaling, controls whether
* a String literal is written when unparsing.
*
* a.2) mandatory -> no eSF. Nothing is read when inhaling, a String literal
* is written when unparsing.
*
*
*/
private void caseConstantContent(SeqExprCS item) {
// --------- (1) MM -------------------------------------------
String constantContent = item.unparseValue(c);
EAttribute val = null;
if (item.isOptional) {
EDataType t = EcorePackage.eINSTANCE.getEBoolean();
String suggestedName = item.suggestedName();
val = MyEcoreUtil.newAttribute(suggestedName, item.srCS.eClass, t);
val.setLowerBound(1);
val.setUpperBound(1);
val.setUnsettable(true);
}
if (c.getOption_ecorizer()) {
assert MyEcoreUtil.isWellFormed(ecorizer.getEPackage());
}
// --------- (2) stms for inhale (ecorize) ---------------------
if (item.isOptional) {
String jOptionalCheck = ecorizeArgName + jDOT
+ item.gymnastGeneratedGetter() + " != null ";
String jSetterInvocation = ecorizeResultName + jDOT + jSetter(val)
+ "( true ) ; ";
final boolean addAssignNullStmtIfNotInInput = true;
String jSetToNull = ecorizeResultName + jDOT + jSetter(val)
+ "( false ) ; ";
ecorizeMethodBody = wrapWithCheckIfOptional(ecorizeMethodBody,
item, jOptionalCheck, jSetterInvocation,
addAssignNullStmtIfNotInInput, jSetToNull);
} else {
ecorizeMethodBody += newLine
+ "/* input contains here a mandatory " + constantContent
+ " */";
}
// --------- (3) stms for unparse ------------------------------
String jArgToAppend = jStrWithQuoteEscaped + constantContent
+ jStrWithQuoteEscaped;
String jAppendStmt = unparseBufferName + ".append(" + jArgToAppend
+ jPLUS + jStrBLANK + jRPAREN + jSEMI;
if (item.isOptional) {
String jOptionalCheck = jGetter(val) + " != false ";
unparseMethodBody = wrapWithCheckIfOptional(unparseMethodBody,
item, jOptionalCheck, jAppendStmt, false, null);
} else {
unparseMethodBody += jAppendStmt;
}
// --------- (4) stms for prettyPrint ------------------------------
jAppendStmt = ppStackName + ".add(" + jArgToAppend + jRPAREN + jSEMI;
if (item.isOptional) {
String jOptionalCheck = jGetter(val) + " != false ";
boolean unsetIfNotInInput = true;
String jStmtUnset = ppStackName + ".add( null );";
ppStackStmts = wrapWithCheckIfOptional(ppStackStmts, item,
jOptionalCheck, jAppendStmt, unsetIfNotInInput, jStmtUnset);
} else {
ppStackStmts += newLine + jAppendStmt;
}
}
private String jPPStackAdd(String arg) {
String jStmt = String.format("prettyPrintStack.add(\" %1s \");", arg);
return jStmt;
}
private EStructuralFeature addStructuralFeatureForRuleInvocation(
String suggestedName, boolean isOptional, EClassifier refedEType,
EClass owningClass) {
EStructuralFeature val = null;
/*
* constituent is seq rule, or token or alt rule with fixed keywords
*/
if (refedEType instanceof EClass) {
EReference valAsRef = MyEcoreUtil.newReference(suggestedName,
owningClass, (EClass) refedEType);
valAsRef.setContainment(true);
val = valAsRef;
} else {
val = MyEcoreUtil.newAttribute(suggestedName, owningClass,
(EDataType) refedEType);
}
val.setLowerBound(isOptional ? 0 : 1);
val.setUpperBound(1);
return val;
}
}