/* "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 #include "UtlException.h" #include "ScpStream.h" #include "CppCompilerEnvironment.h" #include "CGRuntime.h" #include "ExprScriptVariable.h" #include "DtaScriptVariable.h" #include "DtaProject.h" #include "DtaClass.h" #include "BNFDisjunction.h" #include "BNFConjunction.h" #include "BNFString.h" #include "BNFEndOfFile.h" #include "BNFNextStep.h" #include "BNFScanWindow.h" #include "BNFAndOrJunction.h" #include "BNFBreak.h" #include "BNFComplementary.h" #include "BNFFindToken.h" #include "BNFNot.h" #include "BNFCharLitteral.h" #include "BNFCharBoundaries.h" #include "BNFPushItem.h" #include "BNFInsert.h" #include "BNFReadChar.h" #include "BNFReadByte.h" #include "BNFReadAdaString.h" #include "BNFReadCString.h" #include "BNFReadCChar.h" #include "BNFReadIdentifier.h" #include "BNFReadCompleteIdentifier.h" #include "BNFReadInteger.h" #include "BNFReadNumeric.h" #include "BNFReadPythonString.h" #include "BNFReadText.h" #include "BNFReadBytes.h" #include "BNFReadChars.h" #include "BNFCheck.h" #include "BNFClauseCall.h" #include "BNFMultiplicity.h" #include "BNFClause.h" #include "BNFRatchet.h" #include "BNFTryCatch.h" #include "BNFStepintoHook.h" #include "BNFStepoutHook.h" //##markup##"includes" //##begin##"includes" #include "GrfAttachInputToSocket.h" #include "GrfDetachInputFromSocket.h" #include "GrfGoBack.h" #include "GrfSetInputLocation.h" //##end##"includes" #include "DtaASTNavigator.h" #include "ASTCommand.h" #include "GrfParsedFile.h" #include "GrfParsedString.h" #include "GrfGeneratedFile.h" #include "GrfGeneratedString.h" #include "GrfAppendedFile.h" #include "GrfDebugExecution.h" #include "DtaBNFScript.h" #include "DtaTranslateScript.h" #include "BNFIgnore.h" #include "BNFSkipIgnore.h" #include "BNFMoveAhead.h" #include "BNFReadUptoIgnore.h" namespace CodeWorker { class BNFDisengageIgnore { private: DtaBNFScript* _pBNFScript; public: BNFDisengageIgnore(DtaBNFScript* pBNFScript) : _pBNFScript(pBNFScript) { pBNFScript->setIgnoreMode(NOT_IGNORE); } ~BNFDisengageIgnore() { _pBNFScript->setIgnoreMode(IGNORE_CLAUSE); } }; class BNFTransformRules { private: ExprScriptExpression* _pFilter; DtaTranslateScript* _pPrototypeScript; DtaTranslateScript* _pProductionRuleScript; public: inline BNFTransformRules() : _pFilter(NULL), _pPrototypeScript(NULL), _pProductionRuleScript(NULL) {} ~BNFTransformRules() { delete _pFilter; delete _pPrototypeScript; delete _pProductionRuleScript; } inline ExprScriptExpression* getFilter() const { return _pFilter; } inline void setFilter(ExprScriptExpression* pFilter) { _pFilter = pFilter; } inline DtaTranslateScript* getPrototypeScript() const { return _pPrototypeScript; } inline void setPrototypeScript(DtaTranslateScript* pPrototypeScript) { _pPrototypeScript = pPrototypeScript; } inline DtaTranslateScript* getProductionRuleScript() const { return _pProductionRuleScript; } inline void setProductionRuleScript(DtaTranslateScript* pProductionRuleScript) { _pProductionRuleScript = pProductionRuleScript; } virtual bool applyRuleTransformer(ScpStream& script, GrfBlock& block, int iStatementBeginning, int iProductionRuleBeginning, const std::string& sClauseName, const std::string& sPrototype, const std::string& sProductionRule) { DtaScriptVariable theContext; theContext.setValueAtVariable("x", sClauseName.c_str()); std::string sResult = _pFilter->getValue(theContext); if (sResult.empty()) return false; if (_pPrototypeScript != NULL) { std::string sNewPrototype; _pPrototypeScript->translateString(sPrototype, sNewPrototype, DtaProject::getInstance()); if (sNewPrototype != sPrototype) script.insertText(sNewPrototype, iStatementBeginning, sPrototype.size()); } if (_pProductionRuleScript != NULL) { std::string sNewProductionRule; _pProductionRuleScript->translateString(sProductionRule, sNewProductionRule, DtaProject::getInstance()); if (sNewProductionRule != sProductionRule) { script.insertText(sNewProductionRule, iProductionRuleBeginning, sProductionRule.size()); } } return true; } }; struct TemporaryMatchingStorage { bool bBegin; DtaScriptVariable* pClauseNode; TemporaryMatchingStorage(bool b, DtaScriptVariable* p) : bBegin(b), pClauseNode(p) {} }; DtaBNFScript::DtaBNFScript() : DtaPatternScript(true), _bBNFMode(true), _pIgnoreClause(NULL), _bNoCase(false), _bImplicitCopy(false), _bParsedFile(false), _pStream(NULL), _pImplicitCopyFunction(NULL), _eIgnoreMode(NOT_IGNORE), _bTrace(false), _pStepintoHook(NULL), _pStepoutHook(NULL), _iRatchetPosition(-1), _pMatchingAreasContainer(NULL), _pASTContainer(NULL), _pParentClauseMatching(NULL) { } DtaBNFScript::DtaBNFScript(GrfBlock* pParentBlock) : DtaPatternScript(pParentBlock, true), _bBNFMode(true), _pIgnoreClause(NULL), _bNoCase(false), _bImplicitCopy(false), _bParsedFile(false), _pStream(NULL), _pImplicitCopyFunction(NULL), _eIgnoreMode(NOT_IGNORE), _bTrace(false), _pStepintoHook(NULL), _pStepoutHook(NULL), _iRatchetPosition(-1), _pMatchingAreasContainer(NULL), _pASTContainer(NULL), _pParentClauseMatching(NULL) { } DtaBNFScript::DtaBNFScript(EXECUTE_FUNCTION* executeFunction) : DtaPatternScript(executeFunction, true), _bBNFMode(true), _pIgnoreClause(NULL), _bNoCase(false), _bImplicitCopy(false), _bParsedFile(false), _pStream(NULL), _pImplicitCopyFunction(NULL), _eIgnoreMode(NOT_IGNORE), _bTrace(false), _pStepintoHook(NULL), _pStepoutHook(NULL), _iRatchetPosition(-1), _pMatchingAreasContainer(NULL), _pASTContainer(NULL), _pParentClauseMatching(NULL) { } DtaBNFScript::~DtaBNFScript() { delete _pImplicitCopyFunction; for (std::map >::const_iterator i = _listOfClauses.begin(); i != _listOfClauses.end(); i++) { // for (std::list::const_iterator j = i->second.begin(); j != i->second.end(); j++) delete *j; } for (std::list::const_iterator j = _listOfTransformRules.begin(); j != _listOfTransformRules.end(); ++j) { delete *j; } delete _pStepintoHook; delete _pStepoutHook; delete _pMatchingAreasContainer; delete _pASTContainer; delete _pParentClauseMatching; } DtaScriptFactory::SCRIPT_TYPE DtaBNFScript::getType() const { return DtaScriptFactory::BNF_SCRIPT; } bool DtaBNFScript::isAParseScript() const { return true; } bool DtaBNFScript::isAGenerateScript() const { return false; } void DtaBNFScript::traceEngine() const { if (getFilenamePtr() == NULL) CGRuntime::traceLine("Extended-BNF script (no filename):"); else CGRuntime::traceLine("Extended-BNF script \"" + std::string(getFilenamePtr()) + "\":"); traceInternalEngine(); } void DtaBNFScript::traceInternalEngine() const { char tcMessage[80]; sprintf(tcMessage, "\tNumber of production rules = %d", _listOfClauses.size()); CGRuntime::traceLine(tcMessage); if (_eIgnoreMode == NOT_IGNORE) CGRuntime::traceLine("\tignore insignificant chars = OFF"); else if (_pIgnoreClause == NULL) CGRuntime::traceLine("\tignore insignificant chars = " + IGNORE_MODEtoString(_eIgnoreMode)); else CGRuntime::traceLine("\tignore insignificant chars = clause '#ignore'"); if (_bNoCase) CGRuntime::traceLine("\tignore case = ON"); if (!_mapOfIgnoreClauses.empty()) { CGRuntime::traceText("\tignore clauses: "); for (std::map::const_iterator i = _mapOfIgnoreClauses.begin(); i != _mapOfIgnoreClauses.end(); ++i) { if (i != _mapOfIgnoreClauses.begin()) CGRuntime::traceText(", "); CGRuntime::traceText(i->first); } CGRuntime::traceLine(""); } if (_bTrace) CGRuntime::traceLine("\ttrace = ON"); if (_bImplicitCopy) CGRuntime::traceLine("\timplicitCopy = ON"); if (_pImplicitCopyFunction != NULL) { CGRuntime::traceLine("\timplicitCopy function = " + _pImplicitCopyFunction->toString()); } DtaScript::traceInternalEngine(); } DtaBNFScript& DtaBNFScript::getAlienParser() const { DtaBNFScript* pScript = DtaProject::getInstance().getBNFAlienParser(); if (pScript == NULL) throw UtlException("compiling a BNF script in " + _sTargetLanguage + " requires \"($CODEWORKER_HOME)/" + _sTargetLanguage + "/default-scripts/" + _sTargetLanguage + "BNFScript.cwp\""); return *pScript; } int DtaBNFScript::skipEmptyChars(DtaScriptVariable& visibility) { int iImplicitCopyPosition; int iLocation; if (_bImplicitCopy) { iImplicitCopyPosition = CGRuntime::getOutputLocation(); iLocation = CGRuntime::getInputLocation(); } else { iImplicitCopyPosition = -1; } if ((_eIgnoreMode != NOT_IGNORE) && (_eIgnoreMode != UNDEFINED_IGNORE)) { bool bCopyImplicitly = _bImplicitCopy; switch(_eIgnoreMode) { case IGNORE_CPP: case IGNORE_JAVA: CGRuntime::_pInputStream->skipEmpty(); break; case IGNORE_HTML: CGRuntime::_pInputStream->skipEmptyHTML(); break; case IGNORE_BLANKS: CGRuntime::_pInputStream->skipBlanks(); break; case IGNORE_ADA: CGRuntime::_pInputStream->skipEmptyAda(); break; case IGNORE_LATEX: CGRuntime::_pInputStream->skipEmptyLaTeX(); break; case IGNORE_CPP_EXCEPT_DOXYGEN: CGRuntime::_pInputStream->skipEmptyCppExceptDoxygen(); break; case IGNORE_CLAUSE: bCopyImplicitly = false; if (_pIgnoreClause != NULL) { BNFDisengageIgnore disengage(this); _pIgnoreClause->executeClause(visibility, 0); } break; default: throw UtlException("internal error in DtaBNFScript::skipEmptyChars(): unrecognized ignore mode encountered"); } if (bCopyImplicitly) { int iLastLocation = CGRuntime::getInputLocation(); if (iLastLocation > iLocation) { std::string sText = CGRuntime::getLastReadChars(iLastLocation - iLocation); writeBinaryData(sText.c_str(), sText.size()); } } } return iImplicitCopyPosition; } void DtaBNFScript::writeBinaryData(const char* tcText, int iLength) { if (_pImplicitCopyFunction != NULL) { ExprScriptConstant* pConstant = dynamic_cast(_pImplicitCopyFunction->getParameters()[0]); pConstant->setConstant(tcText, iLength); std::string sNewText = _pImplicitCopyFunction->getValue(CGRuntime::getThisInternalNode()); CGRuntime::_pOutputStream->writeBinaryData(sNewText.c_str(), sNewText.size()); } else { CGRuntime::_pOutputStream->writeBinaryData(tcText, iLength); } } void DtaBNFScript::storeClauseMatching(DtaScriptVariable& ruleNames, std::map > >& mapOfAreas, BNFClauseMatchingArea* pClauseMatching) { if (pClauseMatching == NULL) return; int iBegin = pClauseMatching->beginPosition; int iEnd = pClauseMatching->endPosition; if (iBegin != iEnd) { DtaScriptVariable* pClauseNode = ruleNames.getArrayElement(pClauseMatching->clause->getSignature()); mapOfAreas[iBegin][iEnd].push_back(new TemporaryMatchingStorage(true, pClauseNode)); for (std::list::iterator i = pClauseMatching->childs.begin(); i != pClauseMatching->childs.end(); ++i) { storeClauseMatching(ruleNames, mapOfAreas, *i); } mapOfAreas[iEnd][iBegin].push_back(new TemporaryMatchingStorage(false, pClauseNode)); } } void DtaBNFScript::storeMatchingAreas(DtaScriptVariable& thisContext, DtaScriptVariable* pStorage) { // storage of matching areas if (pStorage == NULL) { if (_pMatchingAreasContainer == NULL) return; pStorage = thisContext.getVariable(*_pMatchingAreasContainer); } DtaScriptVariable* pAreas = pStorage->insertNode("areas"); DtaScriptVariable* pRules = pStorage->insertNode("rules"); for (std::map >::iterator i = _listOfClauses.begin(); i != _listOfClauses.end(); ++i) { for (std::list::iterator j = i->second.begin(); j != i->second.end(); ++j) { std::string sSignature = (*j)->getSignature(); DtaScriptVariable* pClauseNode = pRules->addElement(sSignature); pClauseNode->setValue(sSignature.c_str()); } } std::map > > mapOfAreas; storeClauseMatching(*pRules, mapOfAreas, _pParentClauseMatching); { for (std::map > >::iterator i = mapOfAreas.begin(); i != mapOfAreas.end(); ++i) { DtaScriptVariable* pPosition = pAreas->addElement(i->first); for (std::map >::reverse_iterator j = i->second.rbegin(); j != i->second.rend(); ++j) { { for (std::list::iterator k = j->second.begin(); k != j->second.end(); ++k) { if ((*k)->bBegin) { pPosition->insertNode("begin")->addElement(j->first)->pushItem("")->setValue((*k)->pClauseNode); } } } { for (std::list::iterator k = j->second.begin(); k != j->second.end(); ++k) { if (!(*k)->bBegin) { pPosition->insertNode("end")->addElement(j->first)->pushItem("")->setValue((*k)->pClauseNode); } } } { // delete the temporary storage for (std::list::iterator k = j->second.begin(); k != j->second.end(); ++k) { delete *k; } } } } } } void DtaBNFScript::storeAST(DtaScriptVariable& thisContext, ScpStream& inputStream) { DtaASTNavigator navigator; std::auto_ptr structure(navigator.detectASTStructure(*this)); DtaScriptVariable* pStorage = thisContext.getVariable(*_pASTContainer); structure->build(*pStorage); structure->populateAST(*pStorage, *_pParentClauseMatching, inputStream); } SEQUENCE_INTERRUPTION_LIST DtaBNFScript::generate(ScpStream& stream, DtaScriptVariable& thisContext) { CGRuntimeOutputStream noOutput(NULL); _bBNFMode = true; _sParsedFileOrContent = ""; _bParsedFile = false; _pStream = &stream; // TO DO PROPERLY return execute(thisContext); } SEQUENCE_INTERRUPTION_LIST DtaBNFScript::generate(const char* tcFile, DtaScriptVariable& thisContext) { CGRuntimeOutputStream noOutput(NULL); _bBNFMode = true; // absolute path of the parsed file: // avoid ambiguities std::string sAbsolutePath; if (ScpStream::existInputFileFromIncludePath(tcFile, sAbsolutePath)) { if (!ScpStream::existVirtualFile(tcFile)) { sAbsolutePath = CGRuntime::canonizePath(sAbsolutePath); } } else { // should have found! Do not touch the file name, for further error message sAbsolutePath = tcFile; } _sParsedFileOrContent = sAbsolutePath; _bParsedFile = true; // TO DO PROPERLY SEQUENCE_INTERRUPTION_LIST result = execute(thisContext); if (getFilenamePtr() != NULL) { DtaProject::getInstance().captureInputFile(sAbsolutePath.c_str(), getFilenamePtr()); } return result; } SEQUENCE_INTERRUPTION_LIST DtaBNFScript::generateString(std::string& sContent, DtaScriptVariable& thisContext) { CGRuntimeOutputStream noOutput(NULL); _bBNFMode = true; _sParsedFileOrContent = sContent; _bParsedFile = false; _pStream = NULL; // TO DO PROPERLY return execute(thisContext); } SEQUENCE_INTERRUPTION_LIST DtaBNFScript::execute(DtaScriptVariable& thisContext) { SEQUENCE_INTERRUPTION_LIST result; std::string sParsedFileOrContent = _sParsedFileOrContent; // because '_sParsedFileOrContent' is shared ScpStream* pStream; bool bStreamOwner = (_pStream == NULL); if (bStreamOwner) { if (_bParsedFile) { pStream = new ScpStream(sParsedFileOrContent, ScpStream::IN | ScpStream::PATH); if (pStream == NULL) throw UtlException("unable to open file \"" + sParsedFileOrContent + "\""); } else { pStream = new ScpStream; (*pStream) << sParsedFileOrContent; } } else { pStream = _pStream; } // note if 'final info' was requiring to store coverage, // while this BNF script hasn't required coverage recording bool bCreateMatchingAreasContainerForFinalInfo = false; if ((DtaProject::getInstance().getFinalInfoFlag() & DtaProject::FINAL_INFO_PARSE_COVERAGE_FOR_EVERYBODY) != 0) { if (_bParsedFile && !hasCoverageRecording()) { // create a global variable expression for coverage recording // when final info requires coverage on parsed files; // the variable expression points to an item whose key is the name // of the parsed file. if (DtaProject::getInstance().getGlobalVariable("_FINAL_INFO_PARSE_COVERAGE") == NULL) { DtaProject::getInstance().setGlobalVariable("_FINAL_INFO_PARSE_COVERAGE"); } _pMatchingAreasContainer = new ExprScriptVariable("_FINAL_INFO_PARSE_COVERAGE"); _pMatchingAreasContainer->setArrayKey(new ExprScriptConstant(sParsedFileOrContent.c_str())); bCreateMatchingAreasContainerForFinalInfo = true; } } if (hasCoverageRecording()) { // prepare for recording matching areas delete _pParentClauseMatching; _pParentClauseMatching = NULL; } ScpStream* pOldInputStream = CGRuntime::_pInputStream; CGRuntime::_pInputStream = pStream; try { result = DtaPatternScript::execute(thisContext); if (hasCoverageRecording()) { // storage of matching areas / AST in the container CGThisModifier thisModifier(&thisContext); if (_pMatchingAreasContainer != NULL) storeMatchingAreas(thisContext); if (_pASTContainer != NULL) storeAST(thisContext, *CGRuntime::_pInputStream); if (!bCreateMatchingAreasContainerForFinalInfo) { // the variable expression wasn't built for 'final info', but // the latter requires perhaps the coverage if ((DtaProject::getInstance().getFinalInfoFlag() & DtaProject::FINAL_INFO_PARSE_COVERAGE) != 0) { //yes, the coverage tree must be copied for 'final info' DtaScriptVariable* pGlobal = DtaProject::getInstance().getGlobalVariable("_FINAL_INFO_PARSE_COVERAGE"); if (pGlobal == NULL) { pGlobal = DtaProject::getInstance().setGlobalVariable("_FINAL_INFO_PARSE_COVERAGE"); } DtaScriptVariable* pStorage = pGlobal->addElement(sParsedFileOrContent); storeMatchingAreas(thisContext, pStorage); } } // temporary low-level structure used to build the // coverage tree; won't serve anymore delete _pParentClauseMatching; _pParentClauseMatching = NULL; } } catch(UtlException& exception) { int iLine = pStream->getLineCount(); int iCol = pStream->getColCount(); if (bStreamOwner) { pStream->close(); delete pStream; } CGRuntime::_pInputStream = pOldInputStream; std::string sException = exception.getMessage(); std::string sMessage; char tcNumber[64]; if (_bParsedFile) { sMessage = sParsedFileOrContent; sprintf(tcNumber, "(%d,%d):", iLine, iCol); } else if (!sParsedFileOrContent.empty()) { sMessage = CGRuntime::endl() + "----------------- content -----------------" + CGRuntime::endl() + sParsedFileOrContent + CGRuntime::endl() + "-------------------------------------------" + CGRuntime::endl(); sprintf(tcNumber, "line %d, col %d:", iLine, iCol); } sMessage += tcNumber + CGRuntime::endl() + sException; throw UtlException(exception.getTraceStack(), sMessage); } catch(std::exception&) { if (bStreamOwner) { pStream->close(); delete pStream; } CGRuntime::_pInputStream = pOldInputStream; throw; } catch(...) { int iLine = pStream->getLineCount(); int iCol = pStream->getColCount(); if (bStreamOwner) { pStream->close(); delete pStream; } CGRuntime::_pInputStream = pOldInputStream; std::string sMessage; char tcNumber[64]; if (_bParsedFile) { sMessage = sParsedFileOrContent; sprintf(tcNumber, "(%d,%d):", iLine, iCol); } else if (!sParsedFileOrContent.empty()) { sMessage = CGRuntime::endl() + "----------------- content -----------------" + CGRuntime::endl() + sParsedFileOrContent + CGRuntime::endl() + "-------------------------------------------" + CGRuntime::endl(); sprintf(tcNumber, "line %d, col %d:", iLine, iCol); } sMessage += tcNumber + CGRuntime::endl() + "Fatal error: ellipsis exception"; throw UtlException(sMessage); } if (bStreamOwner) { pStream->close(); delete pStream; } CGRuntime::_pInputStream = pOldInputStream; return result; } std::string DtaBNFScript::IGNORE_MODEtoString(IGNORE_MODE eMode) { std::string sResult; switch(eMode) { case NOT_IGNORE: break; case IGNORE_CPP: sResult = "C++";break; case IGNORE_JAVA: sResult = "JAVA";break; case IGNORE_HTML: sResult = "HTML";break; case IGNORE_BLANKS: sResult = "blanks";break; case IGNORE_ADA: sResult = "Ada";break; case IGNORE_LATEX: sResult = "LaTeX";break; case IGNORE_CPP_EXCEPT_DOXYGEN: sResult = "C++/Doxygen";break; case IGNORE_CLAUSE: throw UtlException("IGNORE_MODEtoString('IGNORE_CLAUSE') requires a specific handling!"); default: throw UtlException("internal error in DtaBNFScript::IGNORE_MODEtoString(): unrecognized ignore mode encountered"); } return sResult; } BNFClause& DtaBNFScript::buildClause(ScpStream& script, GrfBlock& parent, const std::string& sName, const std::string& sTemplateKey, bool bGenericKey, int iReturnType, const std::vector& listOfParameters, const std::vector& listOfParameterTypes, bool bOverload) { std::list& listOfHomonyms = _listOfClauses[sName]; BNFClause* pClause = NULL; std::list::iterator i; for (i = listOfHomonyms.begin(); i != listOfHomonyms.end(); i++) { if ((*i)->getArity() >= (int) listOfParameters.size()) { for (std::string::size_type j = 0; j < listOfParameters.size(); j++) { const std::string& sClauseParameter = (*i)->getParameter(j); if (listOfParameters[j] != sClauseParameter) { if (sClauseParameter.empty()) { (*i)->setParameter(j, listOfParameters[j], listOfParameterTypes[j]); } else throw UtlException(script, "parameter '" + listOfParameters[j] + "' must be called '" + sClauseParameter + "' into BNF clause declaration"); } } if (((*i)->getArity() > (int) listOfParameters.size()) && !(*i)->isPropagatedParameter()) { throw UtlException(script, "not enough parameters passed to the non-terminal '" + sName + "'"); } if (((*i)->getTemplateKey() == sTemplateKey) && ((*i)->isGenericKey() == bGenericKey)) { pClause = (*i); pClause->setParent(&parent); break; } } else { throw UtlException(script, "too many parameters passed to the non-terminal '" + sName + "'"); } } if (pClause == NULL) { if (bOverload) throw UtlException(script, "cannot overload a clause that doesn't exist yet!"); BNFClause* pTemplateClause = NULL; if (!sTemplateKey.empty()) pTemplateClause = &buildClause(script, parent, sName, "", false, iReturnType, listOfParameters, listOfParameterTypes, false); pClause = new BNFClause(this, &parent, sName, sTemplateKey, bGenericKey, listOfParameters, listOfParameterTypes); if ((sName[0] != '#') && (_graph.getNbCommands() == 0)) { pClause->setPreprocessingIgnoreMode(NOT_IGNORE, NULL); BNFClauseCall* pClauseCall = new BNFRootClauseCall(this, &_graph, _bNoCase); if (requiresParsingInformation()) pClauseCall->setParsingInformation(getFilenamePtr(), script); _graph.add(pClauseCall); pClauseCall->setClause(pClause); } if (!sTemplateKey.empty()) pClause->setTemplateClause(pTemplateClause); listOfHomonyms.push_front(pClause); } else if (bOverload) { BNFClause* pOverloadedClause = pClause; pClause = new BNFClause(this, &parent, sName, sTemplateKey, bGenericKey, listOfParameters, listOfParameterTypes); pOverloadedClause->setOverloadClause(pClause); } pClause->setReturnType(iReturnType); return *pClause; } BNFClause& DtaBNFScript::buildClause(ScpStream& script, GrfBlock& parent, const std::string& sName, unsigned int iArity) { std::list& listOfHomonyms = _listOfClauses[sName]; BNFClause* pClause = NULL; for (std::list::iterator i = listOfHomonyms.begin(); i != listOfHomonyms.end(); i++) { if ((*i)->getArity() < iArity) { throw UtlException(script, "too many parameters passed to the non-terminal '" + sName + "'"); } else if (((*i)->getArity() > iArity) && !(*i)->isPropagatedParameter()) { throw UtlException(script, "not enough parameters passed to the non-terminal '" + sName + "'"); } else if ((*i)->getTemplateKey().empty()) { pClause = (*i); break; } } if (pClause == NULL) { pClause = new BNFClause(this, &parent, sName, iArity); listOfHomonyms.push_front(pClause); } return *pClause; } void DtaBNFScript::parsePreprocessorDirective(const std::string& sDirective, ScpStream& script, GrfBlock& block) { if (sDirective == "#applyBNFRule") { script.skipEmpty(); std::string sIdentifier; if (!script.readIdentifier(sIdentifier)) throw UtlException(script, "the directive #applyBNFRule should be followed by a non-terminal"); BNFClauseCall* pClauseCall = parseBNFClauseCall(script, block, sIdentifier, false, _bNoCase); if (requiresParsingInformation()) pClauseCall->setParsingInformation(getFilenamePtr(), script); std::vector listOfConstants; bool bConcat; ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, true); pClauseCall->setVariableToAssign(pVarToAssign, bConcat); if (!listOfConstants.empty()) pClauseCall->setConstantsToMatch(listOfConstants); script.skipEmpty(); if (!script.isEqualTo(';')) throw UtlException(script, "syntax error, ';' expected to close the directive #applyBNFRule"); } else { DtaPatternScript::parsePreprocessorDirective(sDirective, script, block); } } void DtaBNFScript::parseInstruction(ScpStream& script, GrfBlock& block) { if (_bBNFMode) { int iStatementBeginning = script.getInputLocation(); if (script.isEqualTo('#')) { std::string sDirective; script.skipEmpty(); if (!script.readIdentifier(sDirective)) throw UtlException(script, "directive name expected"); sDirective = "#" + sDirective; parseBNFPreprocessorDirective(iStatementBeginning, sDirective, script, block); } else { std::string sClauseName; if (!script.readIdentifier(sClauseName)) { throw UtlException(script, "identifier expected: name of a BNF clause or 'function' or 'declare'"); } if ((sClauseName == "function") || (sClauseName == "external") || (sClauseName == "declare")) { script.skipEmpty(); std::string sIdentifier; int iCursor = script.getInputLocation(); if (script.readIdentifier(sIdentifier)) { script.setInputLocation(iCursor); _bBNFMode = false; if (sClauseName == "function") parseFunction(block, script); else if (sClauseName == "external") parseExternal(block, script); else parseDeclare(block, script); _bBNFMode = true; return; } throw UtlException("syntax error after keyword '" + sClauseName + "'"); } else if ((sClauseName == "readonlyHook") || (sClauseName == "writefileHook")) { _bBNFMode = false; if (sClauseName == "readonlyHook") parseReadonlyHook(block, script); else if (sClauseName == "writefileHook") parseWritefileHook(block, script); _bBNFMode = true; return; } else if ((sClauseName == "stepintoHook") || (sClauseName == "stepoutHook")) { _bBNFMode = false; if (sClauseName == "stepintoHook") parseStepintoHook(block, script); else if (sClauseName == "stepoutHook") parseStepoutHook(block, script); _bBNFMode = true; return; } parseBNFClause(script, block, iStatementBeginning, sClauseName, false); } } else { DtaPatternScript::parseInstruction(script, block); } } void DtaBNFScript::parseStepintoHook(GrfBlock& block, ScpStream& script) { if (getStepintoHook() != NULL) throw UtlException(script, "function 'stepintoHook(, )' has already been defined and can't be implemented twice"); BNFStepintoHook* pStepintoHook = new BNFStepintoHook(this, &block); if (requiresParsingInformation()) pStepintoHook->setParsingInformation(getFilenamePtr(), script); block.addFunction(pStepintoHook); script.skipEmpty(); if (!script.isEqualTo('(')) throw UtlException(script, "syntax error: '(' expected"); script.skipEmpty(); std::string sIdentifier; if (!script.readIdentifier(sIdentifier)) throw UtlException(script, "syntax error: argument name expected for "); pStepintoHook->setClauseSignature(sIdentifier.c_str()); script.skipEmpty(); if (!script.isEqualTo(',')) throw UtlException(script, "syntax error: ',' expected"); script.skipEmpty(); if (!script.readIdentifier(sIdentifier)) throw UtlException(script, "syntax error: argument name expected for "); pStepintoHook->setParameters(sIdentifier.c_str()); script.skipEmpty(); if (!script.isEqualTo(')')) throw UtlException(script, "syntax error: ')' expected"); std::string _sOldFunctionBody = _sCurrentFunctionBody; std::string _sOldFunctionTemplateBody = _sCurrentFunctionTemplateBody; bool bOldCurrentFunctionGenericTemplateKey = _bCurrentFunctionGenericTemplateKey; _sCurrentFunctionBody = pStepintoHook->getFunctionName(); _sCurrentFunctionTemplateBody = ""; _bCurrentFunctionGenericTemplateKey = false; pStepintoHook->isBodyDefined(true); parseBlock(script, *pStepintoHook); _sCurrentFunctionBody = _sOldFunctionBody; _sCurrentFunctionTemplateBody = _sOldFunctionTemplateBody; _bCurrentFunctionGenericTemplateKey = bOldCurrentFunctionGenericTemplateKey; } void DtaBNFScript::parseStepoutHook(GrfBlock& block, ScpStream& script) { if (getStepoutHook() != NULL) throw UtlException(script, "function 'StepoutHook(, , )' has already been defined and can't be implemented twice"); BNFStepoutHook* pStepoutHook = new BNFStepoutHook(this, &block); if (requiresParsingInformation()) pStepoutHook->setParsingInformation(getFilenamePtr(), script); block.addFunction(pStepoutHook); script.skipEmpty(); if (!script.isEqualTo('(')) throw UtlException(script, "syntax error: '(' expected"); script.skipEmpty(); std::string sIdentifier; if (!script.readIdentifier(sIdentifier)) throw UtlException(script, "syntax error: argument name expected for "); pStepoutHook->setClauseSignature(sIdentifier.c_str()); script.skipEmpty(); if (!script.isEqualTo(',')) throw UtlException(script, "syntax error: ',' expected"); script.skipEmpty(); if (!script.readIdentifier(sIdentifier)) throw UtlException(script, "syntax error: argument name expected for "); pStepoutHook->setParameters(sIdentifier.c_str()); script.skipEmpty(); if (!script.isEqualTo(',')) throw UtlException(script, "syntax error: ',' expected"); script.skipEmpty(); if (!script.readIdentifier(sIdentifier)) throw UtlException(script, "syntax error: argument name expected for "); pStepoutHook->setSuccess(sIdentifier.c_str()); script.skipEmpty(); if (!script.isEqualTo(')')) throw UtlException(script, "syntax error: ')' expected"); std::string _sOldFunctionBody = _sCurrentFunctionBody; std::string _sOldFunctionTemplateBody = _sCurrentFunctionTemplateBody; bool bOldCurrentFunctionGenericTemplateKey = _bCurrentFunctionGenericTemplateKey; _sCurrentFunctionBody = pStepoutHook->getFunctionName(); _sCurrentFunctionTemplateBody = ""; _bCurrentFunctionGenericTemplateKey = false; pStepoutHook->isBodyDefined(true); parseBlock(script, *pStepoutHook); _sCurrentFunctionBody = _sOldFunctionBody; _sCurrentFunctionTemplateBody = _sOldFunctionTemplateBody; _bCurrentFunctionGenericTemplateKey = bOldCurrentFunctionGenericTemplateKey; } void DtaBNFScript::parseBNFPreprocessorDirective(int iStatementBeginning, const std::string& sDirective, ScpStream& script, GrfBlock& block) { if (sDirective == "#ignore") { std::string sClauseName = sDirective; std::string sKey; script.skipEmpty(); if (script.isEqualTo('[')) { script.skipEmpty(); if (!script.readPythonString(sKey)) throw UtlException(script, "syntax error, constant string expected"); script.skipEmpty(); if (!script.isEqualTo(']')) throw UtlException(script, "syntax error, ']' expected"); if (!sKey.empty()) sClauseName += "[" + sKey + "]"; } BNFClause& theIgnoreClause = parseBNFClause(script, block, iStatementBeginning, sClauseName, false); if (theIgnoreClause.getArity() != 0) throw UtlException(script, "clause '#ignore' doesn't accept parameters"); _mapOfIgnoreClauses[sClauseName] = &theIgnoreClause; } else if (sDirective == "#noCase") { _bNoCase = true; } else if (sDirective == "#trace") { _bTrace = true; } else if (sDirective == "#matching") { script.skipEmpty(); if (!script.isEqualTo('(')) throw UtlException(script, "syntax error, '(' expected"); script.skipEmpty(); if (_pMatchingAreasContainer != NULL) { delete _pMatchingAreasContainer; _pMatchingAreasContainer = NULL; } _pMatchingAreasContainer = parseBNFVariableExpression(block, script); script.skipEmpty(); if (!script.isEqualTo(')')) throw UtlException(script, "syntax error, ')' expected"); } else if (sDirective == "#parameters") { parseAndPropagateParameters(script, block); } else if (sDirective == "#transformRules") { parseTransformRules(script, block); } else if (sDirective == "#overload") { std::string sClauseName; script.skipEmpty(); if (script.isEqualTo('#')) { script.skipEmpty(); if (script.isEqualToIdentifier("ignore")) sClauseName = "#ignore"; } else if (!script.readIdentifier(sClauseName)) throw UtlException(script, "clause name to overload expected"); parseBNFClause(script, block, iStatementBeginning, sClauseName, true); } else if (sDirective == "#buildAST") { script.skipEmpty(); if (!script.isEqualTo('(')) throw UtlException(script, "syntax error, '(' expected"); script.skipEmpty(); if (_pASTContainer != NULL) { delete _pASTContainer; _pASTContainer = NULL; } _pASTContainer = parseBNFVariableExpression(block, script); script.skipEmpty(); if (!script.isEqualTo(')')) throw UtlException(script, "syntax error, ')' expected"); } else DtaPatternScript::parsePreprocessorDirective(sDirective, script, block); } void DtaBNFScript::parseAndPropagateParameters(ScpStream& script, GrfBlock& block) { std::string sFunctionQuantity; script.skipEmpty(); if (!script.readIdentifier(sFunctionQuantity)) throw UtlException(script, "function quantity expected"); script.skipEmpty(); if (!script.isEqualTo('(')) throw UtlException(script, "'(' expected"); std::vector listOfParameters; std::vector listOfParameterTypes; script.skipEmpty(); if (!script.isEqualTo(')')) { int iIndex = 0; EXPRESSION_TYPE paramType; do { std::string sParameter; script.skipEmpty(); if (!script.readIdentifier(sParameter)) throw UtlException(script, "parameter name expected"); script.skipEmpty(); if (!script.isEqualTo(':')) throw UtlException(script, "':' expected after parameter '" + sParameter + "'"); paramType = parseVariableType(block, script); listOfParameters.push_back(sParameter); listOfParameterTypes.push_back(paramType); iIndex++; } while (script.isEqualTo(',')); if (!script.isEqualTo(')')) throw UtlException(script, "')' expected"); } std::auto_ptr pFilter(parseExpression(block, script)); for (std::map >::iterator i = _listOfClauses.begin(); i != _listOfClauses.end(); ++i) { for (std::list::iterator j = i->second.begin(); j != i->second.end(); ++j) { (*j)->propagateParameters(*pFilter, sFunctionQuantity, listOfParameters, listOfParameterTypes); } } } void DtaBNFScript::parseTransformRules(ScpStream& script, GrfBlock& block) { BNFTransformRules* pTransformer = new BNFTransformRules; _listOfTransformRules.push_back(pTransformer); pTransformer->setFilter(parseExpression(block, script)); script.skipEmpty(); int iBeforeBrace = script.getInputLocation(); if (!script.isEqualTo('{')) throw UtlException(script, "'{' expected"); script.skipEmpty(); if (!script.isEqualTo('}')) { script.setInputLocation(iBeforeBrace); pTransformer->setPrototypeScript(new DtaTranslateScript(&block)); pTransformer->getPrototypeScript()->parseEmbeddedScript(script); } script.skipEmpty(); iBeforeBrace = script.getInputLocation(); if (!script.isEqualTo('{')) throw UtlException(script, "'{' expected to transform the production rule"); script.skipEmpty(); if (!script.isEqualTo('}')) { script.setInputLocation(iBeforeBrace); pTransformer->setProductionRuleScript(new DtaTranslateScript(&block)); pTransformer->getProductionRuleScript()->parseEmbeddedScript(script); } } BNFClause& DtaBNFScript::parseBNFClause(ScpStream& script, GrfBlock& block, int iStatementBeginning, const std::string& sClauseName, bool bOverload) { if (!_listOfTransformRules.empty()) { int iLocation = script.getInputLocation(); std::string sCompleteClauseName = sClauseName; script.skipEmpty(); if (script.isEqualTo('<')) { script.skipEmpty(); std::string sText; bool bString = false; if (script.readIdentifier(sText) || script.readPythonString(sText) && (bString = true)) { script.skipEmpty(); if (script.isEqualTo('>')) { if (bString) sText = "\"" + CGRuntime::composeCLikeString(sText) + "\""; sCompleteClauseName += "<" + sText + ">"; } else { // syntax error, to resolve further script.setInputLocation(iLocation); } } else { // syntax error, to resolve further script.setInputLocation(iLocation); } } if (script.findString("::=")) { int iStartProductionRule = script.getInputLocation(); char cChar = '\0'; script.setOutputLocation(iStartProductionRule - 3); script.writeBinaryData(&cChar, 1); std::string sPrototype = script.readBuffer() + iStatementBeginning; cChar = ':'; script.setOutputLocation(iStartProductionRule - 3); script.writeBinaryData(&cChar, 1); int iBrackets = 0; bool bInstruction = false; bool bFail = true; std::string sText; while (bFail && script.skipEmpty()) { switch(script.readChar()) { case '\'': case '\"': script.goBack(); script.readStringOrCharLiteral(sText); break; case '%': if (!script.isEqualTo('>')) break; case '@': do { if (script.isEqualTo('<') && script.isEqualTo('%')) break; script.isEqualTo('\\'); } while (!script.isEqualTo('@')); break; case '{': bInstruction = false; iBrackets++; break; case '}': iBrackets--; break; case '=': if (!bInstruction) bInstruction = script.isEqualTo('>'); break; case ';': if (iBrackets == 0) { if (!bInstruction) bFail = false; else bInstruction = false; } } } if (!bFail) { int iEndProductionRule = script.getInputLocation() - 1; cChar = '\0'; script.setOutputLocation(iEndProductionRule); script.writeBinaryData(&cChar, 1); std::string sProductionRule = script.readBuffer() + iStartProductionRule; cChar = ';'; script.setOutputLocation(iEndProductionRule); script.writeBinaryData(&cChar, 1); for (std::list::const_iterator i = _listOfTransformRules.begin(); i != _listOfTransformRules.end(); ++i) { // if the current rule transformer applies with success, // the new rule replaces the old one in the input stream if ((*i)->applyRuleTransformer(script, block, iStatementBeginning, iStartProductionRule, sCompleteClauseName, sPrototype, sProductionRule)) break; } } script.setInputLocation(iLocation); } } std::vector listOfParameters; std::vector listOfParameterTypes; std::string sTemplateKey; bool bGenericKey = false; script.skipEmpty(); if (script.isEqualTo('<')) { script.skipEmpty(); if (!script.readPythonString(sTemplateKey)) { if (script.readIdentifier(sTemplateKey)) { if (sTemplateKey != "true") { if (sTemplateKey == "false") sTemplateKey = ""; else bGenericKey = true; } } else throw UtlException(script, "template key expected for clause '" + sClauseName + "'"); } script.skipEmpty(); if (!script.isEqualTo('>')) throw UtlException(script, "'>' to end the template key '" + sTemplateKey + "' for clause '" + sClauseName + "'"); script.skipEmpty(); } if (script.isEqualTo('(')) { do { std::string sParameter; script.skipEmpty(); if (!script.readIdentifier(sParameter)) throw UtlException(script, "parameter expected while parsing a BNF clause for declaration"); if (sParameter == sClauseName) throw UtlException(script, "the parameter '" + sParameter + "' cannot hold the same name as the BNF rule"); listOfParameters.push_back(sParameter); script.skipEmpty(); if (!script.isEqualTo(':')) throw UtlException(script, "':' expected after parameter '" + sParameter + "' while parsing a BNF clause for declaration"); script.skipEmpty(); std::string sType; if (!script.readIdentifier(sType)) throw UtlException(script, "parameter type expected for '" + sParameter + "' while parsing a BNF clause for declaration"); EXPRESSION_TYPE exprType; if (sType == "node") exprType = NODE_EXPRTYPE; else if (sType == "reference") exprType = REFERENCE_EXPRTYPE; else if (sType == "value") exprType = VALUE_EXPRTYPE; else if (sType == "variable") { std::string sErrorMessage = script.getMessagePrefix() + "warning! parameter type 'variable' is obsolete since version 3.8.7 -> replace it by 'node'"; if (DtaProject::getInstance().addWarning(sErrorMessage) == 1) CGRuntime::traceLine(sErrorMessage); exprType = NODE_EXPRTYPE; } else throw UtlException(script, "unknown type '" + sType + "' for parameter '" + sParameter + "' while parsing a BNF clause for declaration"); exprType = parseClassType(block, script, exprType); listOfParameterTypes.push_back(exprType); script.skipEmpty(); } while (script.isEqualTo(',')); if (!script.isEqualTo(')')) throw UtlException(script, "')' expected while parsing a BNF clause declaration"); script.skipEmpty(); } if (!script.isEqualTo(':')) throw UtlException(script, "'::=' or ':' expected after parsing a BNF clause declaration"); int iReturnType = BNFClause::NO_RETURN_TYPE; IGNORE_MODE ePreprocessingIgnoreMode = UNDEFINED_IGNORE; BNFClause* pPreprocessingIgnoreClause = NULL; if (!script.isEqualTo(':')) { std::string sReturnType; bool bDefinitionExpected = false; script.skipEmpty(); if (script.readIdentifier(sReturnType)) { if (sReturnType == "list") iReturnType = BNFClause::LIST_RETURN_TYPE; else if (sReturnType == "node") iReturnType = BNFClause::NODE_RETURN_TYPE; else if (sReturnType == "value") iReturnType = BNFClause::VALUE_RETURN_TYPE; else throw UtlException(script, "'list' or 'node' expected instead of '" + sReturnType + "', while parsing return type of a BNF clause for declaration"); script.skipEmpty(); if (script.isEqualTo("::=")) bDefinitionExpected = true; else if (!script.isEqualTo(':')) throw UtlException(script, "'::=' expected after parsing a BNF clause declaration"); } if (!bDefinitionExpected) { if (script.isEqualTo('#')) { if (script.isEqualTo('!')) { if (!script.isEqualToIdentifier("ignore")) throw UtlException(script, "'#!ignore' expected as preprocessing of a BNF clause"); ePreprocessingIgnoreMode = NOT_IGNORE; } else if (script.isEqualToIdentifier("ignore")) { ePreprocessingIgnoreMode = parseIgnoreMode(script, pPreprocessingIgnoreClause); } else { throw UtlException(script, "'::=' or ':' or '#ignore' expected after parsing a BNF clause declaration"); } script.skipEmpty(); } script.skipEmpty(); if (!script.isEqualTo("::=")) throw UtlException(script, "'::=' expected after parsing a BNF clause declaration"); } } else if (!script.isEqualTo('=')) throw UtlException(script, "'::=' expected after parsing a BNF clause declaration"); BNFClause& myClause = buildClause(script, block, sClauseName, sTemplateKey, bGenericKey, iReturnType, listOfParameters, listOfParameterTypes, bOverload); if (myClause.getNbCommands() > 0) throw UtlException(script, "clause '" + myClause.getSignature() + "' has already been described"); // register the clause name as a local variable, if returned value/node expected if ((iReturnType == BNFClause::LIST_RETURN_TYPE) || (iReturnType == BNFClause::NODE_RETURN_TYPE)) { myClause.addLocalVariable(sClauseName, NODE_EXPRTYPE); } else if (iReturnType == BNFClause::VALUE_RETURN_TYPE) { myClause.addLocalVariable(sClauseName, VALUE_EXPRTYPE); } // register the generic template key, if any if (bGenericKey && !sTemplateKey.empty()) { myClause.addLocalVariable(sTemplateKey, VALUE_EXPRTYPE); } GrfBlock* pParent; if (ePreprocessingIgnoreMode != UNDEFINED_IGNORE) { myClause.setPreprocessingIgnoreMode(ePreprocessingIgnoreMode, pPreprocessingIgnoreClause); BNFIgnore* pIgnore = new BNFIgnore(this, &myClause, ePreprocessingIgnoreMode, pPreprocessingIgnoreClause); myClause.add(pIgnore); pParent = pIgnore; } else { pParent = &myClause; } script.skipEmpty(); parseBNFDisjunction(script, myClause, *pParent, _bNoCase, NULL); script.skipEmpty(); if (!script.isEqualTo(';')) throw UtlException(script, "';' expected at the end of a BNF clause definition"); return myClause; } void DtaBNFScript::parseBNFDisjunction(ScpStream& script, BNFClause& rule, GrfBlock& block, bool bNoCase, BNFStepper* pStepperRE) { BNFDisjunction* pDisjunction = new BNFDisjunction(this, &block); if (requiresParsingInformation()) pDisjunction->setParsingInformation(getFilenamePtr(), script); block.add(pDisjunction); parseBNFConjunction(script, rule, *pDisjunction, false, bNoCase, pStepperRE); if (script.isEqualTo('|')) { do { parseBNFConjunction(script, rule, *pDisjunction, false, bNoCase, pStepperRE); } while (script.isEqualTo('|')); } else { pDisjunction->moveCommands(block); block.removeCommand(pDisjunction); } } void DtaBNFScript::parseBNFConjunction(ScpStream& script, BNFClause& rule, GrfBlock& block, bool bContinue, bool bNoCase, BNFStepper* pStepperRE) { BNFConjunction* pConjunction = new BNFConjunction(this, &block); if (requiresParsingInformation()) pConjunction->setParsingInformation(getFilenamePtr(), script); block.add(pConjunction); parseBNFSequence(script, rule, *pConjunction, bContinue, bNoCase, pStepperRE); if (pConjunction->getNbCommands() == 1) { pConjunction->moveCommands(block); block.removeCommand(pConjunction); } } void DtaBNFScript::parseBNFSequence(ScpStream& script, BNFClause& rule, GrfBlock& block, bool bContinue, bool bNoCase, BNFStepper* pStepperRE) { bool bSuccess = parseBNFLitteral(script, rule, block, bContinue, bNoCase, false /* if '=>' or ':' after reading this literal, it belongs to it */, pStepperRE); if (!bSuccess) { int iChar = script.readChar(); std::string sChar; if (iChar < 0) sChar = "end of file"; else sChar = std::string("'") + (char) iChar + "'"; throw UtlException(script, "literal expected, instead of " + sChar); } while (parseBNFLitteral(script, rule, block, bContinue, bNoCase, false /* if '=>' or ':' after reading this literal, it belongs to it */, pStepperRE)) ; } ExprScriptVariable* DtaBNFScript::parseBNFVariableExpression(GrfBlock& block, ScpStream& script) { ExprScriptVariable* pVariableExpr = NULL; script.skipEmpty(); std::string sVariableName; if (script.readIdentifier(sVariableName)) { block.addBNFLocalVariable(sVariableName, NODE_EXPRTYPE); pVariableExpr = new ExprScriptVariable(sVariableName.c_str()); } return parseVariableExpression(block, script, pVariableExpr); } ExprScriptVariable* DtaBNFScript::parseLiteralAssignment(ScpStream& script, GrfBlock& block, std::vector& listOfConstants, bool& bConcatVariable, bool bVariableAllowed) { ExprScriptVariable* pVariableExpr = NULL; script.skipEmpty(); int iLocation = script.getInputLocation(); if (script.isEqualTo(':')) { bool bTryVariable = false; script.skipEmpty(); if (script.isEqualTo('\"')) { script.goBack(); std::string sConstant; if (!script.readPythonString(sConstant)) throw UtlException(script, "constant string expected"); listOfConstants.push_back(sConstant); bTryVariable = bVariableAllowed; } else if (script.isEqualTo('\'')) { script.goBack(); int iChar; if (!script.readCharLiteral(iChar)) throw UtlException(script, "char literal expected"); listOfConstants.push_back(std::string(1, (unsigned char) iChar)); bTryVariable = bVariableAllowed; } else if (script.isEqualTo('{')) { do { script.skipEmpty(); std::string sConstant; if (!script.readStringOrCharLiteral(sConstant)) throw UtlException(script, "constant string expected"); listOfConstants.push_back(sConstant); script.skipEmpty(); } while (script.isEqualTo(',')); if (!script.isEqualTo('}')) throw UtlException(script, "'}' expected to close a set of constant strings"); bTryVariable = bVariableAllowed; } else if (bVariableAllowed) { bConcatVariable = script.isEqualTo('+'); if (hasTargetLanguage()) { pVariableExpr = parseAlienVariableExpression(block, script); } else { pVariableExpr = parseBNFVariableExpression(block, script); } } else { script.setInputLocation(iLocation); } if (bTryVariable) { script.skipEmpty(); if (script.isEqualTo(':')) { bConcatVariable = script.isEqualTo('+'); if (hasTargetLanguage()) { pVariableExpr = parseAlienVariableExpression(block, script); } else { pVariableExpr = parseBNFVariableExpression(block, script); } } } } return pVariableExpr; } bool DtaBNFScript::parseBNFLitteral(ScpStream& script, BNFClause& rule, GrfBlock& block, bool& bContinue, bool& bNoCase, bool bLiteralOnly, BNFStepper* pStepperRE) { bool bSuccess = true; script.skipEmpty(); if (script.isEqualTo('\"')) { script.goBack(); std::string sText; if (!script.readPythonString(sText)) throw UtlException(script, "string literal expected into BNF clause definition"); BNFString* pString = new BNFString(this, &block, sText, bContinue, bNoCase); if (requiresParsingInformation()) pString->setParsingInformation(getFilenamePtr(), script); block.add(pString); std::vector listOfConstants; bool bConcat; ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly); pString->setVariableToAssign(pVarToAssign, bConcat, rule); if (!listOfConstants.empty()) throw UtlException(script, "it has no sense to match a string literal with a constant string"); } else if (script.isEqualTo('\'')) { script.goBack(); int iChar; if (!script.readCharLiteral(iChar)) throw UtlException(script, "char literal expected (between quotes)"); script.skipEmpty(); if (script.isEqualTo("..")) { script.skipEmpty(); int iEndChar; if (!script.readCharLiteral(iEndChar)) throw UtlException(script, "char literal expected (between quotes) after '..'"); if (iChar > iEndChar) throw UtlException(script, "range expression '..' must be ordered correctly"); BNFCharBoundaries* pCharBoundaries = new BNFCharBoundaries(this, &block, iChar, iEndChar, bContinue, bNoCase); if (requiresParsingInformation()) pCharBoundaries->setParsingInformation(getFilenamePtr(), script); block.add(pCharBoundaries); std::vector listOfConstants; bool bConcat; ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly); pCharBoundaries->setVariableToAssign(pVarToAssign, bConcat, rule); if (!listOfConstants.empty()) pCharBoundaries->setConstantsToMatch(listOfConstants); } else { BNFCharLitteral* pCharLitteral = new BNFCharLitteral(this, &block, iChar, bContinue, bNoCase); if (requiresParsingInformation()) pCharLitteral->setParsingInformation(getFilenamePtr(), script); block.add(pCharLitteral); std::vector listOfConstants; bool bConcat; ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly); pCharLitteral->setVariableToAssign(pVarToAssign, bConcat, rule); if (!listOfConstants.empty()) throw UtlException(script, "a char literal shouldn't expect a set of constant values"); } } else if (script.isEqualTo('~') || script.isEqualTo('^')) { BNFComplementary* pComplementary = new BNFComplementary(this, &block, bContinue); if (requiresParsingInformation()) pComplementary->setParsingInformation(getFilenamePtr(), script); block.add(pComplementary); bool bNextContinue = false; bool bNextNoCase = bNoCase; parseBNFLitteral(script, rule, *pComplementary, bNextContinue, bNextNoCase, true /* if '=>' or ':' after reading this literal, it doesn't belong to it */, pComplementary); std::vector listOfConstants; bool bConcat; ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly); pComplementary->setVariableToAssign(pVarToAssign, bConcat, rule); if (!listOfConstants.empty()) pComplementary->setConstantsToMatch(listOfConstants); } else if (script.isEqualTo("->")) { BNFFindToken* pFindToken = new BNFFindToken(this, &block, bContinue); if (requiresParsingInformation()) pFindToken->setParsingInformation(getFilenamePtr(), script); block.add(pFindToken); bool bConcat; ExprScriptVariable* pVarToAssign; BNFMultiplicityBoundaries* pBoundaries = parseMultiplicity(script, block); if (pBoundaries != NULL) { pFindToken->setBoundaries(pBoundaries); script.skipEmpty(); } if (script.isEqualTo('(')) { std::vector listOfIntermediateConstants; pVarToAssign = parseLiteralAssignment(script, block, listOfIntermediateConstants, bConcat, true); pFindToken->setIntermediateVariableToAssign(pVarToAssign, bConcat, rule); if (!listOfIntermediateConstants.empty()) pFindToken->setIntermediateConstantsToMatch(listOfIntermediateConstants); script.skipEmpty(); if (script.isEqualTo('-')) { std::vector listOfFinalConstants; pVarToAssign = parseLiteralAssignment(script, block, listOfFinalConstants, bConcat, true); pFindToken->setFinalVariableToAssign(pVarToAssign, bConcat, rule); if (!listOfFinalConstants.empty()) pFindToken->setFinalConstantsToMatch(listOfFinalConstants); script.skipEmpty(); } if (!script.isEqualTo(')')) { parseBNFDisjunction(script, rule, pFindToken->createIntermediateSequence(), bNoCase, pStepperRE); if (!script.isEqualTo(')')) throw UtlException(script, "')' expected"); } } bool bNextContinue = false; bool bNextNoCase = bNoCase; parseBNFLitteral(script, rule, *pFindToken, bNextContinue, bNextNoCase, true /* if '=>' or ':' after reading this literal, it doesn't belong to it */, pFindToken); std::vector listOfConstants; pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly); pFindToken->setVariableToAssign(pVarToAssign, bConcat, rule); if (!listOfConstants.empty()) pFindToken->setConstantsToMatch(listOfConstants); } else if (script.isEqualTo('!')) { BNFNot* pNot = new BNFNot(this, &block, bContinue); if (requiresParsingInformation()) pNot->setParsingInformation(getFilenamePtr(), script); block.add(pNot); bool bNextContinue = false; bool bNextNoCase = bNoCase; parseBNFLitteral(script, rule, *pNot, bNextContinue, bNextNoCase, true /* if '=>' or ':' after reading this literal, it doesn't belong to it */, pStepperRE); } else if (script.isEqualTo('[')) { BNFMultiplicity* pMultiplicity = new BNFMultiplicity(this, &block, bContinue); if (requiresParsingInformation()) pMultiplicity->setParsingInformation(getFilenamePtr(), script); block.add(pMultiplicity); parseBNFDisjunction(script, rule, *pMultiplicity, bNoCase, pStepperRE); if (!script.isEqualTo(']')) throw UtlException(script, "']' expected into BNF clause definition"); parseMultiplicity(script, block, &pMultiplicity->getBoundaries()); std::vector listOfConstants; bool bConcat; ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly); pMultiplicity->setVariableToAssign(pVarToAssign, bConcat, rule); if (!listOfConstants.empty()) pMultiplicity->setConstantsToMatch(listOfConstants); } else if (script.isEqualTo('#')) { int iSharpLocation = script.getInputLocation() - 1; std::string sIdentifier; if (!script.readIdentifier(sIdentifier)) { if (script.isEqualTo('!') && script.readIdentifier(sIdentifier)) { if (sIdentifier == "ignore") { BNFIgnore* pIgnore = new BNFIgnore(this, &block, NOT_IGNORE, NULL); if (requiresParsingInformation()) pIgnore->setParsingInformation(getFilenamePtr(), script); block.add(pIgnore); while (parseBNFLitteral(script, rule, *pIgnore, bContinue, bNoCase, false /* if '=>' or ':' after reading this literal, it belongs to it */, pStepperRE)) ; } else { throw UtlException(script, "macro instruction '#!" + sIdentifier + "' doesn't exist"); } } else { throw UtlException(script, "macro instruction expected after '#'"); } } else if (sIdentifier == "catch") { script.setInputLocation(iSharpLocation); return false; } else if (sIdentifier == "continue") { bool bNextContinue = true; while (parseBNFLitteral(script, rule, block, bNextContinue, bNoCase, false /* if '=>' or ':' after reading this literal, it belongs to it */, pStepperRE)) ; } else if (sIdentifier == "noCase") { bool bNextNoCase = true; while (parseBNFLitteral(script, rule, block, bContinue, bNextNoCase, false /* if '=>' or ':' after reading this literal, it belongs to it */, pStepperRE)) ; } else if (sIdentifier == "ratchet") { BNFRatchet* pBNFRatchet = new BNFRatchet(this, &block); if (requiresParsingInformation()) pBNFRatchet->setParsingInformation(getFilenamePtr(), script); block.add(pBNFRatchet); while (parseBNFLitteral(script, rule, block, bContinue, bNoCase, false /* if '=>' or ':' after reading this literal, it belongs to it */, pStepperRE)) ; } else if (sIdentifier == "try") { BNFTryCatch* pBNFTryCatch = new BNFTryCatch(this, &block); if (requiresParsingInformation()) pBNFTryCatch->setParsingInformation(getFilenamePtr(), script); block.add(pBNFTryCatch); do { script.skipEmpty(); if (script.isEqualTo('#')) { int iLocation = script.getInputLocation(); script.skipEmpty(); if (script.isEqualTo("catch")) { script.skipEmpty(); if (!script.isEqualTo('(')) throw UtlException(script, "syntax error, directive '#catch' expects a '('"); script.skipEmpty(); std::string sVariableName; if (!script.readIdentifier(sVariableName)) throw UtlException(script, "variable name expected to catch the error message"); if (block.getVariable(sVariableName) == UNKNOWN_EXPRTYPE) block.addBNFLocalVariable(sVariableName, VALUE_EXPRTYPE); pBNFTryCatch->setErrorMessage(parseVariableExpression(block, script, new ExprScriptVariable(sVariableName.c_str()))); script.skipEmpty(); if (!script.isEqualTo(')')) throw UtlException(script, "syntax error, directive '#catch' expects a ')'"); break; } else { script.setInputLocation(iLocation - 1); } } else { script.goBack(); } } while (parseBNFLitteral(script, rule, *pBNFTryCatch->getTryBlock(), bContinue, bNoCase, false /* if '=>' or ':' after reading this literal, it belongs to it */, pStepperRE)); if (pBNFTryCatch->getErrorMessage() == NULL) throw UtlException(script, "directive '#catch' expected before the end of the sequence"); } else if (sIdentifier == "parsedFile") { script.skipEmpty(); if (!isAParseScript()) throw UtlException(script, "directive '#parsedFile' is available on parsing scripts only"); GrfParsedFile* pParsedFile = new GrfParsedFile(&block); if (requiresParsingInformation()) pParsedFile->setParsingInformation(getFilenamePtr(), script); block.add(pParsedFile); if (!script.isEqualTo('(')) throw UtlException(script, "'(' expected by clause '#parsedFile'"); script.skipEmpty(); pParsedFile->setInputFile(parseExpression(block, script)); script.skipEmpty(); if (!script.isEqualTo(')')) throw UtlException(script, "')' expected by clause '#parsedFile'"); while (parseBNFLitteral(script, rule, *pParsedFile, bContinue, bNoCase, false /* if '=>' or ':' after reading this literal, it belongs to it */, pStepperRE)) ; } else if (sIdentifier == "parsedString") { script.skipEmpty(); if (!isAParseScript()) throw UtlException(script, "directive '#parsedString' is available on parsing scripts only"); GrfParsedString* pParsedString = new GrfParsedString(&block); if (requiresParsingInformation()) pParsedString->setParsingInformation(getFilenamePtr(), script); block.add(pParsedString); if (!script.isEqualTo('(')) throw UtlException(script, "'(' expected by clause '#parsedString'"); script.skipEmpty(); pParsedString->setInputString(parseExpression(block, script)); script.skipEmpty(); if (!script.isEqualTo(')')) throw UtlException(script, "')' expected by clause '#parsedString'"); while (parseBNFLitteral(script, rule, *pParsedString, bContinue, bNoCase, false /* if '=>' or ':' after reading this literal, it belongs to it */, pStepperRE)) ; } else if (sIdentifier == "generatedFile") { script.skipEmpty(); if (!isAGenerateScript()) throw UtlException(script, "directive '#generatedFile' is available on pattern scripts only"); GrfGeneratedFile* pGeneratedFile = new GrfGeneratedFile(this, &block); if (requiresParsingInformation()) pGeneratedFile->setParsingInformation(getFilenamePtr(), script); block.add(pGeneratedFile); if (!script.isEqualTo('(')) throw UtlException(script, "'(' expected by clause '#generatedFile'"); script.skipEmpty(); pGeneratedFile->setOutputFile(parseExpression(block, script)); script.skipEmpty(); if (!script.isEqualTo(')')) throw UtlException(script, "')' expected by clause '#generatedFile'"); while (parseBNFLitteral(script, rule, *pGeneratedFile, bContinue, bNoCase, false /* if '=>' or ':' after reading this literal, it belongs to it */, pStepperRE)) ; } else if (sIdentifier == "generatedString") { script.skipEmpty(); if (!isAGenerateScript()) throw UtlException(script, "directive '#generatedString' is available on pattern scripts only"); GrfGeneratedString* pGeneratedString = new GrfGeneratedString(this, &block); if (requiresParsingInformation()) pGeneratedString->setParsingInformation(getFilenamePtr(), script); block.add(pGeneratedString); if (!script.isEqualTo('(')) throw UtlException(script, "'(' expected by clause '#generatedString'"); script.skipEmpty(); pGeneratedString->setOutputString(parseVariableExpression(block, script)); script.skipEmpty(); if (!script.isEqualTo(')')) throw UtlException(script, "')' expected by clause '#generatedString'"); while (parseBNFLitteral(script, rule, *pGeneratedString, bContinue, bNoCase, false /* if '=>' or ':' after reading this literal, it belongs to it */, pStepperRE)) ; } else if (sIdentifier == "appendedFile") { script.skipEmpty(); if (!isAGenerateScript()) throw UtlException(script, "statement modifier 'append_file' is available on pattern scripts only"); GrfAppendedFile* pAppendedFile = new GrfAppendedFile(this, &block); if (requiresParsingInformation()) pAppendedFile->setParsingInformation(getFilenamePtr(), script); block.add(pAppendedFile); if (!script.isEqualTo('(')) throw UtlException(script, "'(' expected by clause '#appendedFile'"); script.skipEmpty(); pAppendedFile->setOutputFile(parseExpression(block, script)); script.skipEmpty(); if (!script.isEqualTo(')')) throw UtlException(script, "')' expected by clause '#appendedFile'"); while (parseBNFLitteral(script, rule, *pAppendedFile, bContinue, bNoCase, false /* if '=>' or ':' after reading this literal, it belongs to it */, pStepperRE)) ; } else if (sIdentifier == "debug") { GrfDebugExecution* pDebug = new GrfDebugExecution(&block); if (requiresParsingInformation()) pDebug->setParsingInformation(getFilenamePtr(), script); block.add(pDebug); while (parseBNFLitteral(script, rule, *pDebug, bContinue, bNoCase, false /* if '=>' or ':' after reading this literal, it belongs to it */, pStepperRE)) ; } else if (sIdentifier == "ignore") { BNFClause* pIgnoreClause = NULL; IGNORE_MODE eMode = parseIgnoreMode(script, pIgnoreClause); BNFIgnore* pIgnore = new BNFIgnore(this, &block, eMode, pIgnoreClause); if (requiresParsingInformation()) pIgnore->setParsingInformation(getFilenamePtr(), script); block.add(pIgnore); while (parseBNFLitteral(script, rule, *pIgnore, bContinue, bNoCase, false /* if '=>' or ':' after reading this literal, it belongs to it */, pStepperRE)) ; } else if (sIdentifier == "nextStep") { if (pStepperRE == NULL) throw UtlException(script, "'#nextStep' must be declared into a jump ('->') or repeat ('[...]*') statement"); BNFNextStep* pNextStep = new BNFNextStep(this, &block, pStepperRE); if (requiresParsingInformation()) pNextStep->setParsingInformation(getFilenamePtr(), script); block.add(pNextStep); } else if (sIdentifier == "break") { BNFBreak* pBreak = new BNFBreak(&block); if (requiresParsingInformation()) pBreak->setParsingInformation(getFilenamePtr(), script); block.add(pBreak); } else if (sIdentifier == "empty") { BNFEndOfFile* pEndOfFile = new BNFEndOfFile(this, &block, bContinue); if (requiresParsingInformation()) pEndOfFile->setParsingInformation(getFilenamePtr(), script); block.add(pEndOfFile); } else if (sIdentifier == "pushItem") { BNFPushItem* pPushItem = new BNFPushItem(this, &block); if (requiresParsingInformation()) pPushItem->setParsingInformation(getFilenamePtr(), script); block.add(pPushItem); script.skipEmpty(); if (!script.isEqualTo('(')) throw UtlException(script, "'(' expected after '#pushItem' to pass the array"); pPushItem->setVariable(parseVariableExpression(block, script)); if (!script.isEqualTo(')')) throw UtlException(script, "')' expected after passing the array to '#pushItem'"); parseBNFSequence(script, rule, *pPushItem, bContinue, bNoCase, pStepperRE); } else if (sIdentifier == "insert") { BNFInsert* pInsert = new BNFInsert(this, &block); if (requiresParsingInformation()) pInsert->setParsingInformation(getFilenamePtr(), script); block.add(pInsert); script.skipEmpty(); if (!script.isEqualTo('(')) throw UtlException(script, "'(' expected after '#insert' to pass the array"); pInsert->setVariable(parseVariableExpression(block, script)); if (!script.isEqualTo(')')) throw UtlException(script, "')' expected after passing the array to '#insert'"); parseBNFSequence(script, rule, *pInsert, bContinue, bNoCase, pStepperRE); } else if (sIdentifier == "readChar") { BNFReadChar* pReadChar = new BNFReadChar(this, &block, bContinue); if (requiresParsingInformation()) pReadChar->setParsingInformation(getFilenamePtr(), script); block.add(pReadChar); std::vector listOfConstants; bool bConcat; ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly); pReadChar->setVariableToAssign(pVarToAssign, bConcat, rule); if (!listOfConstants.empty()) pReadChar->setConstantsToMatch(listOfConstants); } else if (sIdentifier == "readByte") { BNFReadByte* pReadByte = new BNFReadByte(this, &block, bContinue); if (requiresParsingInformation()) pReadByte->setParsingInformation(getFilenamePtr(), script); block.add(pReadByte); std::vector listOfConstants; bool bConcat; ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly); pReadByte->setVariableToAssign(pVarToAssign, bConcat, rule); if (!listOfConstants.empty()) pReadByte->setConstantsToMatch(listOfConstants); } else if (sIdentifier == "readAdaString") { BNFReadAdaString* pReadAdaString = new BNFReadAdaString(this, &block, bContinue, bNoCase); if (requiresParsingInformation()) pReadAdaString->setParsingInformation(getFilenamePtr(), script); block.add(pReadAdaString); std::vector listOfConstants; bool bConcat; ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly); pReadAdaString->setVariableToAssign(pVarToAssign, bConcat, rule); if (!listOfConstants.empty()) pReadAdaString->setConstantsToMatch(listOfConstants); } else if (sIdentifier == "readCString") { BNFReadCString* pReadCString = new BNFReadCString(this, &block, bContinue, bNoCase); if (requiresParsingInformation()) pReadCString->setParsingInformation(getFilenamePtr(), script); block.add(pReadCString); std::vector listOfConstants; bool bConcat; ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly); pReadCString->setVariableToAssign(pVarToAssign, bConcat, rule); if (!listOfConstants.empty()) pReadCString->setConstantsToMatch(listOfConstants); } else if (sIdentifier == "readCChar") { BNFReadCChar* pReadCChar = new BNFReadCChar(this, &block, bContinue, bNoCase); if (requiresParsingInformation()) pReadCChar->setParsingInformation(getFilenamePtr(), script); block.add(pReadCChar); std::vector listOfConstants; bool bConcat; ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly); pReadCChar->setVariableToAssign(pVarToAssign, bConcat, rule); if (!listOfConstants.empty()) pReadCChar->setConstantsToMatch(listOfConstants); } else if (sIdentifier == "readPythonString") { BNFReadPythonString* pReadPythonString = new BNFReadPythonString(this, &block, bContinue, bNoCase); if (requiresParsingInformation()) pReadPythonString->setParsingInformation(getFilenamePtr(), script); block.add(pReadPythonString); std::vector listOfConstants; bool bConcat; ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly); pReadPythonString->setVariableToAssign(pVarToAssign, bConcat, rule); if (!listOfConstants.empty()) pReadPythonString->setConstantsToMatch(listOfConstants); } else if (sIdentifier == "readIdentifier") { BNFReadIdentifier* pReadIdentifier = new BNFReadIdentifier(this, &block, bContinue, bNoCase); if (requiresParsingInformation()) pReadIdentifier->setParsingInformation(getFilenamePtr(), script); block.add(pReadIdentifier); std::vector listOfConstants; bool bConcat; ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly); pReadIdentifier->setVariableToAssign(pVarToAssign, bConcat, rule); if (!listOfConstants.empty()) pReadIdentifier->setConstantsToMatch(listOfConstants); } else if (sIdentifier == "readCompleteIdentifier") { BNFReadCompleteIdentifier* pReadCompleteIdentifier = new BNFReadCompleteIdentifier(this, &block, bContinue, bNoCase); if (requiresParsingInformation()) pReadCompleteIdentifier->setParsingInformation(getFilenamePtr(), script); block.add(pReadCompleteIdentifier); std::vector listOfConstants; bool bConcat; ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly); pReadCompleteIdentifier->setVariableToAssign(pVarToAssign, bConcat, rule); if (!listOfConstants.empty()) pReadCompleteIdentifier->setConstantsToMatch(listOfConstants); } else if (sIdentifier == "readInteger") { BNFReadInteger* pReadInteger = new BNFReadInteger(this, &block, bContinue, bNoCase); if (requiresParsingInformation()) pReadInteger->setParsingInformation(getFilenamePtr(), script); block.add(pReadInteger); std::vector listOfConstants; bool bConcat; ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly); pReadInteger->setVariableToAssign(pVarToAssign, bConcat, rule); if (!listOfConstants.empty()) pReadInteger->setConstantsToMatch(listOfConstants); } else if (sIdentifier == "readNumeric") { BNFReadNumeric* pReadNumeric = new BNFReadNumeric(this, &block, bContinue, bNoCase); if (requiresParsingInformation()) pReadNumeric->setParsingInformation(getFilenamePtr(), script); block.add(pReadNumeric); std::vector listOfConstants; bool bConcat; ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly); pReadNumeric->setVariableToAssign(pVarToAssign, bConcat, rule); if (!listOfConstants.empty()) pReadNumeric->setConstantsToMatch(listOfConstants); } else if (sIdentifier == "readText") { BNFReadText* pReadText = new BNFReadText(this, &block, bContinue, bNoCase); if (requiresParsingInformation()) pReadText->setParsingInformation(getFilenamePtr(), script); block.add(pReadText); script.skipEmpty(); if (!script.isEqualTo('(')) throw UtlException(script, "'(' expected by clause '#readText'"); pReadText->setText(parseExpression(block, script)); if (!script.isEqualTo(')')) throw UtlException(script, "')' expected by clause '#readText'"); std::vector listOfConstants; bool bConcat; ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly); pReadText->setVariableToAssign(pVarToAssign, bConcat, rule); if (!listOfConstants.empty()) pReadText->setConstantsToMatch(listOfConstants); } else if (sIdentifier == "readBytes") { BNFReadBytes* pReadBytes = new BNFReadBytes(this, &block, bContinue, bNoCase); if (requiresParsingInformation()) pReadBytes->setParsingInformation(getFilenamePtr(), script); block.add(pReadBytes); script.skipEmpty(); if (!script.isEqualTo('(')) throw UtlException(script, "'(' expected by clause '#readBytes'"); pReadBytes->setLength(parseExpression(block, script)); if (!script.isEqualTo(')')) throw UtlException(script, "')' expected by clause '#readBytes'"); std::vector listOfConstants; bool bConcat; ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly); pReadBytes->setVariableToAssign(pVarToAssign, bConcat, rule); if (!listOfConstants.empty()) pReadBytes->setConstantsToMatch(listOfConstants); } else if (sIdentifier == "readChars") { BNFReadChars* pReadChars = new BNFReadChars(this, &block, bContinue, bNoCase); if (requiresParsingInformation()) pReadChars->setParsingInformation(getFilenamePtr(), script); block.add(pReadChars); script.skipEmpty(); if (!script.isEqualTo('(')) throw UtlException(script, "'(' expected by clause '#readChars'"); pReadChars->setLength(parseExpression(block, script)); if (!script.isEqualTo(')')) throw UtlException(script, "')' expected by clause '#readChars'"); std::vector listOfConstants; bool bConcat; ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly); pReadChars->setVariableToAssign(pVarToAssign, bConcat, rule); if (!listOfConstants.empty()) pReadChars->setConstantsToMatch(listOfConstants); } else if (sIdentifier == "readUptoIgnore") { BNFClause* pIgnoreClause = NULL; IGNORE_MODE eMode; script.skipEmpty(); if (script.peekChar() == '(') { eMode = parseIgnoreMode(script, pIgnoreClause); } else { eMode = UNDEFINED_IGNORE; } BNFReadUptoIgnore* pReadUptoIgnore = new BNFReadUptoIgnore(this, &block, eMode, pIgnoreClause, bContinue); if (requiresParsingInformation()) pReadUptoIgnore->setParsingInformation(getFilenamePtr(), script); block.add(pReadUptoIgnore); script.skipEmpty(); std::vector listOfConstants; bool bConcat; ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly); pReadUptoIgnore->setVariableToAssign(pVarToAssign, bConcat, rule); if (!listOfConstants.empty()) pReadUptoIgnore->setConstantsToMatch(listOfConstants); } else if (sIdentifier == "skipIgnore") { BNFClause* pIgnoreClause = NULL; IGNORE_MODE eMode; script.skipEmpty(); if (script.peekChar() == '(') { eMode = parseIgnoreMode(script, pIgnoreClause); } else { eMode = UNDEFINED_IGNORE; } BNFSkipIgnore* pSkipIgnore = new BNFSkipIgnore(this, &block, eMode, pIgnoreClause, bContinue); if (requiresParsingInformation()) pSkipIgnore->setParsingInformation(getFilenamePtr(), script); block.add(pSkipIgnore); std::vector listOfConstants; bool bConcat; ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly); pSkipIgnore->setVariableToAssign(pVarToAssign, bConcat, rule); if (!listOfConstants.empty()) pSkipIgnore->setConstantsToMatch(listOfConstants); } else if (sIdentifier == "moveAhead") { BNFMoveAhead* pMoveAhead = new BNFMoveAhead(&block, bContinue); if (requiresParsingInformation()) pMoveAhead->setParsingInformation(getFilenamePtr(), script); block.add(pMoveAhead); } else if (sIdentifier == "check") { BNFCheck* pCheck = new BNFCheck(this, &block, bContinue); if (requiresParsingInformation()) pCheck->setParsingInformation(getFilenamePtr(), script); block.add(pCheck); script.skipEmpty(); if (!script.isEqualTo('(')) throw UtlException(script, "'(' expected by directive '#Check'"); pCheck->setCondition(parseExpression(block, script)); if (!script.isEqualTo(')')) throw UtlException(script, "')' expected by directive '#Check'"); } else if (sIdentifier == "super") { int iSuperClause = 0; std::string sIdentifier; for (;;) { iSuperClause++; script.skipEmpty(); if (!script.isEqualTo("::")) throw UtlException(script, "'::' expected by directive '#super'"); script.skipEmpty(); if (script.isEqualTo('#')) { script.skipEmpty(); if (!script.isEqualToIdentifier("super")) throw UtlException(script, "'::#super' expected"); } else { if (!script.readIdentifier(sIdentifier)) throw UtlException(script, "non-terminal call expected by directive '#super'"); break; } } BNFClauseCall* pClauseCall = parseBNFClauseCall(script, block, sIdentifier, bContinue, bNoCase); pClauseCall->setSuperCallDepth(iSuperClause); if (requiresParsingInformation()) pClauseCall->setParsingInformation(getFilenamePtr(), script); std::vector listOfConstants; bool bConcat; ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly); pClauseCall->setVariableToAssign(pVarToAssign, bConcat, rule); if (!listOfConstants.empty()) pClauseCall->setConstantsToMatch(listOfConstants); } else if ((sIdentifier.size() > 3) && (sIdentifier.substr(sIdentifier.size() - 3) == "AST")) { ASTCommand* pCommand = NULL; if (sIdentifier == "thisAST") pCommand = new ASTThisCommand(script); else if (sIdentifier == "valueAST") pCommand = new ASTValueCommand(script); else if (sIdentifier == "refAST") pCommand = new ASTRefCommand(script); else if (sIdentifier == "slideAST") pCommand = new ASTSlideCommand(script); else { handleUnknownTokenDirective(sIdentifier, script, rule, block, bContinue, bNoCase, bLiteralOnly, pStepperRE); } if (pCommand != NULL) { int iPos = block.getNbCommands(); parseBNFLitteral(script, rule, block, bContinue, bNoCase, bLiteralOnly, pStepperRE); if (iPos == block.getNbCommands()) { throw UtlException(script, "non-terminal call expected after an AST directive (#" + sIdentifier + " here)"); } BNFClauseCall* pNonTerminal = dynamic_cast(block.getCommand(iPos)); if (pNonTerminal == NULL) { throw UtlException(script, "non-terminal call expected after an AST directive (#" + sIdentifier + " here)"); } pNonTerminal->addASTCommand(pCommand); } } else { handleUnknownTokenDirective(sIdentifier, script, rule, block, bContinue, bNoCase, bLiteralOnly, pStepperRE); } } else if (script.isEqualTo("=>")) { _bBNFMode = false; script.skipEmpty(); if (script.isEqualTo('{')) { script.goBack(); GrfBlock* pBlock = new GrfBlock(&block); if (requiresParsingInformation()) pBlock->setParsingInformation(getFilenamePtr(), script); block.add(pBlock); if (hasTargetLanguage()) { parseAlienBlock(script, *pBlock); } else { parseBlock(script, *pBlock); } } else { if (hasTargetLanguage()) { parseAlienInstruction(script, block); } else { parseInstruction(script, block); } } _bBNFMode = true; } else { std::string sIdentifier; if (script.readIdentifier(sIdentifier)) { BNFClauseCall* pClauseCall = parseBNFClauseCall(script, block, sIdentifier, bContinue, bNoCase); if (requiresParsingInformation()) pClauseCall->setParsingInformation(getFilenamePtr(), script); std::vector listOfConstants; bool bConcat; ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly); pClauseCall->setVariableToAssign(pVarToAssign, bConcat, rule); if (!listOfConstants.empty()) pClauseCall->setConstantsToMatch(listOfConstants); } else { bSuccess = false; } } if (bSuccess && !bLiteralOnly) { // binary BNF operators script.skipEmpty(); if (script.isEqualTo("|>")) { BNFScanWindow* pScanWindow = new BNFScanWindow(this, &block, bContinue); if (requiresParsingInformation()) pScanWindow->setParsingInformation(getFilenamePtr(), script); int iIndex = block.getNbCommands() - 1; GrfCommand* pLeftMember = block.getCommand(iIndex); block.setCommand(iIndex, pScanWindow); pScanWindow->setWindow(pLeftMember); bool bNextContinue = false; bool bNextNoCase = bNoCase; parseBNFLitteral(script, rule, *pScanWindow, bNextContinue, bNextNoCase, true /* if '=>' or ':' after reading this literal, it doesn't belong to it */, NULL); } else if (script.isEqualTo("&|")) { BNFAndOrJunction* pAndOrJunction = new BNFAndOrJunction(this, &block, bContinue); if (requiresParsingInformation()) pAndOrJunction->setParsingInformation(getFilenamePtr(), script); int iIndex = block.getNbCommands() - 1; GrfCommand* pLeftMember = block.getCommand(iIndex); block.setCommand(iIndex, pAndOrJunction); pAndOrJunction->setLeftMember(pLeftMember); bool bNextContinue = false; bool bNextNoCase = bNoCase; parseBNFLitteral(script, rule, *pAndOrJunction, bNextContinue, bNextNoCase, true /* if '=>' or ':' after reading this literal, it doesn't belong to it */, NULL); } } return bSuccess; } BNFClauseCall* DtaBNFScript::parseBNFClauseCall(ScpStream& script, GrfBlock& block, const std::string& sClauseCallName, bool bContinue, bool bNoCase) { BNFClauseCall* pClauseCall = new BNFClauseCall(this, &block, bContinue, bNoCase); if (requiresParsingInformation()) pClauseCall->setParsingInformation(getFilenamePtr(), script); block.add(pClauseCall); script.skipEmpty(); if (script.isEqualTo('<')) { ExprScriptExpression* pTemplateExpression = DtaScript::parseKeyTemplateExpression(block, script); pClauseCall->setTemplateExpression(pTemplateExpression); script.skipEmpty(); if (!script.isEqualTo('>')) throw UtlException(script, "'>' expected to end the template expression of clause call '" + sClauseCallName + "'"); script.skipEmpty(); } if (script.isEqualTo('(')) { do { ExprScriptExpression* pParameterExpr = DtaScript::parseExpression(block, script); pClauseCall->addParameter(pParameterExpr); script.skipEmpty(); } while (script.isEqualTo(',')); if (!script.isEqualTo(')')) throw UtlException(script, "')' expected"); } BNFClause& myClause = buildClause(script, block, sClauseCallName, pClauseCall->getParameters().size()); pClauseCall->setClause(&myClause); return pClauseCall; } BNFMultiplicityBoundaries* DtaBNFScript::parseMultiplicity(ScpStream& script, GrfBlock& block, BNFMultiplicityBoundaries* boundaries) { BNFMultiplicityBoundaries* pResult = NULL; script.skipEmpty(); if (script.isEqualTo('*')) { if (boundaries == NULL) boundaries = new BNFMultiplicityBoundaries; pResult = boundaries; boundaries->setMultiplicity(0, -1); } else if (script.isEqualTo('+')) { if (boundaries == NULL) boundaries = new BNFMultiplicityBoundaries; pResult = boundaries; boundaries->setMultiplicity(1, -1); } else if (script.isEqualTo('?')) { if (boundaries == NULL) boundaries = new BNFMultiplicityBoundaries; pResult = boundaries; boundaries->setMultiplicity(0, 1); } else if (script.isEqualTo("#repeat")) { script.skipEmpty(); if (!script.isEqualTo('(')) throw UtlException(script, "'(' expected after '#repeat'"); script.skipEmpty(); std::auto_ptr pBegin(parseExpression(block, script)); script.skipEmpty(); if (script.isEqualTo(',')) { script.skipEmpty(); std::auto_ptr pEnd(parseExpression(block, script)); script.skipEmpty(); if (boundaries == NULL) boundaries = new BNFMultiplicityBoundaries; boundaries->setMultiplicity(pBegin.release(), pEnd.release()); } else { if (boundaries == NULL) boundaries = new BNFMultiplicityBoundaries; boundaries->setMultiplicity(pBegin.release(), NULL); } if (!script.isEqualTo(')')) { if (pResult == NULL) delete boundaries; throw UtlException(script, "')' expected to close '#repeat'"); } pResult = boundaries; } else { int iBegin; int iEnd; if (script.readInt(iBegin)) { if (iBegin < 0) throw UtlException(script, "multiplicity 'm..n' or 'm' doesn't allow negative boundaries"); script.skipEmpty(); if (script.isEqualTo("..")) { script.skipEmpty(); if (script.isEqualTo('*') || script.isEqualTo('n')) iEnd = -1; else { if (!script.readInt(iEnd)) throw UtlException(script, "multiplicity expected as 'm..n' format"); if (iEnd < iBegin) throw UtlException(script, "multiplicity 'm..n' doesn't allow 'm' being greater than 'n'"); } } else { iEnd = iBegin; } if (boundaries == NULL) boundaries = new BNFMultiplicityBoundaries; pResult = boundaries; } else { iBegin = 1; iEnd = 1; if (boundaries == NULL) boundaries = new BNFMultiplicityBoundaries; } boundaries->setMultiplicity(iBegin, iEnd); } return pResult; } bool DtaBNFScript::betweenCommands(ScpStream& script, GrfBlock& block) { return DtaScript::betweenCommands(script, block); } void DtaBNFScript::handleUnknownCommand(const std::string& sCommand, ScpStream& script, GrfBlock& block) { DtaScript::handleUnknownCommand(sCommand, script, block); } void DtaBNFScript::handleNotAWordCommand(ScpStream& script, GrfBlock& block) { DtaScript::handleNotAWordCommand(script, block); } void DtaBNFScript::handleUnknownTokenDirective(const std::string& sDirective, ScpStream& script, BNFClause& rule, GrfBlock& block, bool& bContinue, bool& bNoCase, bool bLiteralOnly, BNFStepper* pStepper) { throw UtlException(script, "unknown macro instruction '#" + sDirective + "' encountered"); } void DtaBNFScript::compileCppHeaderIncludes(CppCompilerEnvironment& theCompilerEnvironment) const { theCompilerEnvironment.getHeader() << "namespace CodeWorker {"; theCompilerEnvironment.getHeader().endl(); theCompilerEnvironment.getHeader() << "\tclass CGBNFRuntimeEnvironment;"; theCompilerEnvironment.getHeader().endl(); theCompilerEnvironment.getHeader() << "}"; theCompilerEnvironment.getHeader().endl(); DtaScript::compileCppHeaderIncludes(theCompilerEnvironment); } void DtaBNFScript::compileCppFunctions(CppCompilerEnvironment& theCompilerEnvironment) const { DtaScript::compileCppFunctions(theCompilerEnvironment); for (std::map >::const_iterator i = _listOfClauses.begin(); i != _listOfClauses.end(); i++) { for (std::list::const_iterator j = i->second.begin(); j != i->second.end(); j++) { (*j)->compileCppFunction(theCompilerEnvironment); } } } void DtaBNFScript::compileCppBNFAssignment(CppCompilerEnvironment& theCompilerEnvironment, int iClauseReturnType, ExprScriptVariable& variableToAssign, bool bConcatVariable, const char* tcText) { CW_BODY_INDENT; variableToAssign.compileCppForBNFSet(theCompilerEnvironment); if (iClauseReturnType == BNFClause::LIST_RETURN_TYPE) { CW_BODY_STREAM << ".pushItem(" << tcText << ");"; } else if (hasTargetLanguage()) { if (bConcatVariable) { CW_BODY_STREAM << " += " << tcText << ";"; } else { CW_BODY_STREAM << " = " << tcText << ";"; } } else { if (bConcatVariable) { CW_BODY_STREAM << ".concatenateValue(" << tcText << ");"; } else { CW_BODY_STREAM << ".setValue(" << tcText << ");"; } } CW_BODY_ENDL; } std::string DtaBNFScript::assignmentToString(ExprScriptVariable* pVariableToAssign, bool bConcatenateVariable) { if (pVariableToAssign != NULL) return ((bConcatenateVariable) ? ":+" : ":") + pVariableToAssign->toString(); return ""; } std::string DtaBNFScript::constantsToString(const std::vector& listOfConstants) { std::string sText; if (listOfConstants.size() == 1) { sText = ":\"" + CGRuntime::composeCLikeString(listOfConstants[0]) + "\""; } else if (!listOfConstants.empty()) { sText = ":{"; for (std::vector::const_iterator i = listOfConstants.begin(); i != listOfConstants.end(); ++i) { if (i != listOfConstants.begin()) sText += ", "; sText += "\"" + CGRuntime::composeCLikeString(*i) + "\""; } sText += "}"; } return sText; } IGNORE_MODE DtaBNFScript::parseIgnoreMode(ScpStream& script, BNFClause*& pPreprocessingIgnoreClause) { IGNORE_MODE eMode; pPreprocessingIgnoreClause = NULL; script.skipEmpty(); if (script.isEqualTo('(')) { script.skipEmpty(); if (script.isEqualTo("C++/Doxygen")) eMode = IGNORE_CPP_EXCEPT_DOXYGEN; else if (script.isEqualTo("C++")) eMode = IGNORE_CPP; else if (script.isEqualTo("JAVA")) eMode = IGNORE_JAVA; else if (script.isEqualTo("HTML") || script.isEqualTo("XML")) eMode = IGNORE_HTML; else if (script.isEqualTo("blanks")) eMode = IGNORE_BLANKS; else if (script.isEqualTo("Ada")) eMode = IGNORE_ADA; else if (script.isEqualTo("LaTeX")) eMode = IGNORE_LATEX; else { eMode = IGNORE_CLAUSE; std::string sKey; script.readPythonString(sKey); if (sKey.empty()) sKey = "#empty"; else sKey = "#ignore[" + sKey + "]"; if (_mapOfIgnoreClauses.find(sKey) == _mapOfIgnoreClauses.end()) { throw UtlException(script, "the ignore clause '" + sKey + "' doesn't exist"); } pPreprocessingIgnoreClause = _mapOfIgnoreClauses[sKey]; } script.skipEmpty(); if (!script.isEqualTo(')')) throw UtlException(script, "')' or correct mode expected by clause '#ignore'"); } else { eMode = IGNORE_CLAUSE; if (_mapOfIgnoreClauses.find("#ignore") == _mapOfIgnoreClauses.end()) { throw UtlException(script, "the ignore clause '#ignore' doesn't exist"); } pPreprocessingIgnoreClause = _mapOfIgnoreClauses["#ignore"]; } return eMode; } //##markup##"parsing" //##begin##"parsing" void DtaBNFScript::parseAttachInputToSocket(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) { GrfAttachInputToSocket* pAttachInputToSocket = new GrfAttachInputToSocket; if (requiresParsingInformation()) pAttachInputToSocket->setParsingInformation(getFilenamePtr(), script); block.add(pAttachInputToSocket); script.skipEmpty(); if (!script.isEqualTo('(')) throw UtlException(script, "syntax error: '(' expected"); script.skipEmpty(); if (pMethodCaller == NULL) pAttachInputToSocket->setSocket(parseExpression(block, script)); else pAttachInputToSocket->setSocket(pMethodCaller); if (!script.isEqualTo(')')) throw UtlException(script, "syntax error: ')' expected"); script.skipEmpty(); if (!script.isEqualTo(';')) throw UtlException(script, "syntax error: ';' expected"); } void DtaBNFScript::parseDetachInputFromSocket(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) { GrfDetachInputFromSocket* pDetachInputFromSocket = new GrfDetachInputFromSocket; if (requiresParsingInformation()) pDetachInputFromSocket->setParsingInformation(getFilenamePtr(), script); block.add(pDetachInputFromSocket); script.skipEmpty(); if (!script.isEqualTo('(')) throw UtlException(script, "syntax error: '(' expected"); script.skipEmpty(); if (pMethodCaller == NULL) pDetachInputFromSocket->setSocket(parseExpression(block, script)); else pDetachInputFromSocket->setSocket(pMethodCaller); if (!script.isEqualTo(')')) throw UtlException(script, "syntax error: ')' expected"); script.skipEmpty(); if (!script.isEqualTo(';')) throw UtlException(script, "syntax error: ';' expected"); } void DtaBNFScript::parseGoBack(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) { GrfGoBack* pGoBack = new GrfGoBack; if (requiresParsingInformation()) pGoBack->setParsingInformation(getFilenamePtr(), script); block.add(pGoBack); script.skipEmpty(); if (!script.isEqualTo('(')) throw UtlException(script, "syntax error: '(' expected"); script.skipEmpty(); if (!script.isEqualTo(')')) throw UtlException(script, "syntax error: ')' expected"); script.skipEmpty(); if (!script.isEqualTo(';')) throw UtlException(script, "syntax error: ';' expected"); } void DtaBNFScript::parseSetInputLocation(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) { GrfSetInputLocation* pSetInputLocation = new GrfSetInputLocation; if (requiresParsingInformation()) pSetInputLocation->setParsingInformation(getFilenamePtr(), script); block.add(pSetInputLocation); script.skipEmpty(); if (!script.isEqualTo('(')) throw UtlException(script, "syntax error: '(' expected"); script.skipEmpty(); if (pMethodCaller == NULL) pSetInputLocation->setLocation(parseExpression(block, script)); else pSetInputLocation->setLocation(pMethodCaller); if (!script.isEqualTo(')')) throw UtlException(script, "syntax error: ')' expected"); script.skipEmpty(); if (!script.isEqualTo(';')) throw UtlException(script, "syntax error: ';' expected"); } void DtaBNFScript::parseAllFloatingLocations(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) { DtaScript::parseAllFloatingLocations(block, script, pMethodCaller); } void DtaBNFScript::parseAttachOutputToSocket(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) { DtaScript::parseAttachOutputToSocket(block, script, pMethodCaller); } void DtaBNFScript::parseDetachOutputFromSocket(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) { DtaScript::parseDetachOutputFromSocket(block, script, pMethodCaller); } void DtaBNFScript::parseIncrementIndentLevel(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) { DtaScript::parseIncrementIndentLevel(block, script, pMethodCaller); } void DtaBNFScript::parseInsertText(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) { DtaScript::parseInsertText(block, script, pMethodCaller); } void DtaBNFScript::parseInsertTextOnce(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) { DtaScript::parseInsertTextOnce(block, script, pMethodCaller); } void DtaBNFScript::parseInsertTextToFloatingLocation(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) { DtaScript::parseInsertTextToFloatingLocation(block, script, pMethodCaller); } void DtaBNFScript::parseInsertTextOnceToFloatingLocation(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) { DtaScript::parseInsertTextOnceToFloatingLocation(block, script, pMethodCaller); } void DtaBNFScript::parseOverwritePortion(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) { DtaScript::parseOverwritePortion(block, script, pMethodCaller); } void DtaBNFScript::parsePopulateProtectedArea(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) { DtaScript::parsePopulateProtectedArea(block, script, pMethodCaller); } void DtaBNFScript::parseResizeOutputStream(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) { DtaScript::parseResizeOutputStream(block, script, pMethodCaller); } void DtaBNFScript::parseSetFloatingLocation(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) { DtaScript::parseSetFloatingLocation(block, script, pMethodCaller); } void DtaBNFScript::parseSetOutputLocation(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) { DtaScript::parseSetOutputLocation(block, script, pMethodCaller); } void DtaBNFScript::parseSetProtectedArea(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) { DtaScript::parseSetProtectedArea(block, script, pMethodCaller); } void DtaBNFScript::parseWriteBytes(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) { DtaScript::parseWriteBytes(block, script, pMethodCaller); } void DtaBNFScript::parseWriteText(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) { DtaScript::parseWriteText(block, script, pMethodCaller); } void DtaBNFScript::parseWriteTextOnce(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) { DtaScript::parseWriteTextOnce(block, script, pMethodCaller); } //##end##"parsing" }