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