1 /* "CodeWorker": a scripting language for parsing and generating text. 2 3 Copyright (C) 1996-1997, 1999-2002 C�dric Lemaire 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with this library; if not, write to the Free Software 17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 19 To contact the author: codeworker@free.fr 20 */ 21 22 #ifdef WIN32 23 #pragma warning (disable : 4786) 24 #endif 25 26 #include "UtlException.h" 27 #include "ScpStream.h" 28 #include "CppCompilerEnvironment.h" 29 #include "CGRuntime.h" 30 31 #include "DtaScriptVariable.h" 32 #include "ExprScriptVariable.h" 33 #include "DtaBNFScript.h" 34 #include "BNFClause.h" 35 #include "DtaVisitor.h" 36 #include "BNFString.h" 37 38 namespace CodeWorker { BNFString(DtaBNFScript * pBNFScript,GrfBlock * pParent,const std::string & sText,bool bContinue,bool bNoCase)39 BNFString::BNFString(DtaBNFScript* pBNFScript, GrfBlock* pParent, const std::string& sText, bool bContinue, bool bNoCase) : _pBNFScript(pBNFScript), GrfCommand(pParent), _pVariableToAssign(NULL), _bContinue(bContinue), _iClauseReturnType(BNFClause::NO_RETURN_TYPE), _bNoCase(bNoCase) { 40 if (_bNoCase) { 41 _bNoCase = false; 42 for (std::string::size_type i = 0; i < sText.size(); i++) { 43 char a = sText[i]; 44 if ((a >= 'A') && (a <= 'Z')) { 45 a += ' '; 46 _bNoCase = true; 47 } else if (!_bNoCase && (a >= 'a') && (a <= 'z')) _bNoCase = true; 48 _sText += a; 49 } 50 } else { 51 _sText = sText; 52 } 53 } 54 ~BNFString()55 BNFString::~BNFString() { 56 delete _pVariableToAssign; 57 } 58 accept(DtaVisitor & visitor,DtaVisitorEnvironment & env)59 void BNFString::accept(DtaVisitor& visitor, DtaVisitorEnvironment& env) { 60 visitor.visitBNFString(*this, env); 61 } 62 isABNFCommand() const63 bool BNFString::isABNFCommand() const { return true; } 64 setVariableToAssign(ExprScriptVariable * pVariableToAssign,bool bConcat,BNFClause & theClause)65 void BNFString::setVariableToAssign(ExprScriptVariable* pVariableToAssign, bool bConcat, BNFClause& theClause) { 66 if (pVariableToAssign != NULL) { 67 _pVariableToAssign = pVariableToAssign; 68 std::string sVariableName = _pVariableToAssign->toString(); 69 if (sVariableName == theClause.getName()) _iClauseReturnType = theClause.getReturnType(); 70 _bConcatVariable = bConcat; 71 } 72 } 73 executeInternal(DtaScriptVariable & visibility)74 SEQUENCE_INTERRUPTION_LIST BNFString::executeInternal(DtaScriptVariable& visibility) { 75 bool bSuccess; 76 int iLocation = CGRuntime::getInputLocation(); 77 int iImplicitCopyPosition = _pBNFScript->skipEmptyChars(visibility); 78 if (_bNoCase) bSuccess = CGRuntime::readIfEqualToIgnoreCase(_sText); 79 else bSuccess = CGRuntime::readIfEqualTo(_sText); 80 if (!bSuccess) { 81 BNF_SYMBOL_HAS_FAILED 82 } 83 if (_pVariableToAssign != NULL) { 84 DtaScriptVariable* pVariable = visibility.getVariable(*_pVariableToAssign); 85 if (_iClauseReturnType == BNFClause::LIST_RETURN_TYPE) { 86 pVariable->pushItem(_sText); 87 } else { 88 if (_bConcatVariable) pVariable->concatValue(_sText.c_str()); 89 else pVariable->setValue(_sText.c_str()); 90 } 91 } 92 if (iImplicitCopyPosition >= 0) _pBNFScript->writeBinaryData(_sText.c_str(), _sText.size()); 93 return NO_INTERRUPTION; 94 } 95 compileCpp(CppCompilerEnvironment & theCompilerEnvironment) const96 void BNFString::compileCpp(CppCompilerEnvironment& theCompilerEnvironment) const { 97 CW_BODY_INDENT << "// " << toString(); 98 CW_BODY_ENDL; 99 int iCursor = theCompilerEnvironment.newCursor(); 100 CW_BODY_INDENT << "int _compilerClauseLocation_" << iCursor << " = CGRuntime::getInputLocation();"; 101 CW_BODY_ENDL; 102 CW_BODY_INDENT << "int _compilerClauseImplicitCopy_" << iCursor << " = theEnvironment.skipEmptyChars();"; 103 CW_BODY_ENDL; 104 CW_BODY_INDENT << "_compilerClauseSuccess = CGRuntime::readIfEqualTo"; 105 if (_bNoCase) CW_BODY_STREAM << "IgnoreCase"; 106 CW_BODY_STREAM << "("; 107 CW_BODY_STREAM.writeString(_sText); 108 CW_BODY_STREAM << ");"; 109 CW_BODY_ENDL; 110 if (_pVariableToAssign != NULL) { 111 CW_BODY_INDENT << "if (_compilerClauseSuccess) {";CW_BODY_ENDL; 112 theCompilerEnvironment.incrementIndentation(); 113 std::string sText = "\"" + CGRuntime::composeCLikeString(_sText) + "\""; 114 _pBNFScript->compileCppBNFAssignment(theCompilerEnvironment, _iClauseReturnType, *_pVariableToAssign, _bConcatVariable, sText.c_str()); 115 theCompilerEnvironment.decrementIndentation(); 116 CW_BODY_INDENT << "}";CW_BODY_ENDL; 117 } 118 CW_BODY_INDENT << "if (!_compilerClauseSuccess) {";CW_BODY_ENDL; 119 if (_bContinue) { 120 CW_BODY_INDENT << "\tCGRuntime::throwBNFExecutionError("; 121 CW_BODY_STREAM.writeString(toString()); 122 CW_BODY_STREAM << ");"; 123 } else { 124 CW_BODY_INDENT << "\tCGRuntime::setInputLocation(_compilerClauseLocation_" << iCursor << ");"; 125 CW_BODY_ENDL; 126 CW_BODY_INDENT << "\tif (_compilerClauseImplicitCopy_" << iCursor << " >= 0) CGRuntime::resizeOutputStream(_compilerClauseImplicitCopy_" << iCursor << ");"; 127 } 128 CW_BODY_ENDL; 129 CW_BODY_INDENT << "} else if (_compilerClauseImplicitCopy_" << iCursor << " >= 0) CGRuntime::writeBinaryData("; 130 CW_BODY_STREAM.writeString(_sText); 131 CW_BODY_STREAM << ", " << (int) _sText.size() << ");"; 132 CW_BODY_ENDL; 133 } 134 toString() const135 std::string BNFString::toString() const { 136 std::string sText = "\"" + _sText + "\"" + DtaBNFScript::assignmentToString(_pVariableToAssign, _bConcatVariable); 137 if (_bContinue) sText = "#continue " + sText; 138 return sText; 139 } 140 } 141