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 "ScpStream.h"
27 #include "CppCompilerEnvironment.h"
28 #include "CGRuntime.h"
29 
30 #include "DtaScriptVariable.h"
31 #include "ExprScriptVariable.h"
32 #include "DtaBNFScript.h"
33 #include "DtaVisitor.h"
34 #include "BNFPushItem.h"
35 
36 namespace CodeWorker {
37 
BNFPushItem(DtaBNFScript * pBNFScript,GrfBlock * pParent)38 	BNFPushItem::BNFPushItem(DtaBNFScript* pBNFScript, GrfBlock* pParent) : _pBNFScript(pBNFScript), GrfBlock(pParent), _pVariable(NULL) {}
39 
~BNFPushItem()40 	BNFPushItem::~BNFPushItem() {
41 	}
42 
accept(DtaVisitor & visitor,DtaVisitorEnvironment & env)43 	void BNFPushItem::accept(DtaVisitor& visitor, DtaVisitorEnvironment& env) {
44 		visitor.visitBNFPushItem(*this, env);
45 	}
46 
isABNFCommand() const47 	bool BNFPushItem::isABNFCommand() const { return true; }
48 
execute(DtaScriptVariable & visibility)49 	SEQUENCE_INTERRUPTION_LIST BNFPushItem::execute(DtaScriptVariable& visibility) {
50 		SEQUENCE_INTERRUPTION_LIST result;
51 		DtaScriptVariable* pVariable = visibility.getExistingVariable(*_pVariable);
52 		bool bCreation = (pVariable == NULL);
53 		if (bCreation) {
54 			pVariable = visibility.getVariable(*_pVariable);
55 			if (pVariable->isLocal()) CGRuntime::throwBNFExecutionError("declare the local variable '" + _pVariable->toString() + "' before calling '#pushItem'");
56 		}
57 		pVariable->pushItem("");
58 		int iCursor = CGRuntime::getInputLocation();
59 		int iImplicitCopyPosition = ((_pBNFScript->implicitCopy()) ? CGRuntime::getOutputLocation() : -1);
60 		result = GrfBlock::executeInternal(visibility);
61 		if (result != NO_INTERRUPTION) {
62 			if (bCreation && !pVariable->isLocal()) CGRuntime::removeVariable(pVariable);
63 			else CGRuntime::removeLastElement(pVariable);
64 			CGRuntime::setInputLocation(iCursor);
65 			if (iImplicitCopyPosition >= 0) CGRuntime::resizeOutputStream(iImplicitCopyPosition);
66 		}
67 		return result;
68 	}
69 
compileCpp(CppCompilerEnvironment & theCompilerEnvironment) const70 	void BNFPushItem::compileCpp(CppCompilerEnvironment& theCompilerEnvironment) const {
71 		std::vector<GrfCommand*>::const_iterator i = getCommands().begin();
72 		if (i != getCommands().end()) {
73 			CW_BODY_INDENT << "// " << toString();
74 			CW_BODY_ENDL;
75 			int iCursor = theCompilerEnvironment.newCursor();
76 			CW_BODY_INDENT << "int _compilerClauseCursor_" << iCursor << " = CGRuntime::getInputLocation();";
77 			CW_BODY_ENDL;
78 			CW_BODY_INDENT << "bool _compilerClauseCreation_" << iCursor << " = CGRuntime::existVariable(";
79 			_pVariable->compileCpp(theCompilerEnvironment);
80 			CW_BODY_STREAM << ");";
81 			CW_BODY_ENDL;
82 			CW_BODY_INDENT;
83 			_pVariable->compileCppForSet(theCompilerEnvironment);
84 			CW_BODY_STREAM << ".pushItem(\"\");";CW_BODY_ENDL;
85 			CW_BODY_INDENT << "if (_compilerClauseCreation_" << iCursor << " && ";
86 			_pVariable->compileCpp(theCompilerEnvironment);
87 			CW_BODY_STREAM << ".isLocal()) CGRuntime::throwBNFExecutionError(\"declare the local variable '" << _pVariable->toString() << "' before calling '#pushItem'\");";CW_BODY_ENDL;
88 			GrfBlock::compileCppBNFSequence(theCompilerEnvironment);
89 			CW_BODY_INDENT << "if (!_compilerClauseSuccess) {";CW_BODY_ENDL;
90 			CW_BODY_INDENT << "\tif (!_compilerClauseCreation_" << iCursor << ") CGRuntime::removeVariable(";
91 			_pVariable->compileCpp(theCompilerEnvironment);
92 			CW_BODY_STREAM << ");";CW_BODY_ENDL;
93 			CW_BODY_INDENT << "\telse CGRuntime::removeLastElement(";
94 			_pVariable->compileCpp(theCompilerEnvironment);
95 			CW_BODY_STREAM << ");";CW_BODY_ENDL;
96 			CW_BODY_INDENT << "\tCGRuntime::setInputLocation(_compilerClauseCursor_" << iCursor << ");";CW_BODY_ENDL;
97 			CW_BODY_INDENT << "}";CW_BODY_ENDL;
98 		}
99 	}
100 
toString() const101 	std::string BNFPushItem::toString() const {
102 		std::string sText = "#pushItem(" + _pVariable->toString() + ")";
103 		for (std::vector<GrfCommand*>::const_iterator i = getCommands().begin(); i != getCommands().end(); i++) {
104 			if ((*i)->isABNFCommand()) {
105 				if (i != getCommands().begin()) sText += " ";
106 				sText += (*i)->toString();
107 			}
108 		}
109 		return sText;
110 	}
111 
112 }
113