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 <stdlib.h>
27 
28 #include "UtlException.h"
29 #include "ScpStream.h"
30 #include "CppCompilerEnvironment.h"
31 #include "CGRuntime.h"
32 
33 #include "ExprScriptVariable.h"
34 #include "DtaScriptVariable.h"
35 #include "DtaProject.h"
36 #include "DtaClass.h"
37 #include "BNFDisjunction.h"
38 #include "BNFConjunction.h"
39 #include "BNFString.h"
40 #include "BNFEndOfFile.h"
41 #include "BNFEndOfLine.h"
42 #include "BNFNextStep.h"
43 #include "BNFScanWindow.h"
44 #include "BNFAndOrJunction.h"
45 #include "BNFBreak.h"
46 #include "BNFComplementary.h"
47 #include "BNFFindToken.h"
48 #include "BNFNot.h"
49 #include "BNFCharLitteral.h"
50 #include "BNFCharBoundaries.h"
51 #include "BNFPushItem.h"
52 #include "BNFInsert.h"
53 #include "BNFReadChar.h"
54 #include "BNFReadByte.h"
55 #include "BNFReadAdaString.h"
56 #include "BNFReadCString.h"
57 #include "BNFReadCChar.h"
58 #include "BNFReadIdentifier.h"
59 #include "BNFReadCompleteIdentifier.h"
60 #include "BNFReadInteger.h"
61 #include "BNFReadNumeric.h"
62 #include "BNFReadPythonString.h"
63 #include "BNFReadText.h"
64 #include "BNFReadBytes.h"
65 #include "BNFReadChars.h"
66 #include "BNFCheck.h"
67 #include "BNFForeach.h"
68 #include "BNFClauseCall.h"
69 #include "BNFMultiplicity.h"
70 #include "BNFClause.h"
71 #include "BNFRatchet.h"
72 #include "BNFTryCatch.h"
73 #include "BNFStepintoHook.h"
74 #include "BNFStepoutHook.h"
75 //##markup##"includes"
76 //##begin##"includes"
77 #include "GrfAttachInputToSocket.h"
78 #include "GrfDetachInputFromSocket.h"
79 #include "GrfGoBack.h"
80 #include "GrfSetInputLocation.h"
81 //##end##"includes"
82 #include "DtaASTNavigator.h"
83 #include "ASTCommand.h"
84 #include "GrfParsedFile.h"
85 #include "GrfParsedString.h"
86 #include "GrfGeneratedFile.h"
87 #include "GrfGeneratedString.h"
88 #include "GrfAppendedFile.h"
89 #include "GrfDebugExecution.h"
90 #include "DtaBNFScript.h"
91 
92 #include "DtaTranslateScript.h"
93 #include "BNFIgnore.h"
94 #include "BNFSkipIgnore.h"
95 #include "BNFMoveAhead.h"
96 #include "BNFReadUptoIgnore.h"
97 
98 
99 namespace CodeWorker {
100 	class BNFDisengageIgnore {
101 	private:
102 		DtaBNFScript* _pBNFScript;
103 
104 	public:
BNFDisengageIgnore(DtaBNFScript * pBNFScript)105 		BNFDisengageIgnore(DtaBNFScript* pBNFScript) : _pBNFScript(pBNFScript) {
106 			pBNFScript->setIgnoreMode(NOT_IGNORE);
107 		}
108 
~BNFDisengageIgnore()109 		~BNFDisengageIgnore() {
110 			_pBNFScript->setIgnoreMode(IGNORE_CLAUSE);
111 		}
112 	};
113 
114 
115 	class BNFTransformRules {
116 		private:
117 			ExprScriptExpression* _pFilter;
118 			DtaTranslateScript* _pPrototypeScript;
119 			DtaTranslateScript* _pProductionRuleScript;
120 
121 		public:
BNFTransformRules()122 			inline BNFTransformRules() : _pFilter(NULL), _pPrototypeScript(NULL), _pProductionRuleScript(NULL) {}
~BNFTransformRules()123 			~BNFTransformRules() {
124 				delete _pFilter;
125 				delete _pPrototypeScript;
126 				delete _pProductionRuleScript;
127 			}
128 
getFilter() const129 			inline ExprScriptExpression* getFilter() const { return _pFilter; }
setFilter(ExprScriptExpression * pFilter)130 			inline void setFilter(ExprScriptExpression* pFilter) { _pFilter = pFilter; }
getPrototypeScript() const131 			inline DtaTranslateScript* getPrototypeScript() const { return _pPrototypeScript; }
setPrototypeScript(DtaTranslateScript * pPrototypeScript)132 			inline void setPrototypeScript(DtaTranslateScript* pPrototypeScript) { _pPrototypeScript = pPrototypeScript; }
getProductionRuleScript() const133 			inline DtaTranslateScript* getProductionRuleScript() const { return _pProductionRuleScript; }
setProductionRuleScript(DtaTranslateScript * pProductionRuleScript)134 			inline void setProductionRuleScript(DtaTranslateScript* pProductionRuleScript) { _pProductionRuleScript = pProductionRuleScript; }
135 
applyRuleTransformer(ScpStream & script,GrfBlock & block,int iStatementBeginning,int iProductionRuleBeginning,const std::string & sClauseName,const std::string & sPrototype,const std::string & sProductionRule)136 			virtual bool applyRuleTransformer(ScpStream& script, GrfBlock& block, int iStatementBeginning, int iProductionRuleBeginning, const std::string& sClauseName, const std::string& sPrototype, const std::string& sProductionRule) {
137 				DtaScriptVariable theContext;
138 				theContext.setValueAtVariable("x", sClauseName.c_str());
139 				std::string sResult = _pFilter->getValue(theContext);
140 				if (sResult.empty()) return false;
141 				if (_pPrototypeScript != NULL) {
142 					std::string sNewPrototype;
143 					_pPrototypeScript->translateString(sPrototype, sNewPrototype, DtaProject::getInstance());
144 					if (sNewPrototype != sPrototype) script.insertText(sNewPrototype, iStatementBeginning, sPrototype.size());
145 				}
146 				if (_pProductionRuleScript != NULL) {
147 					std::string sNewProductionRule;
148 					_pProductionRuleScript->translateString(sProductionRule, sNewProductionRule, DtaProject::getInstance());
149 					if (sNewProductionRule != sProductionRule) {
150 						script.insertText(sNewProductionRule, iProductionRuleBeginning, sProductionRule.size());
151 					}
152 				}
153 				return true;
154 			}
155 	};
156 
157 
158 	struct TemporaryMatchingStorage {
159 		bool bBegin;
160 		DtaScriptVariable* pClauseNode;
TemporaryMatchingStorageCodeWorker::TemporaryMatchingStorage161 		TemporaryMatchingStorage(bool b, DtaScriptVariable* p) : bBegin(b), pClauseNode(p) {}
162 	};
163 
164 
DtaBNFScript()165 	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) {
166 	}
167 
DtaBNFScript(GrfBlock * pParentBlock)168 	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) {
169 	}
170 
DtaBNFScript(EXECUTE_FUNCTION * executeFunction)171 	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) {
172 	}
173 
~DtaBNFScript()174 	DtaBNFScript::~DtaBNFScript() {
175 		delete _pImplicitCopyFunction;
176 		for (std::map<std::string, std::list<BNFClause*> >::const_iterator i = _listOfClauses.begin(); i != _listOfClauses.end(); i++) {
177 	//		for (std::list<BNFClause*>::const_iterator j = i->second.begin(); j != i->second.end(); j++) delete *j;
178 		}
179 		for (std::list<BNFTransformRules*>::const_iterator j = _listOfTransformRules.begin(); j != _listOfTransformRules.end(); ++j) {
180 			delete *j;
181 		}
182 		delete _pStepintoHook;
183 		delete _pStepoutHook;
184 		delete _pMatchingAreasContainer;
185 		delete _pASTContainer;
186 		delete _pParentClauseMatching;
187 	}
188 
getType() const189 	DtaScriptFactory::SCRIPT_TYPE DtaBNFScript::getType() const { return DtaScriptFactory::BNF_SCRIPT; }
isAParseScript() const190 	bool DtaBNFScript::isAParseScript() const { return true; }
isAGenerateScript() const191 	bool DtaBNFScript::isAGenerateScript() const { return false; }
192 
traceEngine() const193 	void DtaBNFScript::traceEngine() const {
194 		if (getFilenamePtr() == NULL) CGRuntime::traceLine("Extended-BNF script (no filename):");
195 		else CGRuntime::traceLine("Extended-BNF script \"" + std::string(getFilenamePtr()) + "\":");
196 		traceInternalEngine();
197 	}
198 
traceInternalEngine() const199 	void DtaBNFScript::traceInternalEngine() const {
200 		char tcMessage[80];
201 		sprintf(tcMessage, "\tNumber of production rules = %d", _listOfClauses.size());
202 		CGRuntime::traceLine(tcMessage);
203 		if (_eIgnoreMode == NOT_IGNORE) CGRuntime::traceLine("\tignore insignificant chars = OFF");
204 		else if (_pIgnoreClause == NULL) CGRuntime::traceLine("\tignore insignificant chars = " + IGNORE_MODEtoString(_eIgnoreMode));
205 		else CGRuntime::traceLine("\tignore insignificant chars = clause '#ignore'");
206 		if (_bNoCase) CGRuntime::traceLine("\tignore case = ON");
207 
208 		if (!_mapOfIgnoreClauses.empty()) {
209 			CGRuntime::traceText("\tignore clauses: ");
210 			for (std::map<std::string, BNFClause*>::const_iterator i = _mapOfIgnoreClauses.begin(); i != _mapOfIgnoreClauses.end(); ++i) {
211 				if (i != _mapOfIgnoreClauses.begin()) CGRuntime::traceText(", ");
212 				CGRuntime::traceText(i->first);
213 			}
214 			CGRuntime::traceLine("");
215 		}
216 
217 		if (_bTrace) CGRuntime::traceLine("\ttrace = ON");
218 		if (_bImplicitCopy) CGRuntime::traceLine("\timplicitCopy = ON");
219 		if (_pImplicitCopyFunction != NULL) {
220 			CGRuntime::traceLine("\timplicitCopy function = " + _pImplicitCopyFunction->toString());
221 		}
222 		DtaScript::traceInternalEngine();
223 	}
224 
getAlienParser() const225 	DtaBNFScript& DtaBNFScript::getAlienParser() const {
226 		DtaBNFScript* pScript = DtaProject::getInstance().getBNFAlienParser();
227 		if (pScript == NULL) throw UtlException("compiling a BNF script in " + _sTargetLanguage + " requires \"($CODEWORKER_HOME)/" + _sTargetLanguage + "/default-scripts/" + _sTargetLanguage + "BNFScript.cwp\"");
228 		return *pScript;
229 	}
230 
skipEmptyChars(DtaScriptVariable & visibility)231 	int DtaBNFScript::skipEmptyChars(DtaScriptVariable& visibility) {
232 		int iImplicitCopyPosition;
233 		int iLocation;
234 		if (_bImplicitCopy) {
235 			iImplicitCopyPosition = CGRuntime::getOutputLocation();
236 			iLocation = CGRuntime::getInputLocation();
237 		} else {
238 			iImplicitCopyPosition = -1;
239 		}
240 		if ((_eIgnoreMode != NOT_IGNORE) && (_eIgnoreMode != UNDEFINED_IGNORE)) {
241 			bool bCopyImplicitly = _bImplicitCopy;
242 			switch(_eIgnoreMode) {
243 				case IGNORE_CPP:
244 				case IGNORE_JAVA:
245 					CGRuntime::_pInputStream->skipEmpty();
246 					break;
247 				case IGNORE_HTML:
248 					CGRuntime::_pInputStream->skipEmptyHTML();
249 					break;
250 				case IGNORE_BLANKS:
251 					CGRuntime::_pInputStream->skipBlanks();
252 					break;
253 				case IGNORE_SPACES:
254 					CGRuntime::_pInputStream->skipSpaces();
255 					break;
256 				case IGNORE_ADA:
257 					CGRuntime::_pInputStream->skipEmptyAda();
258 					break;
259 				case IGNORE_LATEX:
260 					CGRuntime::_pInputStream->skipEmptyLaTeX();
261 					break;
262 				case IGNORE_CPP_EXCEPT_DOXYGEN:
263 					CGRuntime::_pInputStream->skipEmptyCppExceptDoxygen();
264 					break;
265 				case IGNORE_CLAUSE:
266 					bCopyImplicitly = false;
267 					if (_pIgnoreClause != NULL) {
268 						BNFDisengageIgnore disengage(this);
269 						_pIgnoreClause->executeClause(visibility, 0);
270 					}
271 					break;
272 				default:
273 					throw UtlException("internal error in DtaBNFScript::skipEmptyChars(): unrecognized ignore mode encountered");
274 			}
275 			if (bCopyImplicitly) {
276 				int iLastLocation = CGRuntime::getInputLocation();
277 				if (iLastLocation > iLocation) {
278 					std::string sText = CGRuntime::getLastReadChars(iLastLocation - iLocation);
279 					writeBinaryData(sText.c_str(), sText.size());
280 				}
281 			}
282 		}
283 		return iImplicitCopyPosition;
284 	}
285 
writeBinaryData(const char * tcText,int iLength)286 	void DtaBNFScript::writeBinaryData(const char* tcText, int iLength) {
287 		if (_pImplicitCopyFunction != NULL) {
288 			ExprScriptConstant* pConstant = dynamic_cast<ExprScriptConstant*>(_pImplicitCopyFunction->getParameters()[0]);
289 			pConstant->setConstant(tcText, iLength);
290 			std::string sNewText = _pImplicitCopyFunction->getValue(CGRuntime::getThisInternalNode());
291 			CGRuntime::_pOutputStream->writeBinaryData(sNewText.c_str(), sNewText.size());
292 		} else {
293 			CGRuntime::_pOutputStream->writeBinaryData(tcText, iLength);
294 		}
295 	}
296 
storeClauseMatching(DtaScriptVariable & ruleNames,std::map<int,std::map<int,std::list<TemporaryMatchingStorage * >>> & mapOfAreas,BNFClauseMatchingArea * pClauseMatching)297 	void DtaBNFScript::storeClauseMatching(DtaScriptVariable& ruleNames, std::map<int, std::map<int, std::list<TemporaryMatchingStorage*> > >& mapOfAreas, BNFClauseMatchingArea* pClauseMatching) {
298 		if (pClauseMatching == NULL) return;
299 		int iBegin = pClauseMatching->beginPosition;
300 		int iEnd = pClauseMatching->endPosition;
301 		if (iBegin != iEnd) {
302 			DtaScriptVariable* pClauseNode = ruleNames.getArrayElement(pClauseMatching->clause->getSignature());
303 			mapOfAreas[iBegin][iEnd].push_back(new TemporaryMatchingStorage(true, pClauseNode));
304 			for (std::list<BNFClauseMatchingArea*>::iterator i = pClauseMatching->childs.begin(); i != pClauseMatching->childs.end(); ++i) {
305 				storeClauseMatching(ruleNames, mapOfAreas, *i);
306 			}
307 			mapOfAreas[iEnd][iBegin].push_back(new TemporaryMatchingStorage(false, pClauseNode));
308 		}
309 	}
310 
storeMatchingAreas(DtaScriptVariable & thisContext,DtaScriptVariable * pStorage)311 	void DtaBNFScript::storeMatchingAreas(DtaScriptVariable& thisContext, DtaScriptVariable* pStorage) {
312 		// storage of matching areas
313 		if (pStorage == NULL) {
314 			if (_pMatchingAreasContainer == NULL) return;
315 			pStorage = thisContext.getVariable(*_pMatchingAreasContainer);
316 		}
317 		DtaScriptVariable* pAreas = pStorage->insertNode("areas");
318 		DtaScriptVariable* pRules = pStorage->insertNode("rules");
319 		for (std::map<std::string, std::list<BNFClause*> >::iterator i = _listOfClauses.begin(); i != _listOfClauses.end(); ++i) {
320 			for (std::list<BNFClause*>::iterator j = i->second.begin(); j != i->second.end(); ++j) {
321 				std::string sSignature = (*j)->getSignature();
322 				DtaScriptVariable* pClauseNode = pRules->addElement(sSignature);
323 				pClauseNode->setValue(sSignature.c_str());
324 			}
325 		}
326 		std::map<int, std::map<int, std::list<TemporaryMatchingStorage*> > > mapOfAreas;
327 		storeClauseMatching(*pRules, mapOfAreas, _pParentClauseMatching);
328 		{
329 			for (std::map<int, std::map<int, std::list<TemporaryMatchingStorage*> > >::iterator i = mapOfAreas.begin(); i != mapOfAreas.end(); ++i) {
330 				DtaScriptVariable* pPosition = pAreas->addElement(i->first);
331 				for (std::map<int, std::list<TemporaryMatchingStorage*> >::reverse_iterator j = i->second.rbegin(); j != i->second.rend(); ++j) {
332 					{
333 						for (std::list<TemporaryMatchingStorage*>::iterator k = j->second.begin(); k != j->second.end(); ++k) {
334 							if ((*k)->bBegin) {
335 								pPosition->insertNode("begin")->addElement(j->first)->pushItem("")->setValue((*k)->pClauseNode);
336 							}
337 						}
338 					}
339 					{
340 						for (std::list<TemporaryMatchingStorage*>::iterator k = j->second.begin(); k != j->second.end(); ++k) {
341 							if (!(*k)->bBegin) {
342 								pPosition->insertNode("end")->addElement(j->first)->pushItem("")->setValue((*k)->pClauseNode);
343 							}
344 						}
345 					}
346 					{
347 						// delete the temporary storage
348 						for (std::list<TemporaryMatchingStorage*>::iterator k = j->second.begin(); k != j->second.end(); ++k) {
349 							delete *k;
350 						}
351 					}
352 				}
353 			}
354 		}
355 	}
356 
storeAST(DtaScriptVariable & thisContext,ScpStream & inputStream)357 	void DtaBNFScript::storeAST(DtaScriptVariable& thisContext, ScpStream& inputStream) {
358 		DtaASTNavigator navigator;
359 		std::auto_ptr<DtaASTStructure> structure(navigator.detectASTStructure(*this));
360 		DtaScriptVariable* pStorage = thisContext.getVariable(*_pASTContainer);
361 		structure->build(*pStorage);
362 		structure->populateAST(*pStorage, *_pParentClauseMatching, inputStream);
363 	}
364 
generate(ScpStream & stream,DtaScriptVariable & thisContext)365 	SEQUENCE_INTERRUPTION_LIST DtaBNFScript::generate(ScpStream& stream, DtaScriptVariable& thisContext) {
366 		CGRuntimeOutputStream noOutput(NULL);
367 		_bBNFMode = true;
368 		_sParsedFileOrContent = "";
369 		_bParsedFile = false;
370 		_pStream = &stream;
371 		// TO DO PROPERLY
372 		return execute(thisContext);
373 	}
374 
generate(const char * tcFile,DtaScriptVariable & thisContext)375 	SEQUENCE_INTERRUPTION_LIST DtaBNFScript::generate(const char* tcFile, DtaScriptVariable& thisContext) {
376 		CGRuntimeOutputStream noOutput(NULL);
377 		_bBNFMode = true;
378 		// absolute path of the parsed file:
379 		// avoid ambiguities
380 		std::string sAbsolutePath;
381 		if (ScpStream::existInputFileFromIncludePath(tcFile, sAbsolutePath)) {
382 			if (!ScpStream::existVirtualFile(tcFile)) {
383 				sAbsolutePath = CGRuntime::canonizePath(sAbsolutePath);
384 			}
385 		} else {
386 			// should have found! Do not touch the file name, for further error message
387 			sAbsolutePath = tcFile;
388 		}
389 		_sParsedFileOrContent = sAbsolutePath;
390 		_bParsedFile = true;
391 		// TO DO PROPERLY
392 		SEQUENCE_INTERRUPTION_LIST result = execute(thisContext);
393 		if (getFilenamePtr() != NULL) {
394 			DtaProject::getInstance().captureInputFile(sAbsolutePath.c_str(), getFilenamePtr());
395 		}
396 		return result;
397 	}
398 
generateString(std::string & sContent,DtaScriptVariable & thisContext)399 	SEQUENCE_INTERRUPTION_LIST DtaBNFScript::generateString(std::string& sContent, DtaScriptVariable& thisContext) {
400 		CGRuntimeOutputStream noOutput(NULL);
401 		_bBNFMode = true;
402 		_sParsedFileOrContent = sContent;
403 		_bParsedFile = false;
404 		_pStream = NULL;
405 		// TO DO PROPERLY
406 		return execute(thisContext);
407 	}
408 
execute(DtaScriptVariable & thisContext)409 	SEQUENCE_INTERRUPTION_LIST DtaBNFScript::execute(DtaScriptVariable& thisContext) {
410 		SEQUENCE_INTERRUPTION_LIST result;
411 		std::string sParsedFileOrContent = _sParsedFileOrContent; // because '_sParsedFileOrContent' is shared
412 		ScpStream* pStream;
413 		bool bStreamOwner = (_pStream == NULL);
414 		if (bStreamOwner) {
415 			if (_bParsedFile) {
416 				pStream = new ScpStream(sParsedFileOrContent, ScpStream::IN | ScpStream::PATH);
417 				if (pStream == NULL) throw UtlException("unable to open file \"" + sParsedFileOrContent + "\"");
418 			} else {
419 				pStream = new ScpStream;
420 				(*pStream) << sParsedFileOrContent;
421 			}
422 		} else {
423 			pStream = _pStream;
424 		}
425 		// note if 'final info' was requiring to store coverage,
426 		// while this BNF script hasn't required coverage recording
427 		bool bCreateMatchingAreasContainerForFinalInfo = false;
428 		if ((DtaProject::getInstance().getFinalInfoFlag() & DtaProject::FINAL_INFO_PARSE_COVERAGE_FOR_EVERYBODY) != 0) {
429 			if (_bParsedFile && !hasCoverageRecording()) {
430 				// create a global variable expression for coverage recording
431 				// when final info requires coverage on parsed files;
432 				// the variable expression points to an item whose key is the name
433 				// of the parsed file.
434 				if (DtaProject::getInstance().getGlobalVariable("_FINAL_INFO_PARSE_COVERAGE") == NULL) {
435 					DtaProject::getInstance().setGlobalVariable("_FINAL_INFO_PARSE_COVERAGE");
436 				}
437 				_pMatchingAreasContainer = new ExprScriptVariable("_FINAL_INFO_PARSE_COVERAGE");
438 				_pMatchingAreasContainer->setArrayKey(new ExprScriptConstant(sParsedFileOrContent.c_str()));
439 				bCreateMatchingAreasContainerForFinalInfo = true;
440 			}
441 		}
442 		if (hasCoverageRecording()) {
443 			// prepare for recording matching areas
444 			delete _pParentClauseMatching;
445 			_pParentClauseMatching = NULL;
446 		}
447 
448 		ScpStream* pOldInputStream = CGRuntime::_pInputStream;
449 		CGRuntime::_pInputStream = pStream;
450 		try {
451 			result = DtaPatternScript::execute(thisContext);
452 			if (hasCoverageRecording()) {
453 				// storage of matching areas / AST in the container
454 				CGThisModifier thisModifier(&thisContext);
455 				if (_pMatchingAreasContainer != NULL) storeMatchingAreas(thisContext);
456 				if (_pASTContainer != NULL) storeAST(thisContext, *CGRuntime::_pInputStream);
457 				if (!bCreateMatchingAreasContainerForFinalInfo) {
458 					// the variable expression wasn't built for 'final info', but
459 					// the latter requires perhaps the coverage
460 					if ((DtaProject::getInstance().getFinalInfoFlag() & DtaProject::FINAL_INFO_PARSE_COVERAGE) != 0) {
461 						//yes, the coverage tree must be copied for 'final info'
462 						DtaScriptVariable* pGlobal = DtaProject::getInstance().getGlobalVariable("_FINAL_INFO_PARSE_COVERAGE");
463 						if (pGlobal == NULL) {
464 							pGlobal = DtaProject::getInstance().setGlobalVariable("_FINAL_INFO_PARSE_COVERAGE");
465 						}
466 						DtaScriptVariable* pStorage = pGlobal->addElement(sParsedFileOrContent);
467 						storeMatchingAreas(thisContext, pStorage);
468 					}
469 				}
470 				// temporary low-level structure used to build the
471 				// coverage tree; won't serve anymore
472 				delete _pParentClauseMatching;
473 				_pParentClauseMatching = NULL;
474 			}
475 		} catch(UtlException& exception) {
476 			int iLine = pStream->getLineCount();
477 			int iCol = pStream->getColCount();
478 			if (bStreamOwner) {
479 				pStream->close();
480 				delete pStream;
481 			}
482 			CGRuntime::_pInputStream = pOldInputStream;
483 			std::string sException = exception.getMessage();
484 			std::string sMessage;
485 			char tcNumber[64];
486 			if (_bParsedFile) {
487 				sMessage = sParsedFileOrContent;
488 				sprintf(tcNumber, "(%d,%d):", iLine, iCol);
489 			} else if (!sParsedFileOrContent.empty()) {
490 				sMessage = CGRuntime::endl() + "----------------- content -----------------" + CGRuntime::endl() + sParsedFileOrContent + CGRuntime::endl() + "-------------------------------------------" + CGRuntime::endl();
491 				sprintf(tcNumber, "line %d, col %d:", iLine, iCol);
492 			}
493 			sMessage += tcNumber + CGRuntime::endl() + sException;
494 			throw UtlException(exception.getTraceStack(), sMessage);
495 		} catch(std::exception&) {
496 			if (bStreamOwner) {
497 				pStream->close();
498 				delete pStream;
499 			}
500 			CGRuntime::_pInputStream = pOldInputStream;
501 			throw;
502 		} catch(...) {
503 			int iLine = pStream->getLineCount();
504 			int iCol = pStream->getColCount();
505 			if (bStreamOwner) {
506 				pStream->close();
507 				delete pStream;
508 			}
509 			CGRuntime::_pInputStream = pOldInputStream;
510 			std::string sMessage;
511 			char tcNumber[64];
512 			if (_bParsedFile) {
513 				sMessage = sParsedFileOrContent;
514 				sprintf(tcNumber, "(%d,%d):", iLine, iCol);
515 			} else if (!sParsedFileOrContent.empty()) {
516 				sMessage = CGRuntime::endl() + "----------------- content -----------------" + CGRuntime::endl() + sParsedFileOrContent + CGRuntime::endl() + "-------------------------------------------" + CGRuntime::endl();
517 				sprintf(tcNumber, "line %d, col %d:", iLine, iCol);
518 			}
519 			sMessage += tcNumber + CGRuntime::endl() + "Fatal error: ellipsis exception";
520 			throw UtlException(sMessage);
521 		}
522 		if (bStreamOwner) {
523 			pStream->close();
524 			delete pStream;
525 		}
526 		CGRuntime::_pInputStream = pOldInputStream;
527 		return result;
528 	}
529 
IGNORE_MODEtoString(IGNORE_MODE eMode)530 	std::string DtaBNFScript::IGNORE_MODEtoString(IGNORE_MODE eMode) {
531 		std::string sResult;
532 		switch(eMode) {
533 			case NOT_IGNORE: break;
534 			case IGNORE_CPP: sResult = "C++";break;
535 			case IGNORE_JAVA: sResult = "JAVA";break;
536 			case IGNORE_HTML: sResult = "HTML";break;
537 			case IGNORE_BLANKS: sResult = "blanks";break;
538 			case IGNORE_SPACES: sResult = "spaces";break;
539 			case IGNORE_ADA: sResult = "Ada";break;
540 			case IGNORE_LATEX: sResult = "LaTeX";break;
541 			case IGNORE_CPP_EXCEPT_DOXYGEN: sResult = "C++/Doxygen";break;
542 			case IGNORE_CLAUSE:
543 				throw UtlException("IGNORE_MODEtoString('IGNORE_CLAUSE') requires a specific handling!");
544 			default:
545 				throw UtlException("internal error in DtaBNFScript::IGNORE_MODEtoString(): unrecognized ignore mode encountered");
546 		}
547 		return sResult;
548 	}
549 
buildClause(ScpStream & script,GrfBlock & parent,const std::string & sName,const std::string & sTemplateKey,bool bGenericKey,int iReturnType,const std::vector<std::string> & listOfParameters,const std::vector<EXPRESSION_TYPE> & listOfParameterTypes,bool bOverload)550 	BNFClause& DtaBNFScript::buildClause(ScpStream& script, GrfBlock& parent, const std::string& sName, const std::string& sTemplateKey, bool bGenericKey, int iReturnType, const std::vector<std::string>& listOfParameters, const std::vector<EXPRESSION_TYPE>& listOfParameterTypes, bool bOverload) {
551 		std::list<BNFClause*>& listOfHomonyms = _listOfClauses[sName];
552 		BNFClause* pClause = NULL;
553 		std::list<BNFClause*>::iterator i;
554 		for (i = listOfHomonyms.begin(); i != listOfHomonyms.end(); i++) {
555 			if ((*i)->getArity() >= (int) listOfParameters.size()) {
556 				for (std::string::size_type j = 0; j < listOfParameters.size(); j++) {
557 					const std::string& sClauseParameter = (*i)->getParameter(j);
558 					if (listOfParameters[j] != sClauseParameter) {
559 						if (sClauseParameter.empty()) {
560 							(*i)->setParameter(j, listOfParameters[j], listOfParameterTypes[j]);
561 						} else throw UtlException(script, "parameter '" + listOfParameters[j] + "' must be called '" + sClauseParameter + "' into BNF clause declaration");
562 					}
563 				}
564 				if (((*i)->getArity() > (int) listOfParameters.size()) && !(*i)->isPropagatedParameter()) {
565 					throw UtlException(script, "not enough parameters passed to the non-terminal '" + sName + "'");
566 				}
567 				if (((*i)->getTemplateKey() == sTemplateKey) && ((*i)->isGenericKey() == bGenericKey)) {
568 					pClause = (*i);
569 					pClause->setParent(&parent);
570 					break;
571 				}
572 			} else {
573 				throw UtlException(script, "too many parameters passed to the non-terminal '" + sName + "'");
574 			}
575 		}
576 		if (pClause == NULL) {
577 			if (bOverload) throw UtlException(script, "cannot overload a clause that doesn't exist yet!");
578 			BNFClause* pTemplateClause = NULL;
579 			if (!sTemplateKey.empty()) pTemplateClause = &buildClause(script, parent, sName, "", false, iReturnType, listOfParameters, listOfParameterTypes, false);
580 			pClause = new BNFClause(this, &parent, sName, sTemplateKey, bGenericKey, listOfParameters, listOfParameterTypes);
581 			if ((sName[0] != '#') && (_graph.getNbCommands() == 0)) {
582 				pClause->setPreprocessingIgnoreMode(NOT_IGNORE, NULL);
583 				BNFClauseCall* pClauseCall = new BNFRootClauseCall(this, &_graph, _bNoCase);
584 				if (requiresParsingInformation()) pClauseCall->setParsingInformation(getFilenamePtr(), script);
585 				_graph.add(pClauseCall);
586 				pClauseCall->setClause(pClause);
587 			}
588 			if (!sTemplateKey.empty()) pClause->setTemplateClause(pTemplateClause);
589 			listOfHomonyms.push_front(pClause);
590 		} else if (bOverload) {
591 			BNFClause* pOverloadedClause = pClause;
592 			pClause = new BNFClause(this, &parent, sName, sTemplateKey, bGenericKey, listOfParameters, listOfParameterTypes);
593 			pOverloadedClause->setOverloadClause(pClause);
594 		}
595 		pClause->setReturnType(iReturnType);
596 		return *pClause;
597 	}
598 
buildClause(ScpStream & script,GrfBlock & parent,const std::string & sName,unsigned int iArity)599 	BNFClause& DtaBNFScript::buildClause(ScpStream& script, GrfBlock& parent, const std::string& sName, unsigned int iArity) {
600 		std::list<BNFClause*>& listOfHomonyms = _listOfClauses[sName];
601 		BNFClause* pClause = NULL;
602 		for (std::list<BNFClause*>::iterator i = listOfHomonyms.begin(); i != listOfHomonyms.end(); i++) {
603 			if ((*i)->getArity() < iArity) {
604 				throw UtlException(script, "too many parameters passed to the non-terminal '" + sName + "'");
605 			} else if (((*i)->getArity() > iArity) && !(*i)->isPropagatedParameter()) {
606 				throw UtlException(script, "not enough parameters passed to the non-terminal '" + sName + "'");
607 			} else if ((*i)->getTemplateKey().empty()) {
608 				pClause = (*i);
609 				break;
610 			}
611 		}
612 		if (pClause == NULL) {
613 			pClause = new BNFClause(this, &parent, sName, iArity);
614 			listOfHomonyms.push_front(pClause);
615 		}
616 		return *pClause;
617 	}
618 
parsePreprocessorDirective(const std::string & sDirective,ScpStream & script,GrfBlock & block)619 	void DtaBNFScript::parsePreprocessorDirective(const std::string& sDirective, ScpStream& script, GrfBlock& block) {
620 		if (sDirective == "#applyBNFRule") {
621 			script.skipEmpty();
622 			std::string sIdentifier;
623 			if (!script.readIdentifier(sIdentifier)) throw UtlException(script, "the directive #applyBNFRule should be followed by a non-terminal");
624 			BNFClauseCall* pClauseCall = parseBNFClauseCall(script, block, sIdentifier, false, _bNoCase);
625 			if (requiresParsingInformation()) pClauseCall->setParsingInformation(getFilenamePtr(), script);
626 			std::vector<std::string> listOfConstants;
627 			bool bConcat;
628 			ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, true);
629 			pClauseCall->setVariableToAssign(pVarToAssign, bConcat);
630 			if (!listOfConstants.empty()) pClauseCall->setConstantsToMatch(listOfConstants);
631 			script.skipEmpty();
632 			if (!script.isEqualTo(';')) throw UtlException(script, "syntax error, ';' expected to close the directive #applyBNFRule");
633 		} else {
634 			DtaPatternScript::parsePreprocessorDirective(sDirective, script, block);
635 		}
636 	}
637 
parseInstruction(ScpStream & script,GrfBlock & block)638 	void DtaBNFScript::parseInstruction(ScpStream& script, GrfBlock& block) {
639 		if (_bBNFMode) {
640 			int iStatementBeginning = script.getInputLocation();
641 			if (script.isEqualTo('#')) {
642 				std::string sDirective;
643 				script.skipEmpty();
644 				if (!script.readIdentifier(sDirective)) throw UtlException(script, "directive name expected");
645 				sDirective = "#" + sDirective;
646 				parseBNFPreprocessorDirective(iStatementBeginning, sDirective, script, block);
647 			} else {
648 				std::string sClauseName;
649 				if (!script.readIdentifier(sClauseName)) {
650 					throw UtlException(script, "identifier expected: name of a BNF clause or 'function' or 'declare'");
651 				}
652 				if ((sClauseName == "function") || (sClauseName == "external") || (sClauseName == "declare")) {
653 					script.skipEmpty();
654 					std::string sIdentifier;
655 					int iCursor = script.getInputLocation();
656 					if (script.readIdentifier(sIdentifier)) {
657 						script.setInputLocation(iCursor);
658 						_bBNFMode = false;
659 						if (sClauseName == "function") parseFunction(block, script);
660 						else if (sClauseName == "external") parseExternal(block, script);
661 						else parseDeclare(block, script);
662 						_bBNFMode = true;
663 						return;
664 					}
665 					throw UtlException("syntax error after keyword '" + sClauseName + "'");
666 				} else if ((sClauseName == "readonlyHook") || (sClauseName == "writefileHook")) {
667 					_bBNFMode = false;
668 					if (sClauseName == "readonlyHook") parseReadonlyHook(block, script);
669 					else if (sClauseName == "writefileHook") parseWritefileHook(block, script);
670 					_bBNFMode = true;
671 					return;
672 				} else if ((sClauseName == "stepintoHook") || (sClauseName == "stepoutHook")) {
673 					_bBNFMode = false;
674 					if (sClauseName == "stepintoHook") parseStepintoHook(block, script);
675 					else if (sClauseName == "stepoutHook") parseStepoutHook(block, script);
676 					_bBNFMode = true;
677 					return;
678 				}
679 				parseBNFClause(script, block, iStatementBeginning, sClauseName, false);
680 			}
681 		} else {
682 			DtaPatternScript::parseInstruction(script, block);
683 		}
684 	}
685 
parseStepintoHook(GrfBlock & block,ScpStream & script)686 	void DtaBNFScript::parseStepintoHook(GrfBlock& block, ScpStream& script) {
687 		if (getStepintoHook() != NULL) throw UtlException(script, "function 'stepintoHook(<clause_signature>, <parameters>)' has already been defined and can't be implemented twice");
688 		BNFStepintoHook* pStepintoHook = new BNFStepintoHook(this, &block);
689 		if (requiresParsingInformation()) pStepintoHook->setParsingInformation(getFilenamePtr(), script);
690 		block.addFunction(pStepintoHook);
691 		script.skipEmpty();
692 		if (!script.isEqualTo('(')) throw UtlException(script, "syntax error: '(' expected");
693 		script.skipEmpty();
694 		std::string sIdentifier;
695 		if (!script.readIdentifier(sIdentifier)) throw UtlException(script, "syntax error: argument name expected for <clause_signature>");
696 		pStepintoHook->setClauseSignature(sIdentifier.c_str());
697 		script.skipEmpty();
698 		if (!script.isEqualTo(',')) throw UtlException(script, "syntax error: ',' expected");
699 		script.skipEmpty();
700 		if (!script.readIdentifier(sIdentifier)) throw UtlException(script, "syntax error: argument name expected for <parameters>");
701 		pStepintoHook->setParameters(sIdentifier.c_str());
702 		script.skipEmpty();
703 		if (!script.isEqualTo(')')) throw UtlException(script, "syntax error: ')' expected");
704 		std::string _sOldFunctionBody = _sCurrentFunctionBody;
705 		std::string _sOldFunctionTemplateBody = _sCurrentFunctionTemplateBody;
706 		bool bOldCurrentFunctionGenericTemplateKey = _bCurrentFunctionGenericTemplateKey;
707 		_sCurrentFunctionBody = pStepintoHook->getFunctionName();
708 		_sCurrentFunctionTemplateBody = "";
709 		_bCurrentFunctionGenericTemplateKey = false;
710 		pStepintoHook->isBodyDefined(true);
711 		parseBlock(script, *pStepintoHook);
712 		_sCurrentFunctionBody = _sOldFunctionBody;
713 		_sCurrentFunctionTemplateBody = _sOldFunctionTemplateBody;
714 		_bCurrentFunctionGenericTemplateKey = bOldCurrentFunctionGenericTemplateKey;
715 	}
716 
parseStepoutHook(GrfBlock & block,ScpStream & script)717 	void DtaBNFScript::parseStepoutHook(GrfBlock& block, ScpStream& script) {
718 		if (getStepoutHook() != NULL) throw UtlException(script, "function 'StepoutHook(<clause_signature>, <parameters>, <success>)' has already been defined and can't be implemented twice");
719 		BNFStepoutHook* pStepoutHook = new BNFStepoutHook(this, &block);
720 		if (requiresParsingInformation()) pStepoutHook->setParsingInformation(getFilenamePtr(), script);
721 		block.addFunction(pStepoutHook);
722 		script.skipEmpty();
723 		if (!script.isEqualTo('(')) throw UtlException(script, "syntax error: '(' expected");
724 		script.skipEmpty();
725 		std::string sIdentifier;
726 		if (!script.readIdentifier(sIdentifier)) throw UtlException(script, "syntax error: argument name expected for <clause_signature>");
727 		pStepoutHook->setClauseSignature(sIdentifier.c_str());
728 		script.skipEmpty();
729 		if (!script.isEqualTo(',')) throw UtlException(script, "syntax error: ',' expected");
730 		script.skipEmpty();
731 		if (!script.readIdentifier(sIdentifier)) throw UtlException(script, "syntax error: argument name expected for <parameters>");
732 		pStepoutHook->setParameters(sIdentifier.c_str());
733 		script.skipEmpty();
734 		if (!script.isEqualTo(',')) throw UtlException(script, "syntax error: ',' expected");
735 		script.skipEmpty();
736 		if (!script.readIdentifier(sIdentifier)) throw UtlException(script, "syntax error: argument name expected for <success>");
737 		pStepoutHook->setSuccess(sIdentifier.c_str());
738 		script.skipEmpty();
739 		if (!script.isEqualTo(')')) throw UtlException(script, "syntax error: ')' expected");
740 		std::string _sOldFunctionBody = _sCurrentFunctionBody;
741 		std::string _sOldFunctionTemplateBody = _sCurrentFunctionTemplateBody;
742 		bool bOldCurrentFunctionGenericTemplateKey = _bCurrentFunctionGenericTemplateKey;
743 		_sCurrentFunctionBody = pStepoutHook->getFunctionName();
744 		_sCurrentFunctionTemplateBody = "";
745 		_bCurrentFunctionGenericTemplateKey = false;
746 		pStepoutHook->isBodyDefined(true);
747 		parseBlock(script, *pStepoutHook);
748 		_sCurrentFunctionBody = _sOldFunctionBody;
749 		_sCurrentFunctionTemplateBody = _sOldFunctionTemplateBody;
750 		_bCurrentFunctionGenericTemplateKey = bOldCurrentFunctionGenericTemplateKey;
751 	}
752 
parseBNFPreprocessorDirective(int iStatementBeginning,const std::string & sDirective,ScpStream & script,GrfBlock & block)753 	void DtaBNFScript::parseBNFPreprocessorDirective(int iStatementBeginning, const std::string& sDirective, ScpStream& script, GrfBlock& block) {
754 		if (sDirective == "#ignore") {
755 			std::string sClauseName = sDirective;
756 			std::string sKey;
757 			script.skipEmpty();
758 			if (script.isEqualTo('[')) {
759 				script.skipEmpty();
760 				if (!script.readPythonString(sKey)) throw UtlException(script, "syntax error, constant string expected");
761 				script.skipEmpty();
762 				if (!script.isEqualTo(']')) throw UtlException(script, "syntax error, ']' expected");
763 				if (!sKey.empty()) sClauseName += "[" + sKey + "]";
764 			}
765 			BNFClause& theIgnoreClause = parseBNFClause(script, block, iStatementBeginning, sClauseName, false);
766 			if (theIgnoreClause.getArity() != 0) throw UtlException(script, "clause '#ignore' doesn't accept parameters");
767 			_mapOfIgnoreClauses[sClauseName] = &theIgnoreClause;
768 		} else if (sDirective == "#noCase") {
769 			_bNoCase = true;
770 		} else if (sDirective == "#trace") {
771 			_bTrace = true;
772 		} else if (sDirective == "#matching") {
773 			script.skipEmpty();
774 			if (!script.isEqualTo('(')) throw UtlException(script, "syntax error, '(' expected");
775 			script.skipEmpty();
776 			if (_pMatchingAreasContainer != NULL) {
777 				delete _pMatchingAreasContainer;
778 				_pMatchingAreasContainer = NULL;
779 			}
780 			_pMatchingAreasContainer = parseBNFVariableExpression(block, script);
781 			script.skipEmpty();
782 			if (!script.isEqualTo(')')) throw UtlException(script, "syntax error, ')' expected");
783 		} else if (sDirective == "#parameters") {
784 			parseAndPropagateParameters(script, block);
785 		} else if (sDirective == "#transformRules") {
786 			parseTransformRules(script, block);
787 		} else if (sDirective == "#overload") {
788 			std::string sClauseName;
789 			script.skipEmpty();
790 			if (script.isEqualTo('#')) {
791 				script.skipEmpty();
792 				if (script.isEqualToIdentifier("ignore")) sClauseName = "#ignore";
793 			} else if (!script.readIdentifier(sClauseName)) throw UtlException(script, "clause name to overload expected");
794 			parseBNFClause(script, block, iStatementBeginning, sClauseName, true);
795 		} else if (sDirective == "#buildAST") {
796 			script.skipEmpty();
797 			if (!script.isEqualTo('(')) throw UtlException(script, "syntax error, '(' expected");
798 			script.skipEmpty();
799 			if (_pASTContainer != NULL) {
800 				delete _pASTContainer;
801 				_pASTContainer = NULL;
802 			}
803 			_pASTContainer = parseBNFVariableExpression(block, script);
804 			script.skipEmpty();
805 			if (!script.isEqualTo(')')) throw UtlException(script, "syntax error, ')' expected");
806 		} else DtaPatternScript::parsePreprocessorDirective(sDirective, script, block);
807 	}
808 
parseAndPropagateParameters(ScpStream & script,GrfBlock & block)809 	void DtaBNFScript::parseAndPropagateParameters(ScpStream& script, GrfBlock& block) {
810 		std::string sFunctionQuantity;
811 		script.skipEmpty();
812 		if (!script.readIdentifier(sFunctionQuantity)) throw UtlException(script, "function quantity expected");
813 		script.skipEmpty();
814 		if (!script.isEqualTo('(')) throw UtlException(script, "'(' expected");
815 		std::vector<std::string> listOfParameters;
816 		std::vector<EXPRESSION_TYPE> listOfParameterTypes;
817 		script.skipEmpty();
818 		if (!script.isEqualTo(')')) {
819 			int iIndex = 0;
820 			EXPRESSION_TYPE paramType;
821 			do {
822 				std::string sParameter;
823 				script.skipEmpty();
824 				if (!script.readIdentifier(sParameter)) throw UtlException(script, "parameter name expected");
825 				script.skipEmpty();
826 				if (!script.isEqualTo(':')) throw UtlException(script, "':' expected after parameter '" + sParameter + "'");
827 				paramType = parseVariableType(block, script);
828 				listOfParameters.push_back(sParameter);
829 				listOfParameterTypes.push_back(paramType);
830 				iIndex++;
831 			} while (script.isEqualTo(','));
832 			if (!script.isEqualTo(')')) throw UtlException(script, "')' expected");
833 		}
834 		std::auto_ptr<ExprScriptExpression> pFilter(parseExpression(block, script));
835 		for (std::map<std::string, std::list<BNFClause*> >::iterator i = _listOfClauses.begin(); i != _listOfClauses.end(); ++i) {
836 			for (std::list<BNFClause*>::iterator j = i->second.begin(); j != i->second.end(); ++j) {
837 				(*j)->propagateParameters(*pFilter, sFunctionQuantity, listOfParameters, listOfParameterTypes);
838 			}
839 		}
840 	}
841 
parseTransformRules(ScpStream & script,GrfBlock & block)842 	void DtaBNFScript::parseTransformRules(ScpStream& script, GrfBlock& block) {
843 		BNFTransformRules* pTransformer = new BNFTransformRules;
844 		_listOfTransformRules.push_back(pTransformer);
845 		pTransformer->setFilter(parseExpression(block, script));
846 		script.skipEmpty();
847 		int iBeforeBrace = script.getInputLocation();
848 		if (!script.isEqualTo('{')) throw UtlException(script, "'{' expected");
849 		script.skipEmpty();
850 		if (!script.isEqualTo('}')) {
851 			script.setInputLocation(iBeforeBrace);
852 			pTransformer->setPrototypeScript(new DtaTranslateScript(&block));
853 			pTransformer->getPrototypeScript()->parseEmbeddedScript(script);
854 		}
855 		script.skipEmpty();
856 		iBeforeBrace = script.getInputLocation();
857 		if (!script.isEqualTo('{')) throw UtlException(script, "'{' expected to transform the production rule");
858 		script.skipEmpty();
859 		if (!script.isEqualTo('}')) {
860 			script.setInputLocation(iBeforeBrace);
861 			pTransformer->setProductionRuleScript(new DtaTranslateScript(&block));
862 			pTransformer->getProductionRuleScript()->parseEmbeddedScript(script);
863 		}
864 	}
865 
parseBNFClause(ScpStream & script,GrfBlock & block,int iStatementBeginning,const std::string & sClauseName,bool bOverload)866 	BNFClause& DtaBNFScript::parseBNFClause(ScpStream& script, GrfBlock& block, int iStatementBeginning, const std::string& sClauseName, bool bOverload) {
867 		if (!_listOfTransformRules.empty()) {
868 			int iLocation = script.getInputLocation();
869 			std::string sCompleteClauseName = sClauseName;
870 			script.skipEmpty();
871 			if (script.isEqualTo('<')) {
872 				script.skipEmpty();
873 				std::string sText;
874 				bool bString = false;
875 				if (script.readIdentifier(sText) || script.readPythonString(sText) && (bString = true)) {
876 					script.skipEmpty();
877 					if (script.isEqualTo('>')) {
878 						if (bString) sText = "\"" + CGRuntime::composeCLikeString(sText) + "\"";
879 						sCompleteClauseName += "<" + sText + ">";
880 					} else {
881 						// syntax error, to resolve further
882 						script.setInputLocation(iLocation);
883 					}
884 				} else {
885 					// syntax error, to resolve further
886 					script.setInputLocation(iLocation);
887 				}
888 			}
889 			if (script.findString("::=")) {
890 				int iStartProductionRule = script.getInputLocation();
891 				char cChar = '\0';
892 				script.setOutputLocation(iStartProductionRule - 3);
893 				script.writeBinaryData(&cChar, 1);
894 				std::string sPrototype = script.readBuffer() + iStatementBeginning;
895 				cChar = ':';
896 				script.setOutputLocation(iStartProductionRule - 3);
897 				script.writeBinaryData(&cChar, 1);
898 				int iBrackets = 0;
899 				bool bInstruction = false;
900 				bool bFail = true;
901 				std::string sText;
902 				while (bFail && script.skipEmpty()) {
903 					switch(script.readChar()) {
904 						case '\'':
905 						case '\"':
906 							script.goBack();
907 							script.readStringOrCharLiteral(sText);
908 							break;
909 						case '%':
910 							if (!script.isEqualTo('>')) break;
911 						case '@':
912 							do {
913 								if (script.isEqualTo('<') && script.isEqualTo('%')) break;
914 								script.isEqualTo('\\');
915 							} while (!script.isEqualTo('@'));
916 							break;
917 						case '{':
918 							bInstruction = false;
919 							iBrackets++;
920 							break;
921 						case '}':
922 							iBrackets--;
923 							break;
924 						case '=':
925 							if (!bInstruction) bInstruction = script.isEqualTo('>');
926 							break;
927 						case ';':
928 							if (iBrackets == 0) {
929 								if (!bInstruction) bFail = false;
930 								else bInstruction = false;
931 							}
932 					}
933 				}
934 				if (!bFail) {
935 					int iEndProductionRule = script.getInputLocation() - 1;
936 					cChar = '\0';
937 					script.setOutputLocation(iEndProductionRule);
938 					script.writeBinaryData(&cChar, 1);
939 					std::string sProductionRule = script.readBuffer() + iStartProductionRule;
940 					cChar = ';';
941 					script.setOutputLocation(iEndProductionRule);
942 					script.writeBinaryData(&cChar, 1);
943 					for (std::list<BNFTransformRules*>::const_iterator i = _listOfTransformRules.begin(); i != _listOfTransformRules.end(); ++i) {
944 						// if the current rule transformer applies with success,
945 						// the new rule replaces the old one in the input stream
946 						if ((*i)->applyRuleTransformer(script, block, iStatementBeginning, iStartProductionRule, sCompleteClauseName, sPrototype, sProductionRule)) break;
947 					}
948 				}
949 				script.setInputLocation(iLocation);
950 			}
951 		}
952 		std::vector<std::string> listOfParameters;
953 		std::vector<EXPRESSION_TYPE> listOfParameterTypes;
954 		std::string sTemplateKey;
955 		bool bGenericKey = false;
956 		script.skipEmpty();
957 		if (script.isEqualTo('<')) {
958 			script.skipEmpty();
959 			if (!script.readPythonString(sTemplateKey)) {
960 				if (script.readIdentifier(sTemplateKey)) {
961 					if (sTemplateKey != "true") {
962 						if (sTemplateKey == "false") sTemplateKey = "";
963 						else bGenericKey = true;
964 					}
965 				} else throw UtlException(script, "template key expected for clause '" + sClauseName + "'");
966 			}
967 			script.skipEmpty();
968 			if (!script.isEqualTo('>')) throw UtlException(script, "'>' to end the template key '" + sTemplateKey + "' for clause '" + sClauseName + "'");
969 			script.skipEmpty();
970 		}
971 		if (script.isEqualTo('(')) {
972 			do {
973 				std::string sParameter;
974 				script.skipEmpty();
975 				if (!script.readIdentifier(sParameter)) throw UtlException(script, "parameter expected while parsing a BNF clause for declaration");
976 				if (sParameter == sClauseName) throw UtlException(script, "the parameter '" + sParameter + "' cannot hold the same name as the BNF rule");
977 				listOfParameters.push_back(sParameter);
978 				script.skipEmpty();
979 				if (!script.isEqualTo(':')) throw UtlException(script, "':' expected after parameter '" + sParameter + "' while parsing a BNF clause for declaration");
980 				script.skipEmpty();
981 				std::string sType;
982 				if (!script.readIdentifier(sType)) throw UtlException(script, "parameter type expected for '" + sParameter + "' while parsing a BNF clause for declaration");
983 				EXPRESSION_TYPE exprType;
984 				if (sType == "node") exprType = NODE_EXPRTYPE;
985 				else if (sType == "reference") exprType = REFERENCE_EXPRTYPE;
986 				else if (sType == "value") exprType = VALUE_EXPRTYPE;
987 				else if (sType == "variable") {
988 					std::string sErrorMessage = script.getMessagePrefix() + "warning! parameter type 'variable' is obsolete since version 3.8.7 -> replace it by 'node'";
989 					if (DtaProject::getInstance().addWarning(sErrorMessage) == 1) CGRuntime::traceLine(sErrorMessage);
990 					exprType = NODE_EXPRTYPE;
991 				} else throw UtlException(script, "unknown type '" + sType + "' for parameter '" + sParameter + "' while parsing a BNF clause for declaration");
992 				exprType = parseClassType(block, script, exprType);
993 				listOfParameterTypes.push_back(exprType);
994 				script.skipEmpty();
995 			} while (script.isEqualTo(','));
996 			if (!script.isEqualTo(')')) throw UtlException(script, "')' expected while parsing a BNF clause declaration");
997 			script.skipEmpty();
998 		}
999 		if (!script.isEqualTo(':')) throw UtlException(script, "'::=' or ':' expected after parsing a BNF clause declaration");
1000 		int iReturnType = BNFClause::NO_RETURN_TYPE;
1001 		IGNORE_MODE ePreprocessingIgnoreMode = UNDEFINED_IGNORE;
1002 		BNFClause* pPreprocessingIgnoreClause = NULL;
1003 		if (!script.isEqualTo(':')) {
1004 			std::string sReturnType;
1005 			bool bDefinitionExpected = false;
1006 			script.skipEmpty();
1007 			if (script.readIdentifier(sReturnType)) {
1008 				if (sReturnType == "list") iReturnType = BNFClause::LIST_RETURN_TYPE;
1009 				else if (sReturnType == "node") iReturnType = BNFClause::NODE_RETURN_TYPE;
1010 				else if (sReturnType == "value") iReturnType = BNFClause::VALUE_RETURN_TYPE;
1011 				else throw UtlException(script, "'list' or 'node' expected instead of '" + sReturnType + "', while parsing return type of a BNF clause for declaration");
1012 				script.skipEmpty();
1013 				if (script.isEqualTo("::=")) bDefinitionExpected = true;
1014 				else if (!script.isEqualTo(':')) throw UtlException(script, "'::=' expected after parsing a BNF clause declaration");
1015 			}
1016 			if (!bDefinitionExpected) {
1017 				if (script.isEqualTo('#')) {
1018 					if (script.isEqualTo('!')) {
1019 						if (!script.isEqualToIdentifier("ignore")) throw UtlException(script, "'#!ignore' expected as preprocessing of a BNF clause");
1020 						ePreprocessingIgnoreMode = NOT_IGNORE;
1021 					} else if (script.isEqualToIdentifier("ignore")) {
1022 						ePreprocessingIgnoreMode = parseIgnoreMode(script, pPreprocessingIgnoreClause);
1023 					} else {
1024 						throw UtlException(script, "'::=' or ':' or '#ignore' expected after parsing a BNF clause declaration");
1025 					}
1026 					script.skipEmpty();
1027 				}
1028 				script.skipEmpty();
1029 				if (!script.isEqualTo("::=")) throw UtlException(script, "'::=' expected after parsing a BNF clause declaration");
1030 			}
1031 		} else if (!script.isEqualTo('=')) throw UtlException(script, "'::=' expected after parsing a BNF clause declaration");
1032 		BNFClause& myClause = buildClause(script, block, sClauseName, sTemplateKey, bGenericKey, iReturnType, listOfParameters, listOfParameterTypes, bOverload);
1033 		if (myClause.getNbCommands() > 0) throw UtlException(script, "clause '" + myClause.getSignature() + "' has already been described");
1034 		// register the clause name as a local variable, if returned value/node expected
1035 		if ((iReturnType == BNFClause::LIST_RETURN_TYPE) || (iReturnType == BNFClause::NODE_RETURN_TYPE)) {
1036 			myClause.addLocalVariable(sClauseName, NODE_EXPRTYPE);
1037 		} else if (iReturnType == BNFClause::VALUE_RETURN_TYPE) {
1038 			myClause.addLocalVariable(sClauseName, VALUE_EXPRTYPE);
1039 		}
1040 		// register the generic template key, if any
1041 		if (bGenericKey && !sTemplateKey.empty()) {
1042 			myClause.addLocalVariable(sTemplateKey, VALUE_EXPRTYPE);
1043 		}
1044 		GrfBlock* pParent;
1045 		if (ePreprocessingIgnoreMode != UNDEFINED_IGNORE) {
1046 			myClause.setPreprocessingIgnoreMode(ePreprocessingIgnoreMode, pPreprocessingIgnoreClause);
1047 			BNFIgnore* pIgnore = new BNFIgnore(this, &myClause, ePreprocessingIgnoreMode, pPreprocessingIgnoreClause);
1048 			myClause.add(pIgnore);
1049 			pParent = pIgnore;
1050 		} else {
1051 			pParent = &myClause;
1052 		}
1053 		script.skipEmpty();
1054 		parseBNFDisjunction(script, myClause, *pParent, _bNoCase, NULL);
1055 		script.skipEmpty();
1056 		if (!script.isEqualTo(';')) throw UtlException(script, "';' expected at the end of a BNF clause definition");
1057 		return myClause;
1058 	}
1059 
parseBNFDisjunction(ScpStream & script,BNFClause & rule,GrfBlock & block,bool bNoCase,BNFStepper * pStepperRE)1060 	void DtaBNFScript::parseBNFDisjunction(ScpStream& script, BNFClause& rule, GrfBlock& block, bool bNoCase, BNFStepper* pStepperRE) {
1061 		BNFDisjunction* pDisjunction = new BNFDisjunction(this, &block);
1062 		if (requiresParsingInformation()) pDisjunction->setParsingInformation(getFilenamePtr(), script);
1063 		block.add(pDisjunction);
1064 		parseBNFConjunction(script, rule, *pDisjunction, false, bNoCase, pStepperRE);
1065 		if (script.isEqualTo('|')) {
1066 			do {
1067 				parseBNFConjunction(script, rule, *pDisjunction, false, bNoCase, pStepperRE);
1068 			} while (script.isEqualTo('|'));
1069 		} else {
1070 			pDisjunction->moveCommands(block);
1071 			block.removeCommand(pDisjunction);
1072 		}
1073 	}
1074 
parseBNFConjunction(ScpStream & script,BNFClause & rule,GrfBlock & block,bool bContinue,bool bNoCase,BNFStepper * pStepperRE)1075 	void DtaBNFScript::parseBNFConjunction(ScpStream& script, BNFClause& rule, GrfBlock& block, bool bContinue, bool bNoCase, BNFStepper* pStepperRE) {
1076 		BNFConjunction* pConjunction = new BNFConjunction(this, &block);
1077 		if (requiresParsingInformation()) pConjunction->setParsingInformation(getFilenamePtr(), script);
1078 		block.add(pConjunction);
1079 		parseBNFSequence(script, rule, *pConjunction, bContinue, bNoCase, pStepperRE);
1080 		if (pConjunction->getNbCommands() == 1) {
1081 			pConjunction->moveCommands(block);
1082 			block.removeCommand(pConjunction);
1083 		}
1084 	}
1085 
parseBNFSequence(ScpStream & script,BNFClause & rule,GrfBlock & block,bool bContinue,bool bNoCase,BNFStepper * pStepperRE)1086 	void DtaBNFScript::parseBNFSequence(ScpStream& script, BNFClause& rule, GrfBlock& block, bool bContinue, bool bNoCase, BNFStepper* pStepperRE) {
1087 		bool bSuccess = parseBNFLitteral(script, rule, block, bContinue, bNoCase, false /* if '=>' or ':<variable>' after reading this literal, it belongs to it */, pStepperRE);
1088 		if (!bSuccess) {
1089 			int iChar =  script.readChar();
1090 			std::string sChar;
1091 			if (iChar < 0) sChar = "end of file";
1092 			else sChar = std::string("'") + (char) iChar + "'";
1093 			throw UtlException(script, "literal expected, instead of " + sChar);
1094 		}
1095 		while (parseBNFLitteral(script, rule, block, bContinue, bNoCase, false /* if '=>' or ':<variable>' after reading this literal, it belongs to it */, pStepperRE)) ;
1096 	}
1097 
parseBNFVariableExpression(GrfBlock & block,ScpStream & script)1098 	ExprScriptVariable* DtaBNFScript::parseBNFVariableExpression(GrfBlock& block, ScpStream& script) {
1099 		ExprScriptVariable* pVariableExpr = NULL;
1100 		script.skipEmpty();
1101 		std::string sVariableName;
1102 		if (script.readIdentifier(sVariableName)) {
1103 			block.addBNFLocalVariable(sVariableName, NODE_EXPRTYPE);
1104 			pVariableExpr = new ExprScriptVariable(sVariableName.c_str());
1105 		}
1106 		return parseVariableExpression(block, script, pVariableExpr);
1107 	}
1108 
parseLiteralAssignment(ScpStream & script,GrfBlock & block,std::vector<std::string> & listOfConstants,bool & bConcatVariable,bool bVariableAllowed)1109 	ExprScriptVariable* DtaBNFScript::parseLiteralAssignment(ScpStream& script, GrfBlock& block, std::vector<std::string>& listOfConstants, bool& bConcatVariable, bool bVariableAllowed) {
1110 		ExprScriptVariable* pVariableExpr = NULL;
1111 		script.skipEmpty();
1112 		int iLocation = script.getInputLocation();
1113 		if (script.isEqualTo(':')) {
1114 			bool bTryVariable = false;
1115 			script.skipEmpty();
1116 			if (script.isEqualTo('\"')) {
1117 				script.goBack();
1118 				std::string sConstant;
1119 				if (!script.readPythonString(sConstant)) throw UtlException(script, "constant string expected");
1120 				listOfConstants.push_back(sConstant);
1121 				bTryVariable = bVariableAllowed;
1122 			} else if (script.isEqualTo('\'')) {
1123 				script.goBack();
1124 				int iChar;
1125 				if (!script.readCharLiteral(iChar)) throw UtlException(script, "char literal expected");
1126 				listOfConstants.push_back(std::string(1, (unsigned char) iChar));
1127 				bTryVariable = bVariableAllowed;
1128 			} else if (script.isEqualTo('{')) {
1129 				do {
1130 					script.skipEmpty();
1131 					std::string sConstant;
1132 					if (!script.readStringOrCharLiteral(sConstant)) throw UtlException(script, "constant string expected");
1133 					listOfConstants.push_back(sConstant);
1134 					script.skipEmpty();
1135 				} while (script.isEqualTo(','));
1136 				if (!script.isEqualTo('}')) throw UtlException(script, "'}' expected to close a set of constant strings");
1137 				bTryVariable = bVariableAllowed;
1138 			} else if (bVariableAllowed) {
1139 				bConcatVariable = script.isEqualTo('+');
1140 				if (hasTargetLanguage()) {
1141 					pVariableExpr = parseAlienVariableExpression(block, script);
1142 				} else {
1143 					pVariableExpr = parseBNFVariableExpression(block, script);
1144 				}
1145 			} else {
1146 				script.setInputLocation(iLocation);
1147 			}
1148 			if (bTryVariable) {
1149 				script.skipEmpty();
1150 				if (script.isEqualTo(':')) {
1151 					bConcatVariable = script.isEqualTo('+');
1152 					if (hasTargetLanguage()) {
1153 						pVariableExpr = parseAlienVariableExpression(block, script);
1154 					} else {
1155 						pVariableExpr = parseBNFVariableExpression(block, script);
1156 					}
1157 				}
1158 			}
1159 		}
1160 		return pVariableExpr;
1161 	}
1162 
parseBNFLitteral(ScpStream & script,BNFClause & rule,GrfBlock & block,bool & bContinue,bool & bNoCase,bool bLiteralOnly,BNFStepper * pStepperRE)1163 	bool DtaBNFScript::parseBNFLitteral(ScpStream& script, BNFClause& rule, GrfBlock& block, bool& bContinue, bool& bNoCase, bool bLiteralOnly, BNFStepper* pStepperRE) {
1164 		bool bSuccess = true;
1165 		script.skipEmpty();
1166 		if (script.isEqualTo('\"')) {
1167 			script.goBack();
1168 			std::string sText;
1169 			if (!script.readPythonString(sText)) throw UtlException(script, "string literal expected into BNF clause definition");
1170 			BNFString* pString = new BNFString(this, &block, sText, bContinue, bNoCase);
1171 			if (requiresParsingInformation()) pString->setParsingInformation(getFilenamePtr(), script);
1172 			block.add(pString);
1173 			std::vector<std::string> listOfConstants;
1174 			bool bConcat;
1175 			ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly);
1176 			pString->setVariableToAssign(pVarToAssign, bConcat, rule);
1177 			if (!listOfConstants.empty()) throw UtlException(script, "it has no sense to match a string literal with a constant string");
1178 		} else if (script.isEqualTo('\'')) {
1179 			script.goBack();
1180 			int iChar;
1181 			if (!script.readCharLiteral(iChar)) throw UtlException(script, "char literal expected (between quotes)");
1182 			script.skipEmpty();
1183 			if (script.isEqualTo("..")) {
1184 				script.skipEmpty();
1185 				int iEndChar;
1186 				if (!script.readCharLiteral(iEndChar)) throw UtlException(script, "char literal expected (between quotes) after '..'");
1187 				if (iChar > iEndChar) throw UtlException(script, "range expression '..' must be ordered correctly");
1188 				BNFCharBoundaries* pCharBoundaries = new BNFCharBoundaries(this, &block, iChar, iEndChar, bContinue, bNoCase);
1189 				if (requiresParsingInformation()) pCharBoundaries->setParsingInformation(getFilenamePtr(), script);
1190 				block.add(pCharBoundaries);
1191 				std::vector<std::string> listOfConstants;
1192 				bool bConcat;
1193 				ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly);
1194 				pCharBoundaries->setVariableToAssign(pVarToAssign, bConcat, rule);
1195 				if (!listOfConstants.empty()) pCharBoundaries->setConstantsToMatch(listOfConstants);
1196 			} else {
1197 				BNFCharLitteral* pCharLitteral = new BNFCharLitteral(this, &block, iChar, bContinue, bNoCase);
1198 				if (requiresParsingInformation()) pCharLitteral->setParsingInformation(getFilenamePtr(), script);
1199 				block.add(pCharLitteral);
1200 				std::vector<std::string> listOfConstants;
1201 				bool bConcat;
1202 				ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly);
1203 				pCharLitteral->setVariableToAssign(pVarToAssign, bConcat, rule);
1204 				if (!listOfConstants.empty()) throw UtlException(script, "a char literal shouldn't expect a set of constant values");
1205 			}
1206 		} else if (script.isEqualTo('~') || script.isEqualTo('^')) {
1207 			BNFComplementary* pComplementary = new BNFComplementary(this, &block, bContinue);
1208 			if (requiresParsingInformation()) pComplementary->setParsingInformation(getFilenamePtr(), script);
1209 			block.add(pComplementary);
1210 			bool bNextContinue = false;
1211 			bool bNextNoCase = bNoCase;
1212 			parseBNFLitteral(script, rule, *pComplementary, bNextContinue, bNextNoCase, true /* if '=>' or ':<variable>' after reading this literal, it doesn't belong to it */, pComplementary);
1213 			std::vector<std::string> listOfConstants;
1214 			bool bConcat;
1215 			ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly);
1216 			pComplementary->setVariableToAssign(pVarToAssign, bConcat, rule);
1217 			if (!listOfConstants.empty()) pComplementary->setConstantsToMatch(listOfConstants);
1218 		} else if (script.isEqualTo("->")) {
1219 			BNFFindToken* pFindToken = new BNFFindToken(this, &block, bContinue);
1220 			if (requiresParsingInformation()) pFindToken->setParsingInformation(getFilenamePtr(), script);
1221 			block.add(pFindToken);
1222 			bool bConcat;
1223 			ExprScriptVariable* pVarToAssign;
1224 			BNFMultiplicityBoundaries* pBoundaries = parseMultiplicity(script, block);
1225 			if (pBoundaries != NULL) {
1226 				pFindToken->setBoundaries(pBoundaries);
1227 				script.skipEmpty();
1228 			}
1229 			if (script.isEqualTo('(')) {
1230 				std::vector<std::string> listOfIntermediateConstants;
1231 				pVarToAssign = parseLiteralAssignment(script, block, listOfIntermediateConstants, bConcat, true);
1232 				pFindToken->setIntermediateVariableToAssign(pVarToAssign, bConcat, rule);
1233 				if (!listOfIntermediateConstants.empty()) pFindToken->setIntermediateConstantsToMatch(listOfIntermediateConstants);
1234 				script.skipEmpty();
1235 				if (script.isEqualTo('-')) {
1236 					std::vector<std::string> listOfFinalConstants;
1237 					pVarToAssign = parseLiteralAssignment(script, block, listOfFinalConstants, bConcat, true);
1238 					pFindToken->setFinalVariableToAssign(pVarToAssign, bConcat, rule);
1239 					if (!listOfFinalConstants.empty()) pFindToken->setFinalConstantsToMatch(listOfFinalConstants);
1240 					script.skipEmpty();
1241 				}
1242 				if (!script.isEqualTo(')')) {
1243 					parseBNFDisjunction(script, rule, pFindToken->createIntermediateSequence(), bNoCase, pStepperRE);
1244 					if (!script.isEqualTo(')')) throw UtlException(script, "')' expected");
1245 				}
1246 			}
1247 			bool bNextContinue = false;
1248 			bool bNextNoCase = bNoCase;
1249 			parseBNFLitteral(script, rule, *pFindToken, bNextContinue, bNextNoCase, true /* if '=>' or ':<variable>' after reading this literal, it doesn't belong to it */, pFindToken);
1250 			std::vector<std::string> listOfConstants;
1251 			pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly);
1252 			pFindToken->setVariableToAssign(pVarToAssign, bConcat, rule);
1253 			if (!listOfConstants.empty()) pFindToken->setConstantsToMatch(listOfConstants);
1254 		} else if (script.isEqualTo('!')) {
1255 			BNFNot* pNot = new BNFNot(this, &block, bContinue);
1256 			if (requiresParsingInformation()) pNot->setParsingInformation(getFilenamePtr(), script);
1257 			block.add(pNot);
1258 			bool bNextContinue = false;
1259 			bool bNextNoCase = bNoCase;
1260 			parseBNFLitteral(script, rule, *pNot, bNextContinue, bNextNoCase, true /* if '=>' or ':<variable>' after reading this literal, it doesn't belong to it */, pStepperRE);
1261 		} else if (script.isEqualTo('[')) {
1262 			BNFMultiplicity* pMultiplicity = new BNFMultiplicity(this, &block, bContinue);
1263 			if (requiresParsingInformation()) pMultiplicity->setParsingInformation(getFilenamePtr(), script);
1264 			block.add(pMultiplicity);
1265 			parseBNFDisjunction(script, rule, *pMultiplicity, bNoCase, pStepperRE);
1266 			if (!script.isEqualTo(']')) throw UtlException(script, "']' expected into BNF clause definition");
1267 			parseMultiplicity(script, block, &pMultiplicity->getBoundaries());
1268 			std::vector<std::string> listOfConstants;
1269 			bool bConcat;
1270 			ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly);
1271 			pMultiplicity->setVariableToAssign(pVarToAssign, bConcat, rule);
1272 			if (!listOfConstants.empty()) pMultiplicity->setConstantsToMatch(listOfConstants);
1273 		} else if (script.isEqualTo('#')) {
1274 			int iSharpLocation = script.getInputLocation() - 1;
1275 			std::string sIdentifier;
1276 			if (!script.readIdentifier(sIdentifier)) {
1277 				if (script.isEqualTo('!') && script.readIdentifier(sIdentifier)) {
1278 					if (sIdentifier == "ignore") {
1279 						BNFIgnore* pIgnore = new BNFIgnore(this, &block, NOT_IGNORE, NULL);
1280 						if (requiresParsingInformation()) pIgnore->setParsingInformation(getFilenamePtr(), script);
1281 						block.add(pIgnore);
1282 						while (parseBNFLitteral(script, rule, *pIgnore, bContinue, bNoCase, false /* if '=>' or ':<variable>' after reading this literal, it belongs to it */, pStepperRE)) ;
1283 					} else {
1284 						throw UtlException(script, "macro instruction '#!" + sIdentifier + "' doesn't exist");
1285 					}
1286 				} else {
1287 					throw UtlException(script, "macro instruction expected after '#'");
1288 				}
1289 			} else if (sIdentifier == "catch") {
1290 				script.setInputLocation(iSharpLocation);
1291 				return false;
1292 			} else if (sIdentifier == "continue") {
1293 				bool bNextContinue = true;
1294 				script.skipEmpty();
1295 				if (script.isEqualTo('(')) {
1296 					script.skipEmpty();
1297 					std::string sVariableName;
1298 					if (!script.readIdentifier(sVariableName)) throw UtlException(script, "variable name expected to catch the original syntax error");
1299 					if (block.getVariable(sVariableName) == UNKNOWN_EXPRTYPE) block.addBNFLocalVariable(sVariableName, VALUE_EXPRTYPE);
1300 					script.skipEmpty();
1301 					if (!script.isEqualTo(',')) throw UtlException(script, "',' expected");
1302 					std::auto_ptr<ExprScriptExpression> pErrorMessageExpr(parseExpression(block, script));
1303 					script.skipEmpty();
1304 					if (!script.isEqualTo(')')) throw UtlException(script, "')' expected to close the expression of '#continue'");
1305 					BNFContinue* pBNFContinue = new BNFContinue(this, &block, new ExprScriptVariable(sVariableName.c_str()), pErrorMessageExpr.release());
1306 					if (requiresParsingInformation()) pBNFContinue->setParsingInformation(getFilenamePtr(), script);
1307 					block.add(pBNFContinue);
1308 					while (parseBNFLitteral(script, rule, *pBNFContinue->getTryBlock(), bNextContinue, bNoCase, false /* if '=>' or ':<variable>' after reading this literal, it belongs to it */, pStepperRE)) ;
1309 				} else {
1310 					while (parseBNFLitteral(script, rule, block, bNextContinue, bNoCase, false /* if '=>' or ':<variable>' after reading this literal, it belongs to it */, pStepperRE)) ;
1311 				}
1312 			} else if (sIdentifier == "noCase") {
1313 				bool bNextNoCase = true;
1314 				while (parseBNFLitteral(script, rule, block, bContinue, bNextNoCase, false /* if '=>' or ':<variable>' after reading this literal, it belongs to it */, pStepperRE)) ;
1315 			} else if (sIdentifier == "ratchet") {
1316 				BNFRatchet* pBNFRatchet = new BNFRatchet(this, &block);
1317 				if (requiresParsingInformation()) pBNFRatchet->setParsingInformation(getFilenamePtr(), script);
1318 				block.add(pBNFRatchet);
1319 				while (parseBNFLitteral(script, rule, block, bContinue, bNoCase, false /* if '=>' or ':<variable>' after reading this literal, it belongs to it */, pStepperRE)) ;
1320 			} else if (sIdentifier == "try") {
1321 				BNFTryCatch* pBNFTryCatch = new BNFTryCatch(this, &block);
1322 				if (requiresParsingInformation()) pBNFTryCatch->setParsingInformation(getFilenamePtr(), script);
1323 				block.add(pBNFTryCatch);
1324 				do {
1325 					script.skipEmpty();
1326 					if (script.isEqualTo('#')) {
1327 						int iLocation = script.getInputLocation();
1328 						script.skipEmpty();
1329 						if (script.isEqualTo("catch")) {
1330 							script.skipEmpty();
1331 							if (!script.isEqualTo('(')) throw UtlException(script, "syntax error, directive '#catch' expects a '('");
1332 							script.skipEmpty();
1333 							std::string sVariableName;
1334 							if (!script.readIdentifier(sVariableName)) throw UtlException(script, "variable name expected to catch the error message");
1335 							if (block.getVariable(sVariableName) == UNKNOWN_EXPRTYPE) block.addBNFLocalVariable(sVariableName, VALUE_EXPRTYPE);
1336 							pBNFTryCatch->setErrorVariable(parseVariableExpression(block, script, new ExprScriptVariable(sVariableName.c_str())));
1337 							script.skipEmpty();
1338 							if (!script.isEqualTo(')')) throw UtlException(script, "syntax error, directive '#catch' expects a ')'");
1339 							break;
1340 						} else {
1341 							script.setInputLocation(iLocation - 1);
1342 						}
1343 					} else {
1344 						script.goBack();
1345 					}
1346 				} while (parseBNFLitteral(script, rule, *pBNFTryCatch->getTryBlock(), bContinue, bNoCase, false /* if '=>' or ':<variable>' after reading this literal, it belongs to it */, pStepperRE));
1347 				if (pBNFTryCatch->getErrorVariable() == NULL) throw UtlException(script, "directive '#catch' expected before the end of the sequence");
1348 			} else if (sIdentifier == "parsedFile") {
1349 				script.skipEmpty();
1350 				if (!isAParseScript()) throw UtlException(script, "directive '#parsedFile' is available on parsing scripts only");
1351 				GrfParsedFile* pParsedFile = new GrfParsedFile(&block);
1352 				if (requiresParsingInformation()) pParsedFile->setParsingInformation(getFilenamePtr(), script);
1353 				block.add(pParsedFile);
1354 				if (!script.isEqualTo('(')) throw UtlException(script, "'(' expected by clause '#parsedFile'");
1355 				script.skipEmpty();
1356 				pParsedFile->setInputFile(parseExpression(block, script));
1357 				script.skipEmpty();
1358 				if (!script.isEqualTo(')')) throw UtlException(script, "')' expected by clause '#parsedFile'");
1359 				while (parseBNFLitteral(script, rule, *pParsedFile, bContinue, bNoCase, false /* if '=>' or ':<variable>' after reading this literal, it belongs to it */, pStepperRE)) ;
1360 			} else if (sIdentifier == "parsedString") {
1361 				script.skipEmpty();
1362 				if (!isAParseScript()) throw UtlException(script, "directive '#parsedString' is available on parsing scripts only");
1363 				GrfParsedString* pParsedString = new GrfParsedString(&block);
1364 				if (requiresParsingInformation()) pParsedString->setParsingInformation(getFilenamePtr(), script);
1365 				block.add(pParsedString);
1366 				if (!script.isEqualTo('(')) throw UtlException(script, "'(' expected by clause '#parsedString'");
1367 				script.skipEmpty();
1368 				pParsedString->setInputString(parseExpression(block, script));
1369 				script.skipEmpty();
1370 				if (!script.isEqualTo(')')) throw UtlException(script, "')' expected by clause '#parsedString'");
1371 				while (parseBNFLitteral(script, rule, *pParsedString, bContinue, bNoCase, false /* if '=>' or ':<variable>' after reading this literal, it belongs to it */, pStepperRE)) ;
1372 			} else if (sIdentifier == "generatedFile") {
1373 				script.skipEmpty();
1374 				if (!isAGenerateScript()) throw UtlException(script, "directive '#generatedFile' is available on pattern scripts only");
1375 				GrfGeneratedFile* pGeneratedFile = new GrfGeneratedFile(this, &block);
1376 				if (requiresParsingInformation()) pGeneratedFile->setParsingInformation(getFilenamePtr(), script);
1377 				block.add(pGeneratedFile);
1378 				if (!script.isEqualTo('(')) throw UtlException(script, "'(' expected by clause '#generatedFile'");
1379 				script.skipEmpty();
1380 				pGeneratedFile->setOutputFile(parseExpression(block, script));
1381 				script.skipEmpty();
1382 				if (!script.isEqualTo(')')) throw UtlException(script, "')' expected by clause '#generatedFile'");
1383 				while (parseBNFLitteral(script, rule, *pGeneratedFile, bContinue, bNoCase, false /* if '=>' or ':<variable>' after reading this literal, it belongs to it */, pStepperRE)) ;
1384 			} else if (sIdentifier == "generatedString") {
1385 				script.skipEmpty();
1386 				if (!isAGenerateScript()) throw UtlException(script, "directive '#generatedString' is available on pattern scripts only");
1387 				GrfGeneratedString* pGeneratedString = new GrfGeneratedString(this, &block);
1388 				if (requiresParsingInformation()) pGeneratedString->setParsingInformation(getFilenamePtr(), script);
1389 				block.add(pGeneratedString);
1390 				if (!script.isEqualTo('(')) throw UtlException(script, "'(' expected by clause '#generatedString'");
1391 				script.skipEmpty();
1392 				pGeneratedString->setOutputString(parseVariableExpression(block, script));
1393 				script.skipEmpty();
1394 				if (!script.isEqualTo(')')) throw UtlException(script, "')' expected by clause '#generatedString'");
1395 				while (parseBNFLitteral(script, rule, *pGeneratedString, bContinue, bNoCase, false /* if '=>' or ':<variable>' after reading this literal, it belongs to it */, pStepperRE)) ;
1396 			} else if (sIdentifier == "appendedFile") {
1397 				script.skipEmpty();
1398 				if (!isAGenerateScript()) throw UtlException(script, "statement modifier 'append_file' is available on pattern scripts only");
1399 				GrfAppendedFile* pAppendedFile = new GrfAppendedFile(this, &block);
1400 				if (requiresParsingInformation()) pAppendedFile->setParsingInformation(getFilenamePtr(), script);
1401 				block.add(pAppendedFile);
1402 				if (!script.isEqualTo('(')) throw UtlException(script, "'(' expected by clause '#appendedFile'");
1403 				script.skipEmpty();
1404 				pAppendedFile->setOutputFile(parseExpression(block, script));
1405 				script.skipEmpty();
1406 				if (!script.isEqualTo(')')) throw UtlException(script, "')' expected by clause '#appendedFile'");
1407 				while (parseBNFLitteral(script, rule, *pAppendedFile, bContinue, bNoCase, false /* if '=>' or ':<variable>' after reading this literal, it belongs to it */, pStepperRE)) ;
1408 			} else if (sIdentifier == "debug") {
1409 				GrfDebugExecution* pDebug = new GrfDebugExecution(&block);
1410 				if (requiresParsingInformation()) pDebug->setParsingInformation(getFilenamePtr(), script);
1411 				block.add(pDebug);
1412 				while (parseBNFLitteral(script, rule, *pDebug, bContinue, bNoCase, false /* if '=>' or ':<variable>' after reading this literal, it belongs to it */, pStepperRE)) ;
1413 			} else if (sIdentifier == "ignore") {
1414 				BNFClause* pIgnoreClause = NULL;
1415 				IGNORE_MODE eMode = parseIgnoreMode(script, pIgnoreClause);
1416 				BNFIgnore* pIgnore = new BNFIgnore(this, &block, eMode, pIgnoreClause);
1417 				if (requiresParsingInformation()) pIgnore->setParsingInformation(getFilenamePtr(), script);
1418 				block.add(pIgnore);
1419 				while (parseBNFLitteral(script, rule, *pIgnore, bContinue, bNoCase, false /* if '=>' or ':<variable>' after reading this literal, it belongs to it */, pStepperRE)) ;
1420 			} else if (sIdentifier == "nextStep") {
1421 				if (pStepperRE == NULL) throw UtlException(script, "'#nextStep' must be declared into a jump ('->') or repeat ('[...]*') statement");
1422 				BNFNextStep* pNextStep = new BNFNextStep(this, &block, pStepperRE);
1423 				if (requiresParsingInformation()) pNextStep->setParsingInformation(getFilenamePtr(), script);
1424 				block.add(pNextStep);
1425 			} else if (sIdentifier == "break") {
1426 				BNFBreak* pBreak = new BNFBreak(&block);
1427 				if (requiresParsingInformation()) pBreak->setParsingInformation(getFilenamePtr(), script);
1428 				block.add(pBreak);
1429 				script.skipEmpty();
1430 				if (script.isEqualTo('(')) {
1431 					pBreak->setCondition(parseExpression(block, script));
1432 					if (!script.isEqualTo(')')) throw UtlException(script, "')' expected to close the expression of '#break'");
1433 				}
1434 			} else if (sIdentifier == "empty") {
1435 				BNFEndOfFile* pEndOfFile = new BNFEndOfFile(this, &block, bContinue);
1436 				if (requiresParsingInformation()) pEndOfFile->setParsingInformation(getFilenamePtr(), script);
1437 				block.add(pEndOfFile);
1438 			} else if (sIdentifier == "pushItem") {
1439 				BNFPushItem* pPushItem = new BNFPushItem(this, &block);
1440 				if (requiresParsingInformation()) pPushItem->setParsingInformation(getFilenamePtr(), script);
1441 				block.add(pPushItem);
1442 				script.skipEmpty();
1443 				if (!script.isEqualTo('(')) throw UtlException(script, "'(' expected after '#pushItem' to pass the array");
1444 				pPushItem->setVariable(parseVariableExpression(block, script));
1445 				if (!script.isEqualTo(')')) throw UtlException(script, "')' expected after passing the array to '#pushItem'");
1446 				parseBNFSequence(script, rule, *pPushItem, bContinue, bNoCase, pStepperRE);
1447 			} else if (sIdentifier == "insert") {
1448 				BNFInsert* pInsert = new BNFInsert(this, &block);
1449 				if (requiresParsingInformation()) pInsert->setParsingInformation(getFilenamePtr(), script);
1450 				block.add(pInsert);
1451 				script.skipEmpty();
1452 				if (!script.isEqualTo('(')) throw UtlException(script, "'(' expected after '#insert' to pass the array");
1453 				pInsert->setVariable(parseVariableExpression(block, script));
1454 				if (!script.isEqualTo(')')) throw UtlException(script, "')' expected after passing the array to '#insert'");
1455 				parseBNFSequence(script, rule, *pInsert, bContinue, bNoCase, pStepperRE);
1456 			} else if (sIdentifier == "EOL") {
1457 				BNFEndOfLine* pEndOfLine = new BNFEndOfLine(this, &block, bContinue);
1458 				if (requiresParsingInformation()) pEndOfLine->setParsingInformation(getFilenamePtr(), script);
1459 				block.add(pEndOfLine);
1460 				std::vector<std::string> listOfConstants;
1461 				bool bConcat;
1462 				ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly);
1463 				pEndOfLine->setVariableToAssign(pVarToAssign, bConcat, rule);
1464 				if (!listOfConstants.empty()) pEndOfLine->setConstantsToMatch(listOfConstants);
1465 			} else if (sIdentifier == "readChar") {
1466 				BNFReadChar* pReadChar = new BNFReadChar(this, &block, bContinue);
1467 				if (requiresParsingInformation()) pReadChar->setParsingInformation(getFilenamePtr(), script);
1468 				block.add(pReadChar);
1469 				std::vector<std::string> listOfConstants;
1470 				bool bConcat;
1471 				ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly);
1472 				pReadChar->setVariableToAssign(pVarToAssign, bConcat, rule);
1473 				if (!listOfConstants.empty()) pReadChar->setConstantsToMatch(listOfConstants);
1474 			} else if (sIdentifier == "readByte") {
1475 				BNFReadByte* pReadByte = new BNFReadByte(this, &block, bContinue);
1476 				if (requiresParsingInformation()) pReadByte->setParsingInformation(getFilenamePtr(), script);
1477 				block.add(pReadByte);
1478 				std::vector<std::string> listOfConstants;
1479 				bool bConcat;
1480 				ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly);
1481 				pReadByte->setVariableToAssign(pVarToAssign, bConcat, rule);
1482 				if (!listOfConstants.empty()) pReadByte->setConstantsToMatch(listOfConstants);
1483 			} else if (sIdentifier == "readAdaString") {
1484 				BNFReadAdaString* pReadAdaString = new BNFReadAdaString(this, &block, bContinue, bNoCase);
1485 				if (requiresParsingInformation()) pReadAdaString->setParsingInformation(getFilenamePtr(), script);
1486 				block.add(pReadAdaString);
1487 				std::vector<std::string> listOfConstants;
1488 				bool bConcat;
1489 				ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly);
1490 				pReadAdaString->setVariableToAssign(pVarToAssign, bConcat, rule);
1491 				if (!listOfConstants.empty()) pReadAdaString->setConstantsToMatch(listOfConstants);
1492 			} else if (sIdentifier == "readCString") {
1493 				BNFReadCString* pReadCString = new BNFReadCString(this, &block, bContinue, bNoCase);
1494 				if (requiresParsingInformation()) pReadCString->setParsingInformation(getFilenamePtr(), script);
1495 				block.add(pReadCString);
1496 				std::vector<std::string> listOfConstants;
1497 				bool bConcat;
1498 				ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly);
1499 				pReadCString->setVariableToAssign(pVarToAssign, bConcat, rule);
1500 				if (!listOfConstants.empty()) pReadCString->setConstantsToMatch(listOfConstants);
1501 			} else if (sIdentifier == "readCChar") {
1502 				BNFReadCChar* pReadCChar = new BNFReadCChar(this, &block, bContinue, bNoCase);
1503 				if (requiresParsingInformation()) pReadCChar->setParsingInformation(getFilenamePtr(), script);
1504 				block.add(pReadCChar);
1505 				std::vector<std::string> listOfConstants;
1506 				bool bConcat;
1507 				ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly);
1508 				pReadCChar->setVariableToAssign(pVarToAssign, bConcat, rule);
1509 				if (!listOfConstants.empty()) pReadCChar->setConstantsToMatch(listOfConstants);
1510 			} else if (sIdentifier == "readPythonString") {
1511 				BNFReadPythonString* pReadPythonString = new BNFReadPythonString(this, &block, bContinue, bNoCase);
1512 				if (requiresParsingInformation()) pReadPythonString->setParsingInformation(getFilenamePtr(), script);
1513 				block.add(pReadPythonString);
1514 				std::vector<std::string> listOfConstants;
1515 				bool bConcat;
1516 				ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly);
1517 				pReadPythonString->setVariableToAssign(pVarToAssign, bConcat, rule);
1518 				if (!listOfConstants.empty()) pReadPythonString->setConstantsToMatch(listOfConstants);
1519 			} else if (sIdentifier == "readIdentifier") {
1520 				BNFReadIdentifier* pReadIdentifier = new BNFReadIdentifier(this, &block, bContinue, bNoCase);
1521 				if (requiresParsingInformation()) pReadIdentifier->setParsingInformation(getFilenamePtr(), script);
1522 				block.add(pReadIdentifier);
1523 				std::vector<std::string> listOfConstants;
1524 				bool bConcat;
1525 				ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly);
1526 				pReadIdentifier->setVariableToAssign(pVarToAssign, bConcat, rule);
1527 				if (!listOfConstants.empty()) pReadIdentifier->setConstantsToMatch(listOfConstants);
1528 			} else if (sIdentifier == "readCompleteIdentifier") {
1529 				BNFReadCompleteIdentifier* pReadCompleteIdentifier = new BNFReadCompleteIdentifier(this, &block, bContinue, bNoCase);
1530 				if (requiresParsingInformation()) pReadCompleteIdentifier->setParsingInformation(getFilenamePtr(), script);
1531 				block.add(pReadCompleteIdentifier);
1532 				std::vector<std::string> listOfConstants;
1533 				bool bConcat;
1534 				ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly);
1535 				pReadCompleteIdentifier->setVariableToAssign(pVarToAssign, bConcat, rule);
1536 				if (!listOfConstants.empty()) pReadCompleteIdentifier->setConstantsToMatch(listOfConstants);
1537 			} else if (sIdentifier == "readInteger") {
1538 				BNFReadInteger* pReadInteger = new BNFReadInteger(this, &block, bContinue, bNoCase);
1539 				if (requiresParsingInformation()) pReadInteger->setParsingInformation(getFilenamePtr(), script);
1540 				block.add(pReadInteger);
1541 				std::vector<std::string> listOfConstants;
1542 				bool bConcat;
1543 				ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly);
1544 				pReadInteger->setVariableToAssign(pVarToAssign, bConcat, rule);
1545 				if (!listOfConstants.empty()) pReadInteger->setConstantsToMatch(listOfConstants);
1546 			} else if (sIdentifier == "readNumeric") {
1547 				BNFReadNumeric* pReadNumeric = new BNFReadNumeric(this, &block, bContinue, bNoCase);
1548 				if (requiresParsingInformation()) pReadNumeric->setParsingInformation(getFilenamePtr(), script);
1549 				block.add(pReadNumeric);
1550 				std::vector<std::string> listOfConstants;
1551 				bool bConcat;
1552 				ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly);
1553 				pReadNumeric->setVariableToAssign(pVarToAssign, bConcat, rule);
1554 				if (!listOfConstants.empty()) pReadNumeric->setConstantsToMatch(listOfConstants);
1555 			} else if (sIdentifier == "readText") {
1556 				BNFReadText* pReadText = new BNFReadText(this, &block, bContinue, bNoCase);
1557 				if (requiresParsingInformation()) pReadText->setParsingInformation(getFilenamePtr(), script);
1558 				block.add(pReadText);
1559 				script.skipEmpty();
1560 				if (!script.isEqualTo('(')) throw UtlException(script, "'(' expected by clause '#readText'");
1561 				pReadText->setText(parseExpression(block, script));
1562 				if (!script.isEqualTo(')')) throw UtlException(script, "')' expected by clause '#readText'");
1563 				std::vector<std::string> listOfConstants;
1564 				bool bConcat;
1565 				ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly);
1566 				pReadText->setVariableToAssign(pVarToAssign, bConcat, rule);
1567 				if (!listOfConstants.empty()) pReadText->setConstantsToMatch(listOfConstants);
1568 			} else if (sIdentifier == "readBytes") {
1569 				BNFReadBytes* pReadBytes = new BNFReadBytes(this, &block, bContinue, bNoCase);
1570 				if (requiresParsingInformation()) pReadBytes->setParsingInformation(getFilenamePtr(), script);
1571 				block.add(pReadBytes);
1572 				script.skipEmpty();
1573 				if (!script.isEqualTo('(')) throw UtlException(script, "'(' expected by clause '#readBytes'");
1574 				pReadBytes->setLength(parseExpression(block, script));
1575 				if (!script.isEqualTo(')')) throw UtlException(script, "')' expected by clause '#readBytes'");
1576 				std::vector<std::string> listOfConstants;
1577 				bool bConcat;
1578 				ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly);
1579 				pReadBytes->setVariableToAssign(pVarToAssign, bConcat, rule);
1580 				if (!listOfConstants.empty()) pReadBytes->setConstantsToMatch(listOfConstants);
1581 			} else if (sIdentifier == "readChars") {
1582 				BNFReadChars* pReadChars = new BNFReadChars(this, &block, bContinue, bNoCase);
1583 				if (requiresParsingInformation()) pReadChars->setParsingInformation(getFilenamePtr(), script);
1584 				block.add(pReadChars);
1585 				script.skipEmpty();
1586 				if (!script.isEqualTo('(')) throw UtlException(script, "'(' expected by clause '#readChars'");
1587 				pReadChars->setLength(parseExpression(block, script));
1588 				if (!script.isEqualTo(')')) throw UtlException(script, "')' expected by clause '#readChars'");
1589 				std::vector<std::string> listOfConstants;
1590 				bool bConcat;
1591 				ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly);
1592 				pReadChars->setVariableToAssign(pVarToAssign, bConcat, rule);
1593 				if (!listOfConstants.empty()) pReadChars->setConstantsToMatch(listOfConstants);
1594 			} else if (sIdentifier == "readUptoIgnore") {
1595 				BNFClause* pIgnoreClause = NULL;
1596 				IGNORE_MODE eMode;
1597 				script.skipEmpty();
1598 				if (script.peekChar() == '(') {
1599 					eMode = parseIgnoreMode(script, pIgnoreClause);
1600 				} else {
1601 					eMode = UNDEFINED_IGNORE;
1602 				}
1603 				BNFReadUptoIgnore* pReadUptoIgnore = new BNFReadUptoIgnore(this, &block, eMode, pIgnoreClause, bContinue);
1604 				if (requiresParsingInformation()) pReadUptoIgnore->setParsingInformation(getFilenamePtr(), script);
1605 				block.add(pReadUptoIgnore);
1606 				script.skipEmpty();
1607 				std::vector<std::string> listOfConstants;
1608 				bool bConcat;
1609 				ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly);
1610 				pReadUptoIgnore->setVariableToAssign(pVarToAssign, bConcat, rule);
1611 				if (!listOfConstants.empty()) pReadUptoIgnore->setConstantsToMatch(listOfConstants);
1612 			} else if (sIdentifier == "skipIgnore") {
1613 				BNFClause* pIgnoreClause = NULL;
1614 				IGNORE_MODE eMode;
1615 				script.skipEmpty();
1616 				if (script.peekChar() == '(') {
1617 					eMode = parseIgnoreMode(script, pIgnoreClause);
1618 				} else {
1619 					eMode = UNDEFINED_IGNORE;
1620 				}
1621 				BNFSkipIgnore* pSkipIgnore = new BNFSkipIgnore(this, &block, eMode, pIgnoreClause, bContinue);
1622 				if (requiresParsingInformation()) pSkipIgnore->setParsingInformation(getFilenamePtr(), script);
1623 				block.add(pSkipIgnore);
1624 				std::vector<std::string> listOfConstants;
1625 				bool bConcat;
1626 				ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly);
1627 				pSkipIgnore->setVariableToAssign(pVarToAssign, bConcat, rule);
1628 				if (!listOfConstants.empty()) pSkipIgnore->setConstantsToMatch(listOfConstants);
1629 			} else if (sIdentifier == "moveAhead") {
1630 				BNFMoveAhead* pMoveAhead = new BNFMoveAhead(&block, bContinue);
1631 				if (requiresParsingInformation()) pMoveAhead->setParsingInformation(getFilenamePtr(), script);
1632 				block.add(pMoveAhead);
1633 			} else if (sIdentifier == "check") {
1634 				BNFCheck* pCheck = new BNFCheck(this, &block, bContinue);
1635 				if (requiresParsingInformation()) pCheck->setParsingInformation(getFilenamePtr(), script);
1636 				block.add(pCheck);
1637 				script.skipEmpty();
1638 				if (!script.isEqualTo('(')) throw UtlException(script, "'(' expected by directive '#check'");
1639 				pCheck->setCondition(parseExpression(block, script));
1640 				if (!script.isEqualTo(')')) throw UtlException(script, "')' expected by directive '#check'");
1641 			} else if (sIdentifier == "foreach") {
1642 				BNFForeach* pForeach = new BNFForeach(this, &block, bContinue);
1643 				if (requiresParsingInformation()) pForeach->setParsingInformation(getFilenamePtr(), script);
1644 				block.add(pForeach);
1645 				script.skipEmpty();
1646 				if (!script.isEqualTo('(')) throw UtlException(script, "'(' expected by directive '#foreach'");
1647 				parseForeachListDeclaration(block, script, pForeach);
1648 				script.skipEmpty();
1649 				if (!script.isEqualTo(')')) throw UtlException(script, "')' expected by directive '#foreach'");
1650 				while (parseBNFLitteral(script, rule, *pForeach, bContinue, bNoCase, false /* if '=>' or ':<variable>' after reading this literal, it belongs to it */, pStepperRE)) ;
1651 			} else if (sIdentifier == "super") {
1652 				int iSuperClause = 0;
1653 				std::string sIdentifier;
1654 				for (;;) {
1655 					iSuperClause++;
1656 					script.skipEmpty();
1657 					if (!script.isEqualTo("::")) throw UtlException(script, "'::' expected by directive '#super'");
1658 					script.skipEmpty();
1659 					if (script.isEqualTo('#')) {
1660 						script.skipEmpty();
1661 						if (!script.isEqualToIdentifier("super")) throw UtlException(script, "'::#super' expected");
1662 					} else {
1663 						if (!script.readIdentifier(sIdentifier)) throw UtlException(script, "non-terminal call expected by directive '#super'");
1664 						break;
1665 					}
1666 				}
1667 				BNFClauseCall* pClauseCall = parseBNFClauseCall(script, block, sIdentifier, bContinue, bNoCase);
1668 				pClauseCall->setSuperCallDepth(iSuperClause);
1669 				if (requiresParsingInformation()) pClauseCall->setParsingInformation(getFilenamePtr(), script);
1670 				std::vector<std::string> listOfConstants;
1671 				bool bConcat;
1672 				ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly);
1673 				pClauseCall->setVariableToAssign(pVarToAssign, bConcat, rule);
1674 				if (!listOfConstants.empty()) pClauseCall->setConstantsToMatch(listOfConstants);
1675 			} else if ((sIdentifier.size() > 3) && (sIdentifier.substr(sIdentifier.size() - 3) == "AST")) {
1676 				ASTCommand* pCommand = NULL;
1677 				if (sIdentifier == "thisAST") pCommand = new ASTThisCommand(script);
1678 				else if (sIdentifier == "valueAST") pCommand = new ASTValueCommand(script);
1679 				else if (sIdentifier == "refAST") pCommand = new ASTRefCommand(script);
1680 				else if (sIdentifier == "slideAST") pCommand = new ASTSlideCommand(script);
1681 				else {
1682 					handleUnknownTokenDirective(sIdentifier, script, rule, block, bContinue, bNoCase, bLiteralOnly, pStepperRE);
1683 				}
1684 				if (pCommand != NULL) {
1685 					int iPos = block.getNbCommands();
1686 					parseBNFLitteral(script, rule, block, bContinue, bNoCase, bLiteralOnly, pStepperRE);
1687 					if (iPos == block.getNbCommands()) {
1688 						throw UtlException(script, "non-terminal call expected after an AST directive (#" + sIdentifier + " here)");
1689 					}
1690 					BNFClauseCall* pNonTerminal = dynamic_cast<BNFClauseCall*>(block.getCommand(iPos));
1691 					if (pNonTerminal == NULL) {
1692 						throw UtlException(script, "non-terminal call expected after an AST directive (#" + sIdentifier + " here)");
1693 					}
1694 					pNonTerminal->addASTCommand(pCommand);
1695 				}
1696 			} else {
1697 				handleUnknownTokenDirective(sIdentifier, script, rule, block, bContinue, bNoCase, bLiteralOnly, pStepperRE);
1698 			}
1699 		} else if (script.isEqualTo("=>")) {
1700 			_bBNFMode = false;
1701 			script.skipEmpty();
1702 			if (script.isEqualTo('{')) {
1703 				script.goBack();
1704 				GrfBlock* pBlock = new GrfBlock(&block);
1705 				if (requiresParsingInformation()) pBlock->setParsingInformation(getFilenamePtr(), script);
1706 				block.add(pBlock);
1707 				if (hasTargetLanguage()) {
1708 					parseAlienBlock(script, *pBlock);
1709 				} else {
1710 					parseBlock(script, *pBlock);
1711 				}
1712 			} else {
1713 				if (hasTargetLanguage()) {
1714 					parseAlienInstruction(script, block);
1715 				} else {
1716 					parseInstruction(script, block);
1717 				}
1718 			}
1719 			_bBNFMode = true;
1720 		} else {
1721 			std::string sIdentifier;
1722 			if (script.readIdentifier(sIdentifier)) {
1723 				BNFClauseCall* pClauseCall = parseBNFClauseCall(script, block, sIdentifier, bContinue, bNoCase);
1724 				if (requiresParsingInformation()) pClauseCall->setParsingInformation(getFilenamePtr(), script);
1725 				std::vector<std::string> listOfConstants;
1726 				bool bConcat;
1727 				ExprScriptVariable* pVarToAssign = parseLiteralAssignment(script, block, listOfConstants, bConcat, !bLiteralOnly);
1728 				pClauseCall->setVariableToAssign(pVarToAssign, bConcat, rule);
1729 				if (!listOfConstants.empty()) pClauseCall->setConstantsToMatch(listOfConstants);
1730 			} else {
1731 				bSuccess = false;
1732 			}
1733 		}
1734 		if (bSuccess && !bLiteralOnly) {
1735 			// binary BNF operators
1736 			script.skipEmpty();
1737 			if (script.isEqualTo("|>")) {
1738 				BNFScanWindow* pScanWindow = new BNFScanWindow(this, &block, bContinue);
1739 				if (requiresParsingInformation()) pScanWindow->setParsingInformation(getFilenamePtr(), script);
1740 				int iIndex = block.getNbCommands() - 1;
1741 				GrfCommand* pLeftMember = block.getCommand(iIndex);
1742 				block.setCommand(iIndex, pScanWindow);
1743 				pScanWindow->setWindow(pLeftMember);
1744 				bool bNextContinue = false;
1745 				bool bNextNoCase = bNoCase;
1746 				parseBNFLitteral(script, rule, *pScanWindow, bNextContinue, bNextNoCase, true /* if '=>' or ':<variable>' after reading this literal, it doesn't belong to it */, NULL);
1747 			} else if (script.isEqualTo("&|")) {
1748 				BNFAndOrJunction* pAndOrJunction = new BNFAndOrJunction(this, &block, bContinue);
1749 				if (requiresParsingInformation()) pAndOrJunction->setParsingInformation(getFilenamePtr(), script);
1750 				int iIndex = block.getNbCommands() - 1;
1751 				GrfCommand* pLeftMember = block.getCommand(iIndex);
1752 				block.setCommand(iIndex, pAndOrJunction);
1753 				pAndOrJunction->setLeftMember(pLeftMember);
1754 				bool bNextContinue = false;
1755 				bool bNextNoCase = bNoCase;
1756 				parseBNFLitteral(script, rule, *pAndOrJunction, bNextContinue, bNextNoCase, true /* if '=>' or ':<variable>' after reading this literal, it doesn't belong to it */, NULL);
1757 			}
1758 		}
1759 		return bSuccess;
1760 	}
1761 
parseBNFClauseCall(ScpStream & script,GrfBlock & block,const std::string & sClauseCallName,bool bContinue,bool bNoCase)1762 	BNFClauseCall* DtaBNFScript::parseBNFClauseCall(ScpStream& script, GrfBlock& block, const std::string& sClauseCallName, bool bContinue, bool bNoCase) {
1763 		BNFClauseCall* pClauseCall = new BNFClauseCall(this, &block, bContinue, bNoCase);
1764 		if (requiresParsingInformation()) pClauseCall->setParsingInformation(getFilenamePtr(), script);
1765 		block.add(pClauseCall);
1766 		script.skipEmpty();
1767 		if (script.isEqualTo('<')) {
1768 			ExprScriptExpression* pTemplateExpression = DtaScript::parseKeyTemplateExpression(block, script);
1769 			pClauseCall->setTemplateExpression(pTemplateExpression);
1770 			script.skipEmpty();
1771 			if (!script.isEqualTo('>')) throw UtlException(script, "'>' expected to end the template expression of clause call '" + sClauseCallName + "'");
1772 			script.skipEmpty();
1773 		}
1774 		if (script.isEqualTo('(')) {
1775 			do {
1776 				ExprScriptExpression* pParameterExpr = DtaScript::parseExpression(block, script);
1777 				pClauseCall->addParameter(pParameterExpr);
1778 				script.skipEmpty();
1779 			} while (script.isEqualTo(','));
1780 			if (!script.isEqualTo(')')) throw UtlException(script, "')' expected");
1781 		}
1782 		BNFClause& myClause = buildClause(script, block, sClauseCallName, pClauseCall->getParameters().size());
1783 		pClauseCall->setClause(&myClause);
1784 		return pClauseCall;
1785 	}
1786 
parseMultiplicity(ScpStream & script,GrfBlock & block,BNFMultiplicityBoundaries * boundaries)1787 	BNFMultiplicityBoundaries* DtaBNFScript::parseMultiplicity(ScpStream& script, GrfBlock& block, BNFMultiplicityBoundaries* boundaries) {
1788 		BNFMultiplicityBoundaries* pResult = NULL;
1789 		script.skipEmpty();
1790 		if (script.isEqualTo('*')) {
1791 			if (boundaries == NULL) boundaries = new BNFMultiplicityBoundaries;
1792 			pResult = boundaries;
1793 			boundaries->setMultiplicity(0, -1);
1794 		} else if (script.isEqualTo('+')) {
1795 			if (boundaries == NULL) boundaries = new BNFMultiplicityBoundaries;
1796 			pResult = boundaries;
1797 			boundaries->setMultiplicity(1, -1);
1798 		} else if (script.isEqualTo('?')) {
1799 			if (boundaries == NULL) boundaries = new BNFMultiplicityBoundaries;
1800 			pResult = boundaries;
1801 			boundaries->setMultiplicity(0, 1);
1802 		} else if (script.isEqualTo("#repeat")) {
1803 			script.skipEmpty();
1804 			if (!script.isEqualTo('(')) throw UtlException(script, "'(' expected after '#repeat'");
1805 			script.skipEmpty();
1806 			std::auto_ptr<ExprScriptExpression> pBegin(parseExpression(block, script));
1807 			script.skipEmpty();
1808 			if (script.isEqualTo(',')) {
1809 				script.skipEmpty();
1810 				std::auto_ptr<ExprScriptExpression> pEnd(parseExpression(block, script));
1811 				script.skipEmpty();
1812 				if (boundaries == NULL) boundaries = new BNFMultiplicityBoundaries;
1813 				boundaries->setMultiplicity(pBegin.release(), pEnd.release());
1814 			} else {
1815 				if (boundaries == NULL) boundaries = new BNFMultiplicityBoundaries;
1816 				boundaries->setMultiplicity(pBegin.release(), NULL);
1817 			}
1818 			if (!script.isEqualTo(')')) {
1819 				if (pResult == NULL) delete boundaries;
1820 				throw UtlException(script, "')' expected to close '#repeat'");
1821 			}
1822 			pResult = boundaries;
1823 		} else {
1824 			int iBegin;
1825 			int iEnd;
1826 			if (script.readInt(iBegin)) {
1827 				if (iBegin < 0) throw UtlException(script, "multiplicity 'm..n' or 'm' doesn't allow negative boundaries");
1828 				script.skipEmpty();
1829 				if (script.isEqualTo("..")) {
1830 					script.skipEmpty();
1831 					if (script.isEqualTo('*') || script.isEqualTo('n')) iEnd = -1;
1832 					else {
1833 						if (!script.readInt(iEnd)) throw UtlException(script, "multiplicity expected as 'm..n' format");
1834 						if (iEnd < iBegin) throw UtlException(script, "multiplicity 'm..n' doesn't allow 'm' being greater than 'n'");
1835 					}
1836 				} else {
1837 					iEnd = iBegin;
1838 				}
1839 				if (boundaries == NULL) boundaries = new BNFMultiplicityBoundaries;
1840 				pResult = boundaries;
1841 			} else {
1842 				iBegin = 1;
1843 				iEnd = 1;
1844 				if (boundaries == NULL) boundaries = new BNFMultiplicityBoundaries;
1845 			}
1846 			boundaries->setMultiplicity(iBegin, iEnd);
1847 		}
1848 		return pResult;
1849 	}
1850 
betweenCommands(ScpStream & script,GrfBlock & block)1851 	bool DtaBNFScript::betweenCommands(ScpStream& script, GrfBlock& block) {
1852 		return DtaScript::betweenCommands(script, block);
1853 	}
1854 
handleUnknownCommand(const std::string & sCommand,ScpStream & script,GrfBlock & block)1855 	void DtaBNFScript::handleUnknownCommand(const std::string& sCommand, ScpStream& script, GrfBlock& block) {
1856 		DtaScript::handleUnknownCommand(sCommand, script, block);
1857 	}
1858 
handleNotAWordCommand(ScpStream & script,GrfBlock & block)1859 	void DtaBNFScript::handleNotAWordCommand(ScpStream& script, GrfBlock& block) {
1860 		DtaScript::handleNotAWordCommand(script, block);
1861 	}
1862 
handleUnknownTokenDirective(const std::string & sDirective,ScpStream & script,BNFClause & rule,GrfBlock & block,bool & bContinue,bool & bNoCase,bool bLiteralOnly,BNFStepper * pStepper)1863 	void DtaBNFScript::handleUnknownTokenDirective(const std::string& sDirective, ScpStream& script, BNFClause& rule, GrfBlock& block, bool& bContinue, bool& bNoCase, bool bLiteralOnly, BNFStepper* pStepper) {
1864 		throw UtlException(script, "unknown macro instruction '#" + sDirective + "' encountered");
1865 	}
1866 
compileCppHeaderIncludes(CppCompilerEnvironment & theCompilerEnvironment) const1867 	void DtaBNFScript::compileCppHeaderIncludes(CppCompilerEnvironment& theCompilerEnvironment) const {
1868 		theCompilerEnvironment.getHeader() << "namespace CodeWorker {";
1869 		theCompilerEnvironment.getHeader().endl();
1870 		theCompilerEnvironment.getHeader() << "\tclass CGBNFRuntimeEnvironment;";
1871 		theCompilerEnvironment.getHeader().endl();
1872 		theCompilerEnvironment.getHeader() << "}";
1873 		theCompilerEnvironment.getHeader().endl();
1874 		DtaScript::compileCppHeaderIncludes(theCompilerEnvironment);
1875 	}
1876 
compileCppFunctions(CppCompilerEnvironment & theCompilerEnvironment) const1877 	void DtaBNFScript::compileCppFunctions(CppCompilerEnvironment& theCompilerEnvironment) const {
1878 		DtaScript::compileCppFunctions(theCompilerEnvironment);
1879 		for (std::map<std::string, std::list<BNFClause*> >::const_iterator i = _listOfClauses.begin(); i != _listOfClauses.end(); i++) {
1880 			for (std::list<BNFClause*>::const_iterator j = i->second.begin(); j != i->second.end(); j++) {
1881 				(*j)->compileCppFunction(theCompilerEnvironment);
1882 			}
1883 		}
1884 	}
1885 
compileCppBNFAssignment(CppCompilerEnvironment & theCompilerEnvironment,int iClauseReturnType,ExprScriptVariable & variableToAssign,bool bConcatVariable,const char * tcText)1886 	void DtaBNFScript::compileCppBNFAssignment(CppCompilerEnvironment& theCompilerEnvironment, int iClauseReturnType, ExprScriptVariable& variableToAssign, bool bConcatVariable, const char* tcText) {
1887 		CW_BODY_INDENT;
1888 		variableToAssign.compileCppForBNFSet(theCompilerEnvironment);
1889 		if (iClauseReturnType == BNFClause::LIST_RETURN_TYPE) {
1890 			CW_BODY_STREAM << ".pushItem(" << tcText << ");";
1891 		} else if (hasTargetLanguage()) {
1892 			if (bConcatVariable) {
1893 				CW_BODY_STREAM << " += " << tcText << ";";
1894 			} else {
1895 				CW_BODY_STREAM << " = " << tcText << ";";
1896 			}
1897 		} else {
1898 			if (bConcatVariable) {
1899 				CW_BODY_STREAM << ".concatenateValue(" << tcText << ");";
1900 			} else {
1901 				CW_BODY_STREAM << ".setValue(" << tcText << ");";
1902 			}
1903 		}
1904 		CW_BODY_ENDL;
1905 	}
1906 
assignmentToString(ExprScriptVariable * pVariableToAssign,bool bConcatenateVariable)1907 	std::string DtaBNFScript::assignmentToString(ExprScriptVariable* pVariableToAssign, bool bConcatenateVariable) {
1908 		if (pVariableToAssign != NULL) return ((bConcatenateVariable) ? ":+" : ":") + pVariableToAssign->toString();
1909 		return "";
1910 	}
1911 
constantsToString(const std::vector<std::string> & listOfConstants)1912 	std::string DtaBNFScript::constantsToString(const std::vector<std::string>& listOfConstants) {
1913 		std::string sText;
1914 		if (listOfConstants.size() == 1) {
1915 			sText = ":\"" + CGRuntime::composeCLikeString(listOfConstants[0]) + "\"";
1916 		} else if (!listOfConstants.empty()) {
1917 			sText = ":{";
1918 			for (std::vector<std::string>::const_iterator i = listOfConstants.begin(); i != listOfConstants.end(); ++i) {
1919 				if (i != listOfConstants.begin()) sText += ", ";
1920 				sText += "\"" + CGRuntime::composeCLikeString(*i) + "\"";
1921 			}
1922 			sText += "}";
1923 		}
1924 		return sText;
1925 	}
1926 
parseIgnoreMode(ScpStream & script,BNFClause * & pPreprocessingIgnoreClause)1927 	IGNORE_MODE DtaBNFScript::parseIgnoreMode(ScpStream& script, BNFClause*& pPreprocessingIgnoreClause) {
1928 		IGNORE_MODE eMode;
1929 		pPreprocessingIgnoreClause = NULL;
1930 		script.skipEmpty();
1931 		if (script.isEqualTo('(')) {
1932 			script.skipEmpty();
1933 			if (script.isEqualTo("C++/Doxygen")) eMode = IGNORE_CPP_EXCEPT_DOXYGEN;
1934 			else if (script.isEqualTo("C++")) eMode = IGNORE_CPP;
1935 			else if (script.isEqualTo("JAVA")) eMode = IGNORE_JAVA;
1936 			else if (script.isEqualTo("HTML") || script.isEqualTo("XML")) eMode = IGNORE_HTML;
1937 			else if (script.isEqualTo("blanks")) eMode = IGNORE_BLANKS;
1938 			else if (script.isEqualTo("spaces")) eMode = IGNORE_SPACES;
1939 			else if (script.isEqualTo("Ada")) eMode = IGNORE_ADA;
1940 			else if (script.isEqualTo("LaTeX")) eMode = IGNORE_LATEX;
1941 			else {
1942 				eMode = IGNORE_CLAUSE;
1943 				std::string sKey;
1944 				script.readPythonString(sKey);
1945 				if (sKey.empty()) sKey = "#empty";
1946 				else sKey = "#ignore[" + sKey + "]";
1947 				if (_mapOfIgnoreClauses.find(sKey) == _mapOfIgnoreClauses.end()) {
1948 					throw UtlException(script, "the ignore clause '" + sKey + "' doesn't exist");
1949 				}
1950 				pPreprocessingIgnoreClause = _mapOfIgnoreClauses[sKey];
1951 			}
1952 			script.skipEmpty();
1953 			if (!script.isEqualTo(')')) throw UtlException(script, "')' or correct mode expected by clause '#ignore'");
1954 		} else {
1955 			eMode = IGNORE_CLAUSE;
1956 			if (_mapOfIgnoreClauses.find("#ignore") == _mapOfIgnoreClauses.end()) {
1957 				throw UtlException(script, "the ignore clause '#ignore' doesn't exist");
1958 			}
1959 			pPreprocessingIgnoreClause = _mapOfIgnoreClauses["#ignore"];
1960 		}
1961 		return eMode;
1962 	}
1963 
1964 //##markup##"parsing"
1965 //##begin##"parsing"
parseAttachInputToSocket(GrfBlock & block,ScpStream & script,ExprScriptVariable * pMethodCaller)1966 	void DtaBNFScript::parseAttachInputToSocket(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) {
1967 		GrfAttachInputToSocket* pAttachInputToSocket = new GrfAttachInputToSocket;
1968 		if (requiresParsingInformation()) pAttachInputToSocket->setParsingInformation(getFilenamePtr(), script);
1969 		block.add(pAttachInputToSocket);
1970 		script.skipEmpty();
1971 		if (!script.isEqualTo('(')) throw UtlException(script, "syntax error: '(' expected");
1972 		script.skipEmpty();
1973 		if (pMethodCaller == NULL) pAttachInputToSocket->setSocket(parseExpression(block, script));
1974 		else pAttachInputToSocket->setSocket(pMethodCaller);
1975 		if (!script.isEqualTo(')')) throw UtlException(script, "syntax error: ')' expected");
1976 		script.skipEmpty();
1977 		if (!script.isEqualTo(';')) throw UtlException(script, "syntax error: ';' expected");
1978 	}
1979 
parseDetachInputFromSocket(GrfBlock & block,ScpStream & script,ExprScriptVariable * pMethodCaller)1980 	void DtaBNFScript::parseDetachInputFromSocket(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) {
1981 		GrfDetachInputFromSocket* pDetachInputFromSocket = new GrfDetachInputFromSocket;
1982 		if (requiresParsingInformation()) pDetachInputFromSocket->setParsingInformation(getFilenamePtr(), script);
1983 		block.add(pDetachInputFromSocket);
1984 		script.skipEmpty();
1985 		if (!script.isEqualTo('(')) throw UtlException(script, "syntax error: '(' expected");
1986 		script.skipEmpty();
1987 		if (pMethodCaller == NULL) pDetachInputFromSocket->setSocket(parseExpression(block, script));
1988 		else pDetachInputFromSocket->setSocket(pMethodCaller);
1989 		if (!script.isEqualTo(')')) throw UtlException(script, "syntax error: ')' expected");
1990 		script.skipEmpty();
1991 		if (!script.isEqualTo(';')) throw UtlException(script, "syntax error: ';' expected");
1992 	}
1993 
parseGoBack(GrfBlock & block,ScpStream & script,ExprScriptVariable * pMethodCaller)1994 	void DtaBNFScript::parseGoBack(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) {
1995 		GrfGoBack* pGoBack = new GrfGoBack;
1996 		if (requiresParsingInformation()) pGoBack->setParsingInformation(getFilenamePtr(), script);
1997 		block.add(pGoBack);
1998 		script.skipEmpty();
1999 		if (!script.isEqualTo('(')) throw UtlException(script, "syntax error: '(' expected");
2000 		script.skipEmpty();
2001 		if (!script.isEqualTo(')')) throw UtlException(script, "syntax error: ')' expected");
2002 		script.skipEmpty();
2003 		if (!script.isEqualTo(';')) throw UtlException(script, "syntax error: ';' expected");
2004 	}
2005 
parseSetInputLocation(GrfBlock & block,ScpStream & script,ExprScriptVariable * pMethodCaller)2006 	void DtaBNFScript::parseSetInputLocation(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) {
2007 		GrfSetInputLocation* pSetInputLocation = new GrfSetInputLocation;
2008 		if (requiresParsingInformation()) pSetInputLocation->setParsingInformation(getFilenamePtr(), script);
2009 		block.add(pSetInputLocation);
2010 		script.skipEmpty();
2011 		if (!script.isEqualTo('(')) throw UtlException(script, "syntax error: '(' expected");
2012 		script.skipEmpty();
2013 		if (pMethodCaller == NULL) pSetInputLocation->setLocation(parseExpression(block, script));
2014 		else pSetInputLocation->setLocation(pMethodCaller);
2015 		if (!script.isEqualTo(')')) throw UtlException(script, "syntax error: ')' expected");
2016 		script.skipEmpty();
2017 		if (!script.isEqualTo(';')) throw UtlException(script, "syntax error: ';' expected");
2018 	}
2019 
parseAllFloatingLocations(GrfBlock & block,ScpStream & script,ExprScriptVariable * pMethodCaller)2020 	void DtaBNFScript::parseAllFloatingLocations(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) {
2021 		DtaScript::parseAllFloatingLocations(block, script, pMethodCaller);
2022 	}
2023 
parseAttachOutputToSocket(GrfBlock & block,ScpStream & script,ExprScriptVariable * pMethodCaller)2024 	void DtaBNFScript::parseAttachOutputToSocket(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) {
2025 		DtaScript::parseAttachOutputToSocket(block, script, pMethodCaller);
2026 	}
2027 
parseDetachOutputFromSocket(GrfBlock & block,ScpStream & script,ExprScriptVariable * pMethodCaller)2028 	void DtaBNFScript::parseDetachOutputFromSocket(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) {
2029 		DtaScript::parseDetachOutputFromSocket(block, script, pMethodCaller);
2030 	}
2031 
parseIncrementIndentLevel(GrfBlock & block,ScpStream & script,ExprScriptVariable * pMethodCaller)2032 	void DtaBNFScript::parseIncrementIndentLevel(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) {
2033 		DtaScript::parseIncrementIndentLevel(block, script, pMethodCaller);
2034 	}
2035 
parseInsertText(GrfBlock & block,ScpStream & script,ExprScriptVariable * pMethodCaller)2036 	void DtaBNFScript::parseInsertText(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) {
2037 		DtaScript::parseInsertText(block, script, pMethodCaller);
2038 	}
2039 
parseInsertTextOnce(GrfBlock & block,ScpStream & script,ExprScriptVariable * pMethodCaller)2040 	void DtaBNFScript::parseInsertTextOnce(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) {
2041 		DtaScript::parseInsertTextOnce(block, script, pMethodCaller);
2042 	}
2043 
parseInsertTextToFloatingLocation(GrfBlock & block,ScpStream & script,ExprScriptVariable * pMethodCaller)2044 	void DtaBNFScript::parseInsertTextToFloatingLocation(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) {
2045 		DtaScript::parseInsertTextToFloatingLocation(block, script, pMethodCaller);
2046 	}
2047 
parseInsertTextOnceToFloatingLocation(GrfBlock & block,ScpStream & script,ExprScriptVariable * pMethodCaller)2048 	void DtaBNFScript::parseInsertTextOnceToFloatingLocation(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) {
2049 		DtaScript::parseInsertTextOnceToFloatingLocation(block, script, pMethodCaller);
2050 	}
2051 
parseOverwritePortion(GrfBlock & block,ScpStream & script,ExprScriptVariable * pMethodCaller)2052 	void DtaBNFScript::parseOverwritePortion(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) {
2053 		DtaScript::parseOverwritePortion(block, script, pMethodCaller);
2054 	}
2055 
parsePopulateProtectedArea(GrfBlock & block,ScpStream & script,ExprScriptVariable * pMethodCaller)2056 	void DtaBNFScript::parsePopulateProtectedArea(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) {
2057 		DtaScript::parsePopulateProtectedArea(block, script, pMethodCaller);
2058 	}
2059 
parseResizeOutputStream(GrfBlock & block,ScpStream & script,ExprScriptVariable * pMethodCaller)2060 	void DtaBNFScript::parseResizeOutputStream(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) {
2061 		DtaScript::parseResizeOutputStream(block, script, pMethodCaller);
2062 	}
2063 
parseSetFloatingLocation(GrfBlock & block,ScpStream & script,ExprScriptVariable * pMethodCaller)2064 	void DtaBNFScript::parseSetFloatingLocation(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) {
2065 		DtaScript::parseSetFloatingLocation(block, script, pMethodCaller);
2066 	}
2067 
parseSetOutputLocation(GrfBlock & block,ScpStream & script,ExprScriptVariable * pMethodCaller)2068 	void DtaBNFScript::parseSetOutputLocation(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) {
2069 		DtaScript::parseSetOutputLocation(block, script, pMethodCaller);
2070 	}
2071 
parseSetProtectedArea(GrfBlock & block,ScpStream & script,ExprScriptVariable * pMethodCaller)2072 	void DtaBNFScript::parseSetProtectedArea(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) {
2073 		DtaScript::parseSetProtectedArea(block, script, pMethodCaller);
2074 	}
2075 
parseWriteBytes(GrfBlock & block,ScpStream & script,ExprScriptVariable * pMethodCaller)2076 	void DtaBNFScript::parseWriteBytes(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) {
2077 		DtaScript::parseWriteBytes(block, script, pMethodCaller);
2078 	}
2079 
parseWriteText(GrfBlock & block,ScpStream & script,ExprScriptVariable * pMethodCaller)2080 	void DtaBNFScript::parseWriteText(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) {
2081 		DtaScript::parseWriteText(block, script, pMethodCaller);
2082 	}
2083 
parseWriteTextOnce(GrfBlock & block,ScpStream & script,ExprScriptVariable * pMethodCaller)2084 	void DtaBNFScript::parseWriteTextOnce(GrfBlock& block, ScpStream& script, ExprScriptVariable* pMethodCaller) {
2085 		DtaScript::parseWriteTextOnce(block, script, pMethodCaller);
2086 	}
2087 
2088 //##end##"parsing"
2089 }
2090