/*******************************************************************************
* Copyright (c) 2008 SAP
* see https://research.qkal.sap.corp/mediawiki/index.php/CoMONET
*
* Date: $Date: 2009-09-18 14:13:44 +0200 (Fr, 18 Sep 2009) $
* @version $Revision: 7886 $
* @author: $Author: c5106462 $
*******************************************************************************/
package com.sap.furcas.parsergenerator.tcs.t2m.grammar;
import com.sap.furcas.metamodel.FURCAS.TCS.Alternative;
import com.sap.furcas.metamodel.FURCAS.TCS.Block;
import com.sap.furcas.metamodel.FURCAS.TCS.ConditionalElement;
import com.sap.furcas.metamodel.FURCAS.TCS.CustomSeparator;
import com.sap.furcas.metamodel.FURCAS.TCS.FunctionCall;
import com.sap.furcas.metamodel.FURCAS.TCS.InjectorActionsBlock;
import com.sap.furcas.metamodel.FURCAS.TCS.Literal;
import com.sap.furcas.metamodel.FURCAS.TCS.LiteralRef;
import com.sap.furcas.metamodel.FURCAS.TCS.Property;
import com.sap.furcas.metamodel.FURCAS.TCS.Sequence;
import com.sap.furcas.metamodel.FURCAS.TCS.SequenceElement;
import com.sap.furcas.runtime.common.exceptions.MetaModelLookupException;
import com.sap.furcas.runtime.common.exceptions.SyntaxElementException;
import com.sap.furcas.runtime.parser.exceptions.SyntaxParsingException;
import com.sap.furcas.runtime.tcs.SyntaxLookup;
import com.sap.furcas.runtime.tcs.TemplateNamingHelper;
/**
* Utility class to make Interfaces easier to understand. Works as a combination
* of a StringBuffer and a Class to be called recursively. This class calls
* handlers which during that call may call this class again, to produce nested
* production rule bodies.
*
* @author C5127705
*/
public class SemanticRuleBodyStringBuffer extends RuleBodyStringBuffer {
// elements protected to make unit testing a bit easier
private final String semanticRef;
/**
* Instantiates a new rule body string buffer.
*
* @param newAlternativeHandler
* the alternative handler
* @param blockHandler
* the block handler
* @param conElHandler
* the con el handler
* @param propertyHandler
* the property handler
* @param syntaxLookup
* the syntax lookup
* @param namingHelper
* @param errorBucket
* @param newInjectorActionsHandler
*/
public SemanticRuleBodyStringBuffer(
AlternativeHandler newAlternativeHandler,
BlockTypeHandler blockHandler,
ConditionalElementHandler<?> conElHandler,
PropertyTypeHandler<?> propertyHandler, SyntaxLookup syntaxLookup,
TemplateNamingHelper<?> namingHelper,
InjectorActionsHandler<?> newInjectorActionsHandler,
SemanticErrorBucket errorBucket, String semanticRef) {
super(newAlternativeHandler, blockHandler, conElHandler,
propertyHandler, syntaxLookup, namingHelper,
newInjectorActionsHandler, errorBucket);
this.semanticRef = semanticRef;
}
@Override
protected void addToRuleFragment(Sequence seq)
throws MetaModelLookupException {
if (seq == null) {
return;
}
blockHandler.addElement(seq, this, semanticRef);
}
/**
* recursive call for elements that do not create a rule of their own, but
* influence creation of a rule body.
*
* @param element
* the element
*
* @throws SyntaxParsingException
* the syntax parsing exception
* @throws MetaModelLookupException
* the meta model lookup exception
*/
@Override
protected void addToRuleFragment(SequenceElement element)
throws MetaModelLookupException {
try {
if (element == null) {
return;
}
this.append(ObservationDirectivesHelper
.getEnterSequenceElementNotification(element));
if (element instanceof Block) {
Block seq = (Block) element;
blockHandler.addElement(seq, this,semanticRef);
} else if (element instanceof Property) {
Property prop = (Property) element;
propertyHandler.addElement(prop, this);
} else if (element instanceof Literal) {
Literal lit = (Literal) element;
this.append(lit.getValue());
} else if (element instanceof LiteralRef) {
LiteralRef lit = (LiteralRef) element;
if (lit.getReferredLiteral() == null) {
throw new RuntimeException(
"Bug: Missing reference, check that references were set after parsing in "
+ element);
}
String value = lit.getReferredLiteral().getValue();
this.append(syntaxLookup.getSymbolRule(value));
} else if (element instanceof ConditionalElement) {
ConditionalElement conEl = (ConditionalElement) element;
conElHandler.addElement(conEl, this);
} else if (element instanceof Alternative) {
Alternative alt = (Alternative) element;
alternativeHandler.addElement(alt, this);
} else if (element instanceof InjectorActionsBlock) {
//InjectorActionsBlock block = (InjectorActionsBlock) element;
//injectorActionsHandler.addElement(block, this);
} else if (element instanceof CustomSeparator) {
// CustomSeparator conEl = (CustomSeparator) element;
// ignore here, only relevant for serializing
// throw new
// RuntimeException("CustomSeparator mapping not implemented yet in "
// + element.getLocation());
} else if (element instanceof FunctionCall) {
FunctionCall funcCall = (FunctionCall) element;
if (funcCall.getCalledFunction() == null) {
throw new RuntimeException(
"Bug: Missing Function Template in function call in "
+ element);
}
String rulename = namingHelper.getRuleName(funcCall
.getCalledFunction());
this.append(rulename + "[ret]");
} else {
// should never happen, as long as TCS defines only the
// SequenceElement subclasses above
throw new RuntimeException("Unknown kind of SequenceElement "
+ element.getClass());
}
} catch (SyntaxElementException e) {
errorBucket.addException(e);
}
this.append(ObservationDirectivesHelper
.getExitSequenceElementNotification());
}
}