/* "CodeWorker": a scripting language for parsing and generating text. Copyright (C) 1996-1997, 1999-2002 Cédric Lemaire This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA To contact the author: codeworker@free.fr */ #ifdef WIN32 #pragma warning (disable : 4786) #endif #include "UtlException.h" #include "ScpStream.h" #include "CppCompilerEnvironment.h" #include "CGRuntime.h" #include "DtaScript.h" #include "DtaProject.h" #include "DtaClass.h" #include "DtaBNFScript.h" #include "DtaVisitor.h" #include "BNFClause.h" namespace CodeWorker { BNFClauseMatchingArea::~BNFClauseMatchingArea() { for (std::list::iterator i = childs.begin(); i != childs.end(); ++i) { delete *i; } } void BNFClauseMatchingArea::purgeChildsAfterPosition(int iPosition) { while (!childs.empty() && (childs.back()->endPosition > iPosition)) { delete childs.back(); childs.pop_back(); } } class BNFClauseMatchingAreaValidator { private: DtaBNFScript* pBNFScript_; BNFClauseMatchingArea* pOld_; public: BNFClauseMatchingAreaValidator(BNFClause* pClause, DtaBNFScript* pBNFScript) { if (!pBNFScript->hasCoverageRecording()) { pBNFScript_ = NULL; } else { pBNFScript_ = pBNFScript; pOld_ = pBNFScript->getParentClauseMatching(); pBNFScript->setParentClauseMatching(new BNFClauseMatchingArea(pClause, CGRuntime::getInputLocation())); } } ~BNFClauseMatchingAreaValidator() { if (pBNFScript_ != NULL) { if (pBNFScript_->getParentClauseMatching()->endPosition < 0) { // the clause has failed! delete pBNFScript_->getParentClauseMatching(); // if (pOld_ != NULL) pOld_->popChild(); pBNFScript_->setParentClauseMatching(pOld_); } else { // the clause has succeeded, keep the matching // and don't loose the header clause matching! if (pOld_ != NULL) pBNFScript_->setParentClauseMatching(pOld_); } } } void validate() { if (pBNFScript_ != NULL) { BNFClauseMatchingArea* pNew = pBNFScript_->getParentClauseMatching(); if (pNew->endPosition < 0) { // prevents against multiple call to 'validate()' (shouldn't) pNew->endPosition = CGRuntime::getInputLocation(); if (pOld_ != NULL) pOld_->pushChild(pNew); } } } }; int BNFClause::NO_RETURN_TYPE = 0; int BNFClause::LIST_RETURN_TYPE = 1; int BNFClause::NODE_RETURN_TYPE = 2; int BNFClause::VALUE_RETURN_TYPE = 3; BNFClause::BNFClause(DtaBNFScript* pBNFScript, GrfBlock* pParent, const std::string& sName, const std::string& sTemplateKey, bool bGenericKey, const std::vector& listOfParameters, const std::vector& listOfParameterTypes) : _pBNFScript(pBNFScript), GrfBlock(pParent), _sName(sName), _sTemplateKey(sTemplateKey), _bGenericKey(bGenericKey), _pTemplateClause(NULL), _pGenericTemplateClause(NULL), _iReturnType(0), _parameters(listOfParameters), _parameterTypes(listOfParameterTypes), _pOverloadClause(NULL), _bPropagatedParameters(false), _iPreprocessingIgnoreMode(0/*UNDEFINED_IGNORE*/), _pPreprocessingIgnoreClause(NULL) { } BNFClause::BNFClause(DtaBNFScript* pBNFScript, GrfBlock* pParent, const std::string& sName, int iArity) : _pBNFScript(pBNFScript), GrfBlock(pParent), _sName(sName), _bGenericKey(false), _pTemplateClause(NULL), _pGenericTemplateClause(NULL), _iReturnType(0), _pOverloadClause(NULL), _bPropagatedParameters(false), _iPreprocessingIgnoreMode(0/*UNDEFINED_IGNORE*/), _pPreprocessingIgnoreClause(NULL) { _parameters.resize(iArity); _parameterTypes.resize(iArity); } BNFClause::~BNFClause() { delete _pOverloadClause; } void BNFClause::accept(DtaVisitor& visitor, DtaVisitorEnvironment& env) { visitor.visitBNFClause(*this, env); } void BNFClause::setPreprocessingIgnoreMode(int/*IGNORE_MODE*/ iPreprocessingIgnoreMode, BNFClause* pIgnoreClause) { _iPreprocessingIgnoreMode = iPreprocessingIgnoreMode; _pPreprocessingIgnoreClause = pIgnoreClause; if (_pTemplateClause != NULL) { // the default template clause might have been created implicitly, // so the preprocessing ignore mode isn't initialized _pTemplateClause->_iPreprocessingIgnoreMode = _iPreprocessingIgnoreMode; _pTemplateClause->_pPreprocessingIgnoreClause = _pPreprocessingIgnoreClause; } } bool BNFClause::isABNFCommand() const { return true; } void BNFClause::setTemplateClause(BNFClause* pTemplateClause) { _pTemplateClause = pTemplateClause; if (isGenericKey()) _pTemplateClause->_pGenericTemplateClause = this; else _pTemplateClause->_mapOfTemplateInstantiations[_sTemplateKey] = this; } BNFClause* BNFClause::getInstantiatedClause(const std::string& sInstantiationKey) const { std::map::const_iterator cursor = _mapOfTemplateInstantiations.find(sInstantiationKey); if (cursor == _mapOfTemplateInstantiations.end()) { if (sInstantiationKey.empty() && (getNbCommands() != 0)) return const_cast(this); return _pGenericTemplateClause; } return cursor->second; } void BNFClause::setParameter(int i, const std::string& sParameter, EXPRESSION_TYPE iType) { _parameters[i] = sParameter; _parameterTypes[i] = iType; } void BNFClause::setOverloadClause(BNFClause* pOverloadClause) { if (_pOverloadClause != NULL) _pOverloadClause->setOverloadClause(pOverloadClause); else _pOverloadClause = pOverloadClause; } bool BNFClause::propagateParameters(ExprScriptExpression& theFilter, const std::string& sFunctionQuantity, const std::vector& listOfParameters, const std::vector& listOfParameterTypes) { DtaScriptVariable theContext; std::string sSignature = getSignature(); theContext.setValueAtVariable(sFunctionQuantity.c_str(), sSignature.c_str()); std::string sResult = theFilter.getValue(theContext); bool bResult = (!sResult.empty()); if (bResult) { _bPropagatedParameters = true; if (listOfParameters.size() < getArity()) throw UtlException("while propagating parameters on non terminals, not enough parameters assigned to " + sFunctionQuantity + "='" + sSignature + "'"); std::string::size_type i; for (i = 0; i < getArity(); ++i) { if (getParameterType(i) != listOfParameterTypes[i]) throw UtlException("while propagating parameters on non terminals, incompatible parameter type assigned to " + sFunctionQuantity + "='" + sSignature + "'/parameter='" + listOfParameters[i] + "'"); } for (i = getArity(); i < listOfParameterTypes.size(); ++i) { _parameters.push_back(listOfParameters[i]); _parameterTypes.push_back(listOfParameterTypes[i]); } } if ((_pGenericTemplateClause != NULL) && _pGenericTemplateClause->propagateParameters(theFilter, sFunctionQuantity, listOfParameters, listOfParameterTypes)) bResult = true; for (std::map::iterator i = _mapOfTemplateInstantiations.begin(); i != _mapOfTemplateInstantiations.end(); ++i) { if (i->second->propagateParameters(theFilter, sFunctionQuantity, listOfParameters, listOfParameterTypes)) bResult = true; } if ((_pOverloadClause != NULL) && _pOverloadClause->propagateParameters(theFilter, sFunctionQuantity, listOfParameters, listOfParameterTypes)) bResult = true; if (bResult && !_bPropagatedParameters) { ExprScriptConstant alwaysTrue(true); propagateParameters(alwaysTrue, sFunctionQuantity, listOfParameters, listOfParameterTypes); } return bResult; } bool BNFClause::addBNFLocalVariable(const std::string& sVarName, EXPRESSION_TYPE varType) { return addLocalVariable(sVarName, varType); } EXPRESSION_TYPE BNFClause::getLocalVariable(const std::string& sVarName) const { EXPRESSION_TYPE result = GrfBlock::getLocalVariable(sVarName); if (result == UNKNOWN_EXPRTYPE) { int iIndex = 0; for (std::vector::const_iterator i = _parameters.begin(); i != _parameters.end(); i++) { if ((*i) == sVarName) { result = getParameterType(iIndex); break; } ++iIndex; } } return result; } EXPRESSION_TYPE BNFClause::getVariable(const std::string& sVarName) const { EXPRESSION_TYPE result = getLocalVariable(sVarName); if (result == UNKNOWN_EXPRTYPE) { if ((sVarName == "this") || (sVarName == "project") || (sVarName == "null") || (DtaProject::getInstance().getGlobalVariableType(sVarName) != UNKNOWN_EXPRTYPE)) return NODE_EXPRTYPE; } return result; } SEQUENCE_INTERRUPTION_LIST BNFClause::execute(DtaScriptVariable& visibility) { throw UtlException("internal error: call 'BNFClause::executeClause(..., 0)' instead of 'BNFClause::execute(...)'"); } SEQUENCE_INTERRUPTION_LIST BNFClause::executeClause(DtaScriptVariable& visibility, int iSuperCallDepth) { SEQUENCE_INTERRUPTION_LIST result; BNFClauseMatchingAreaValidator matchingAreaValidator(this, _pBNFScript); if (iSuperCallDepth == 0) { register BNFClause* pLastOverloadClause = this; while (pLastOverloadClause->_pOverloadClause != NULL) pLastOverloadClause = pLastOverloadClause->_pOverloadClause; result = pLastOverloadClause->GrfBlock::execute(visibility); } else { result = executeInternalSuperClause(visibility, iSuperCallDepth); if (result == CONTINUE_INTERRUPTION) result = NO_INTERRUPTION; if (iSuperCallDepth > 0) throw UtlException("'#super' has failed: no overloaded non-terminal found for '" + getSignature() + "'"); } if (result != BREAK_INTERRUPTION) { matchingAreaValidator.validate(); } return result; } SEQUENCE_INTERRUPTION_LIST BNFClause::executeInternalSuperClause(DtaScriptVariable& visibility, int &iSuperCallDepth) { SEQUENCE_INTERRUPTION_LIST result; if (_pOverloadClause != NULL) { result = _pOverloadClause->executeInternalSuperClause(visibility, iSuperCallDepth); iSuperCallDepth--; if (iSuperCallDepth == 0) result = GrfBlock::execute(visibility); } else { result = NO_INTERRUPTION; } return result; } std::string BNFClause::getSignature() const { std::string sText; BNFClause* pOverloadClause = _pOverloadClause; while (pOverloadClause != NULL) { sText += "super::"; pOverloadClause = pOverloadClause->_pOverloadClause; } sText += getName(); if (!_sTemplateKey.empty()) { if (_bGenericKey) sText += "<" + _sTemplateKey + ">"; else sText += "<\"" + _sTemplateKey + "\">"; } if (!_parameters.empty()) { sText += "("; int iIndex = 0; for (std::vector::const_iterator i = _parameters.begin(); i != _parameters.end(); i++, iIndex++) { if (i != _parameters.begin()) sText += ", "; sText += (*i); EXPRESSION_TYPE exprType = getParameterType(iIndex); switch(exprType & 0x00FF) { case VALUE_EXPRTYPE: sText += " : value";break; case REFERENCE_EXPRTYPE: sText += " : reference";break; case ITERATOR_EXPRTYPE: sText += " : iterator";break; case NODE_EXPRTYPE: sText += " : node";break; default: throw UtlException("internal error in BNFClause::getSignature(): unhandled parameter type"); } DtaClass* pTypeSpecifier = DtaClass::getClass(exprType); if (pTypeSpecifier != NULL) { sText += "<" + pTypeSpecifier->getName() + ">"; } } sText += ")"; } switch(getReturnType()) { case 0/*NO_RETURN_TYPE*/: break; case 1/*LIST_RETURN_TYPE*/: sText += " : list";break; case 2/*NODE_RETURN_TYPE*/: sText += " : node";break; case 3/*VALUE_RETURN_TYPE*/: sText += " : value";break; default: throw UtlException("internal error in BNFClause::toString(): unhandled enum"); } return sText; } std::string BNFClause::toString() const { std::string sText = getSignature(); sText += " ::= "; if (getNbCommands() == 1) { sText += getCommands()[0]->toString(); } else { std::string sPrefix(sText.size(), ' '); for (std::vector::const_iterator i = getCommands().begin(); i != getCommands().end(); i++) { if (i != getCommands().begin()) { sText += "\n"; sText += sPrefix + "| "; } else { sText += " "; } sText += "["; (*i)->toString(); sText += "]"; } } return sText + ";"; } void BNFClause::compileCppFunction(CppCompilerEnvironment& theCompilerEnvironment) const { theCompilerEnvironment.setBNFStepperCursor(0); const BNFClause* pParentClause = theCompilerEnvironment.getCurrentClause(); int iPointerToDeclarations = theCompilerEnvironment.getPointerToDeclarations(); theCompilerEnvironment.newClause(this); // create the name of the clause std::string sClauseName = getName(); if (isATemplateInstantiation()) { if (_bGenericKey) sClauseName = "_compilerTemplateClause_" + sClauseName + "_compilerGeneric"; else sClauseName = "_compilerTemplateClause_" + sClauseName + "_compilerInstantiation_" + theCompilerEnvironment.convertTemplateKey(_sTemplateKey); } else if (sClauseName[0] == '#') sClauseName = "_compilerDirectiveClause_" + sClauseName.substr(1); else sClauseName = "_compilerClause_" + sClauseName; std::vector::const_iterator i; int iIndex = 0; if (isATemplateInstantiation() && _sTemplateKey.empty()) { // prototype of the dispatcher for template clauses, in the C++ header theCompilerEnvironment.getHeader() << theCompilerEnvironment.getIndentation() << "\t\tstatic bool " << sClauseName << "(const std::string& _compilerTemplateClause_dispatching, "; for (i = _parameters.begin(); i != _parameters.end(); i++, iIndex++) { switch(getParameterType(iIndex) & 0x00FF) { case VALUE_EXPRTYPE: theCompilerEnvironment.getHeader() << "CodeWorker::CppParsingTree_value ";break; case ITERATOR_EXPRTYPE: case REFERENCE_EXPRTYPE: theCompilerEnvironment.getHeader() << "const CodeWorker::CppParsingTree_var& ";break; case NODE_EXPRTYPE: theCompilerEnvironment.getHeader() << "const CodeWorker::CppParsingTree_var& ";break; default: throw UtlException("internal error in BNFClause::compileCppFunction(): unhandled parameter type"); } theCompilerEnvironment.getHeader() << (*i) << ", "; } theCompilerEnvironment.getHeader() << "CodeWorker::CGBNFRuntimeEnvironment& theEnvironment);"; theCompilerEnvironment.getHeader().endl(); iIndex = 0; theCompilerEnvironment.getHeader() << theCompilerEnvironment.getIndentation() << "\t\tstatic bool " << sClauseName << "(const std::string& _compilerTemplateClause_dispatching, const CodeWorker::CppParsingTree_var& _compilerClause_returnValue, "; for (i = _parameters.begin(); i != _parameters.end(); i++, iIndex++) { EXPRESSION_TYPE exprType = getParameterType(iIndex); if ((exprType & ~0x00FF) == 0) { switch(exprType) { case VALUE_EXPRTYPE: theCompilerEnvironment.getHeader() << "CodeWorker::CppParsingTree_value ";break; case ITERATOR_EXPRTYPE: case REFERENCE_EXPRTYPE: theCompilerEnvironment.getHeader() << "const CodeWorker::CppParsingTree_var& ";break; case NODE_EXPRTYPE: theCompilerEnvironment.getHeader() << "const CodeWorker::CppParsingTree_var& ";break; default: throw UtlException("internal error in BNFClause::compileCppFunction(): unhandled parameter type"); } } else { DtaClass* pTypeSpecifier = DtaClass::getClass(exprType); theCompilerEnvironment.getHeader() << pTypeSpecifier->getCppTypeSpecifier() << " "; } theCompilerEnvironment.getHeader() << (*i) << ", "; } theCompilerEnvironment.getHeader() << "CodeWorker::CGBNFRuntimeEnvironment& theEnvironment);"; theCompilerEnvironment.getHeader().endl(); } // prototype in the C++ header, without return value iIndex = 0; theCompilerEnvironment.getHeader() << theCompilerEnvironment.getIndentation() << "\t\tstatic bool " << sClauseName << "("; for (i = _parameters.begin(); i != _parameters.end(); i++, iIndex++) { EXPRESSION_TYPE exprType = getParameterType(iIndex); if ((exprType & ~0x00FF) == 0) { switch(exprType) { case VALUE_EXPRTYPE: theCompilerEnvironment.getHeader() << "CodeWorker::CppParsingTree_value ";break; case ITERATOR_EXPRTYPE: case REFERENCE_EXPRTYPE: theCompilerEnvironment.getHeader() << "const CodeWorker::CppParsingTree_var& ";break; case NODE_EXPRTYPE: theCompilerEnvironment.getHeader() << "const CodeWorker::CppParsingTree_var& ";break; default: throw UtlException("internal error in BNFClause::compileCppFunction(): unhandled parameter type"); } } else { DtaClass* pTypeSpecifier = DtaClass::getClass(exprType); theCompilerEnvironment.getHeader() << pTypeSpecifier->getCppTypeSpecifier() << " "; } theCompilerEnvironment.getHeader() << (*i) << ", "; } theCompilerEnvironment.getHeader() << "CodeWorker::CGBNFRuntimeEnvironment& theEnvironment);"; theCompilerEnvironment.getHeader().endl(); // prototype in the C++ header with return value iIndex = 0; theCompilerEnvironment.getHeader() << theCompilerEnvironment.getIndentation() << "\t\tstatic bool " << sClauseName << "(const CodeWorker::CppParsingTree_var& _compilerClause_returnValue, "; for (i = _parameters.begin(); i != _parameters.end(); i++, iIndex++) { EXPRESSION_TYPE exprType = getParameterType(iIndex); if ((exprType & ~0x00FF) == 0) { switch(exprType) { case VALUE_EXPRTYPE: theCompilerEnvironment.getHeader() << "CodeWorker::CppParsingTree_value ";break; case ITERATOR_EXPRTYPE: case REFERENCE_EXPRTYPE: theCompilerEnvironment.getHeader() << "const CodeWorker::CppParsingTree_var& ";break; case NODE_EXPRTYPE: theCompilerEnvironment.getHeader() << "const CodeWorker::CppParsingTree_var& ";break; default: throw UtlException("internal error in BNFClause::compileCppFunction(): unhandled parameter type"); } } else { DtaClass* pTypeSpecifier = DtaClass::getClass(exprType); theCompilerEnvironment.getHeader() << pTypeSpecifier->getCppTypeSpecifier() << " "; } theCompilerEnvironment.getHeader() << (*i) << ", "; } theCompilerEnvironment.getHeader() << "CodeWorker::CGBNFRuntimeEnvironment& theEnvironment);"; theCompilerEnvironment.getHeader().endl(); // implementations of the clause in the C++ body CW_BODY_INDENT << "//**"; CW_BODY_ENDL; CW_BODY_INDENT << "// " << toString(); CW_BODY_ENDL; CW_BODY_INDENT << "//**"; CW_BODY_ENDL; if (isATemplateInstantiation() && _sTemplateKey.empty()) { // implementation of the dispatcher for template clauses, in the C++ body CW_BODY_INDENT << "bool " << DtaScript::convertFilenameAsIdentifier(theCompilerEnvironment.getRadical()) << "::" << sClauseName << "(const std::string& _compilerTemplateClause_dispatching, "; iIndex = 0; for (i = _parameters.begin(); i != _parameters.end(); i++, iIndex++) { EXPRESSION_TYPE exprType = getParameterType(iIndex); if ((exprType & ~0x00FF) == 0) { switch(exprType) { case VALUE_EXPRTYPE: CW_BODY_STREAM << "CppParsingTree_value ";break; case ITERATOR_EXPRTYPE: case REFERENCE_EXPRTYPE: CW_BODY_STREAM << "const CppParsingTree_var& ";break; case NODE_EXPRTYPE: CW_BODY_STREAM << "const CppParsingTree_var& ";break; default: throw UtlException("internal error in BNFClause::compileCppFunction(): unhandled parameter type"); } } else { DtaClass* pTypeSpecifier = DtaClass::getClass(exprType); CW_BODY_STREAM << pTypeSpecifier->getCppTypeSpecifier() << " "; } CW_BODY_STREAM << (*i) << ", "; } CW_BODY_STREAM << "CGBNFRuntimeEnvironment& theEnvironment) {"; CW_BODY_ENDL; CW_BODY_STREAM << " CppParsingTree_value _compilerClauseThis;"; CW_BODY_ENDL; CW_BODY_STREAM << " return " << sClauseName << "(_compilerTemplateClause_dispatching, _compilerClauseThis, "; for (i = _parameters.begin(); i != _parameters.end(); i++, iIndex++) { CW_BODY_STREAM << (*i) << ", "; } CW_BODY_STREAM << "theEnvironment);"; CW_BODY_ENDL; CW_BODY_STREAM << "}"; CW_BODY_ENDL; CW_BODY_ENDL; CW_BODY_INDENT << "bool " << DtaScript::convertFilenameAsIdentifier(theCompilerEnvironment.getRadical()) << "::" << sClauseName << "(const std::string& _compilerTemplateClause_dispatching, const CppParsingTree_var& _compilerClause_returnValue, "; iIndex = 0; for (i = _parameters.begin(); i != _parameters.end(); i++, iIndex++) { EXPRESSION_TYPE exprType = getParameterType(iIndex); if ((exprType & ~0x00FF) == 0) { switch(exprType) { case VALUE_EXPRTYPE: CW_BODY_STREAM << "CppParsingTree_value ";break; case ITERATOR_EXPRTYPE: case REFERENCE_EXPRTYPE: CW_BODY_STREAM << "const CppParsingTree_var& ";break; case NODE_EXPRTYPE: CW_BODY_STREAM << "const CppParsingTree_var& ";break; default: throw UtlException("internal error in BNFClause::compileCppFunction(): unhandled parameter type"); } } else { DtaClass* pTypeSpecifier = DtaClass::getClass(exprType); CW_BODY_STREAM << pTypeSpecifier->getCppTypeSpecifier() << " "; } CW_BODY_STREAM << (*i) << ", "; } CW_BODY_STREAM << "CGBNFRuntimeEnvironment& theEnvironment) {"; CW_BODY_ENDL; // core of the dispatcher if (_mapOfTemplateInstantiations.size() < 8) { // just a battery of if/else on the key for determining the correct function call for (std::map::const_iterator j = _mapOfTemplateInstantiations.begin(); j != _mapOfTemplateInstantiations.end(); ++j) { CW_BODY_STREAM << "\t"; if (j != _mapOfTemplateInstantiations.begin()) CW_BODY_STREAM << "else "; CW_BODY_STREAM << "if (_compilerTemplateClause_dispatching == "; CW_BODY_STREAM.writeString(j->first); CW_BODY_STREAM << ") return " << sClauseName << theCompilerEnvironment.convertTemplateKey(j->first) << "(_compilerClause_returnValue, "; for (i = _parameters.begin(); i != _parameters.end(); i++, iIndex++) { CW_BODY_STREAM << (*i) << ", "; } CW_BODY_STREAM << "theEnvironment);"; CW_BODY_ENDL; } } else { // a switch/case depending on a hash code issued of the key std::map > keysByCode; for (std::map::const_iterator j = _mapOfTemplateInstantiations.begin(); j != _mapOfTemplateInstantiations.end(); ++j) { long iHashCode = 0; char* u = (char*) (j->first.c_str()); while (*u != '\0') iHashCode = iHashCode * 31 + (((long) *u++) % 31); keysByCode[iHashCode].push_back(j->first); } CW_BODY_STREAM << "\tlong _compilerInternal_hashCode = 0;"; CW_BODY_ENDL; CW_BODY_STREAM << "\tchar* _compilerInternal_u = (char*) (_compilerTemplateClause_dispatching.c_str());"; CW_BODY_ENDL; CW_BODY_STREAM << "\twhile (*_compilerInternal_u != '\\0') _compilerInternal_hashCode = _compilerInternal_hashCode * 31 + (((long) *_compilerInternal_u++) % 31);"; CW_BODY_ENDL; CW_BODY_STREAM << "\tswitch(_compilerInternal_hashCode) {"; CW_BODY_ENDL; for (std::map >::const_iterator k = keysByCode.begin(); k != keysByCode.end(); ++k) { CW_BODY_STREAM << "\t\tcase " << k->first << ": "; CW_BODY_ENDL; for (std::list::const_iterator l = k->second.begin(); l != k->second.end(); ++l) { CW_BODY_STREAM << "\t\t\tif (_compilerTemplateClause_dispatching == "; CW_BODY_STREAM.writeString(*l); CW_BODY_STREAM << ") return " << sClauseName << theCompilerEnvironment.convertTemplateKey(*l) << "(_compilerClause_returnValue, "; for (i = _parameters.begin(); i != _parameters.end(); i++, iIndex++) { CW_BODY_STREAM << (*i) << ", "; } CW_BODY_STREAM << "theEnvironment);"; CW_BODY_ENDL; } CW_BODY_STREAM << "\t\t\tbreak;"; CW_BODY_ENDL; } CW_BODY_STREAM << "\t}"; CW_BODY_ENDL; } if (_pGenericTemplateClause != NULL) { CW_BODY_STREAM << "\treturn _compilerTemplateClause_" + getName() + "_compilerGeneric(_compilerClause_returnValue, "; for (i = _parameters.begin(); i != _parameters.end(); i++, iIndex++) { CW_BODY_STREAM << (*i) << ", "; } CW_BODY_STREAM << "theEnvironment);";CW_BODY_ENDL; } else { CW_BODY_STREAM << "\tif (!_compilerTemplateClause_dispatching.empty()) throw UtlException(\"template clause '" << getName() << "<\\\"\" + _compilerTemplateClause_dispatching + \"\\\">' hasn't been implemented\");";CW_BODY_ENDL; if (getNbCommands() == 0) { CW_BODY_STREAM << "\treturn true;";CW_BODY_ENDL; } else { CW_BODY_STREAM << "\treturn " << sClauseName << "(_compilerClause_returnValue, "; for (i = _parameters.begin(); i != _parameters.end(); i++, iIndex++) { CW_BODY_STREAM << (*i) << ", "; } CW_BODY_STREAM << "theEnvironment);"; CW_BODY_ENDL; } } CW_BODY_STREAM << "}"; CW_BODY_ENDL; CW_BODY_ENDL; } // implementation of the clause in the C++ body, with a return value CW_BODY_INDENT << "bool " << DtaScript::convertFilenameAsIdentifier(theCompilerEnvironment.getRadical()) << "::" << sClauseName << "(const CppParsingTree_var& _compilerClause_returnValue, "; iIndex = 0; for (i = _parameters.begin(); i != _parameters.end(); i++, iIndex++) { EXPRESSION_TYPE exprType = getParameterType(iIndex); if ((exprType & ~0x00FF) == 0) { switch(exprType) { case VALUE_EXPRTYPE: CW_BODY_STREAM << "CppParsingTree_value ";break; case ITERATOR_EXPRTYPE: case REFERENCE_EXPRTYPE: CW_BODY_STREAM << "const CppParsingTree_var& ";break; case NODE_EXPRTYPE: CW_BODY_STREAM << "const CppParsingTree_var& ";break; default: throw UtlException("internal error in BNFClause::compileCppFunction(): unhandled parameter type"); } } else { DtaClass* pTypeSpecifier = DtaClass::getClass(exprType); CW_BODY_STREAM << pTypeSpecifier->getCppTypeSpecifier() << " "; } CW_BODY_STREAM << (*i) << ", "; } CW_BODY_STREAM << "CGBNFRuntimeEnvironment& theEnvironment) {";CW_BODY_ENDL; theCompilerEnvironment.setPointerToDeclarations(CW_BODY_STREAM.getOutputLocation()); theCompilerEnvironment.incrementIndentation(); theCompilerEnvironment.pushVariableScope(); if (_pBNFScript->hasCoverageRecording()) { // coverage recording required CW_BODY_INDENT << "CGBNFRuntimeClauseMatchingAreaValidator _compilerClauseMatching(\"" << CGRuntime::composeCLikeString(getSignature()) << "\", &theEnvironment);";CW_BODY_ENDL; } CW_BODY_INDENT << "CGBNFClauseScope _compilerClauseScope;";CW_BODY_ENDL; CW_BODY_STREAM.newFloatingLocation("CLAUSE SCOPE DECLARATION"); CW_BODY_INDENT << "bool _compilerClauseSuccess = true;";CW_BODY_ENDL; for (i = _parameters.begin(); i != _parameters.end(); i++, iIndex++) { theCompilerEnvironment.addVariable((*i)); } if (getReturnType() != 0/*NO_RETURN_TYPE*/) { // the clause admits a return value theCompilerEnvironment.setClauseReturnValue(getName()); } theCompilerEnvironment.bracketsToNextBlock(false); GrfBlock::compileCpp(theCompilerEnvironment); if (theCompilerEnvironment.hasEvaluatedExpressionInScope()) { for (i = _parameters.begin(); i != _parameters.end(); i++, iIndex++) { std::string sDynamicVariable = theCompilerEnvironment.getIndentation() + "_compilerClauseScope.insertNode(\"" + *i + "\").setReference(" + *i + ");" + ScpStream::ENDL; ScpStream* pOwner = 0; CW_BODY_STREAM.insertText(sDynamicVariable, CW_BODY_STREAM.getFloatingLocation("CLAUSE SCOPE DECLARATION", pOwner)); } } if (_pBNFScript->hasCoverageRecording()) { // coverage recording required CW_BODY_INDENT << "if (_compilerClauseSuccess) _compilerClauseMatching.validate();";CW_BODY_ENDL; } CW_BODY_INDENT << "return _compilerClauseSuccess;";CW_BODY_ENDL; theCompilerEnvironment.popVariableScope(); theCompilerEnvironment.decrementIndentation(); CW_BODY_INDENT << "}"; CW_BODY_ENDL; CW_BODY_ENDL; // implementation of the clause in the C++ body, without a return value CW_BODY_INDENT << "bool " << DtaScript::convertFilenameAsIdentifier(theCompilerEnvironment.getRadical()) << "::" << sClauseName << "("; iIndex = 0; for (i = _parameters.begin(); i != _parameters.end(); i++, iIndex++) { EXPRESSION_TYPE exprType = getParameterType(iIndex); if ((exprType & ~0x00FF) == 0) { switch(exprType) { case VALUE_EXPRTYPE: CW_BODY_STREAM << "CppParsingTree_value ";break; case ITERATOR_EXPRTYPE: case REFERENCE_EXPRTYPE: CW_BODY_STREAM << "const CppParsingTree_var& ";break; case NODE_EXPRTYPE: CW_BODY_STREAM << "const CppParsingTree_var& ";break; default: throw UtlException("internal error in BNFClause::compileCppFunction(): unhandled parameter type"); } } else { DtaClass* pTypeSpecifier = DtaClass::getClass(exprType); CW_BODY_STREAM << pTypeSpecifier->getCppTypeSpecifier() << " "; } CW_BODY_STREAM << (*i) << ", "; } CW_BODY_STREAM << "CGBNFRuntimeEnvironment& theEnvironment) {"; CW_BODY_ENDL; CW_BODY_STREAM << " CppParsingTree_value _compilerClauseThis;"; CW_BODY_ENDL; CW_BODY_STREAM << " return " << sClauseName << "(_compilerClauseThis, "; for (i = _parameters.begin(); i != _parameters.end(); i++, iIndex++) { CW_BODY_STREAM << (*i) << ", "; } CW_BODY_STREAM << "theEnvironment);"; CW_BODY_ENDL; CW_BODY_STREAM << "}"; CW_BODY_ENDL; CW_BODY_ENDL; theCompilerEnvironment.setCurrentClause(pParentClause); theCompilerEnvironment.setPointerToDeclarations(iPointerToDeclarations); } }