1 define(['require','CONSTANT'],
  2 function(require, CONSTANT) {
  3 	var ObjectType = CONSTANT.ObjectType;
  4 	/**
  5 	 * @description A Collection of Objects used for Grammar Tree Objects
  6 	 * @name GrammarTreeObjects
  7 	 * @class GrammarTreeObjects
  8 	 * @example require('GrammarTreeObjects')
  9 	 * @exports GrammarTreeObjects
 10 	 * @version 1.0
 11 	 * @module GrammarTreeObjects
 12 	 * @augments CONSTANT
 13 	**/
 14 	var TREEObjects = {
 15 		/**
 16 		 * @desription A Tree Object, It can have root and Childrens 
 17 		 * @name Tree
 18 		 * @class Tree
 19 		 * @example require('GrammarTreeObjects').Tree
 20 		 * @exports Tree
 21 		 * @version 1.0
 22 		 * @module GrammarTreeObjects
 23 		 * @memberOf GrammarTreeObjects
 24 		 * @field
 25 		 **/
 26 		Tree : function() {
 27 			var ROOT = null;
 28 			var tree = {
 29 				setRoot : function(obj) {
 30 					ROOT = obj;
 31 					return this;
 32 				},
 33 				getRoot : function() {
 34 					return ROOT;
 35 				},
 36 				clone : function(){
 37 					var cloneTree = TREEObjects.Tree();
 38 					cloneTree.setRoot(this.getRoot().clone());
 39 					return cloneTree; 
 40 				}
 41 			};
 42 			return tree;
 43 		},
 44 		/**
 45 		 * @desription A PROGRAM Object, As mentoned in the Grammar The program will have a fact and IF Body, The body can have list of Objects 
 46 		 * @name PROGRAM
 47 		 * @class PROGRAM
 48 		 * @example require('GrammarTreeObjects').PROGRAM
 49 		 * @exports PROGRAM
 50 		 * @version 1.0
 51 		 * @module GrammarTreeObjects
 52 		 * @memberOf GrammarTreeObjects
 53 		 * @field
 54 		 **/
 55 		PROGRAM : function(prgm, type) {
 56 			var program = prgm;
 57 			var ptype = type;
 58 			var programObj = {
 59 				getProgram : function() {
 60 					return program;
 61 				},
 62 				type : function() {
 63 					return ptype;
 64 				},
 65 				toString : function() {
 66 					return program.toString();
 67 				},
 68 				clone : function(){
 69 					var cloneProgram = TREEObjects.PROGRAM(this.program.clone(), this.ptype);
 70 					return cloneProgram;
 71 				}
 72 			};
 73 			return programObj;
 74 		},
 75 		/**
 76 		 * @desription A RUNTIME_TABLE Object, As mentoned in the Grammar The program will have a fact and IF Body, The body can have list of Objects 
 77 		 * @name PROGRAM
 78 		 * @class PROGRAM
 79 		 * @example require('GrammarTreeObjects').PROGRAM
 80 		 * @exports PROGRAM
 81 		 * @version 1.0
 82 		 * @module GrammarTreeObjects
 83 		 * @memberOf GrammarTreeObjects
 84 		 * @field
 85 		 **/
 86 		RUNTIME_TABLE : function(nme, prgms) {
 87 			var name = nme;
 88 			var programs = prgms;
 89 			var pType = ObjectType.RUNTIME_TABLE;
 90 			var runtimeTable = {
 91 				getRTPrograms : function() {
 92 					return programs;
 93 				},
 94 				/**
 95 				 *	This method is used to change the runtime program while it is being changed to handle relative formula.
 96 				 */
 97 				setRTProgram : function(prog) {
 98 					programs = prog;
 99 				},
100 				getName:function(){
101 					return name;
102 				},
103 				setname:function(n){
104 					name=n;
105 				},
106 				type : function() {
107 					return pType;
108 				},
109 				toString : function() {
110 					return name+'=[\n\t' + programs.join('.\n').replaceAll('\t','\t\t') + '.\n\t]';
111 				},
112 				clone : function(){
113 					var cloneNRP = TREEObjects.RUNTIME_TABLE(this.name, this.programs.clone());
114 					cloneNRP.setRTProgram(this.programs.clone());
115 					return cloneNRP;
116 				}
117 			};
118 			return runtimeTable;
119 
120 		},
121 		NEXCEL_RT_PROGRAM : function(prgms) {
122 			var programs = prgms;
123 			var pType = ObjectType.NEXCEL_RT_PROGRAM;
124 			var nexcelRTProgram = {
125 				getRTPrograms : function() {
126 					return programs;
127 				},
128 				/**
129 				 *	This method is used to change the runtime program while it is being changed to handle relative formula.
130 				 */
131 				setRTProgram : function(prog) {
132 					programs = prog;
133 				},
134 				type : function() {
135 					return pType;
136 				},
137 				toString : function() {
138 					return '[' + programs.join('.\n') + '.]';
139 				},
140 				clone : function(){
141 					var cloneNRP = TREEObjects.NEXCEL_RT_PROGRAM(this.programs.clone());
142 					cloneNRP.setRTProgram(this.programs.clone());
143 					return cloneNRP;
144 				}
145 			};
146 			return nexcelRTProgram;
147 
148 		},
149 		CLAUSE : function(type, fact, body) {
150 			var type = type;
151 			var fact;
152 			var body;
153 			var clause = {
154 				getBody : function() {
155 					return body;
156 				},
157 				type : function() {
158 					return type;
159 				},
160 				getFact : function() {
161 					return fact;
162 				},
163 				toString : function() {
164 					if (body)
165 						return fact.toString() + ' :- \n\t' + body.join(',\n\t');
166 					else
167 						return fact.toString();
168 				},
169 				clone : function(){
170 					var cloneClause = TREEObjects.CLAUSE(this.type, this.fact, this.body);
171 					return cloneClause;
172 				}
173 			};
174 			return clause;
175 		},
176 		RANGE : function(type, rangeName) {
177 			var type = type;
178 			var negative = false;
179 			var name = rangeName;
180 			var fromCell;
181 			var toCell;
182 			var variables = [];
183 			var range = {
184 				addVariable : function(variable) {
185 					variables = variables.concat(variable);
186 					return this;
187 				},
188 				setRange : function(from, to) {
189 					fromCell = from;
190 					toCell = to;
191 					return this;
192 				},
193 				getVariables : function() {
194 					return variables;
195 				},
196 				/**
197 				 *	@param vars new Variable names which will replace the existing variables. 
198 				 */
199 				setVariables : function(vars) {
200 					variables=vars;
201 				},
202 				type : function() {
203 					return type;
204 				},
205 				getName : function() {
206 					return name;
207 				},
208 				setName:function(nam){
209 					name=nam;
210 				},
211 				getRange : function() {
212 					return [fromCell, toCell];
213 				},
214 				negate : function() {
215 					negative = true;
216 				},
217 				isNegative : function() {
218 					return negative;
219 				},
220 				toString : function(prolog) {
221 					var str = "";
222 					if (type == ObjectType.RANGE_CELL) {
223 						str = fromCell.toString() + ':' + toCell.toString();
224 					} else {
225 						if (variables.length > 0)
226 							str = name + '(' + variables.toString() + ')';
227 						else
228 							str = '' + name;
229 					}
230 					if (negative && prolog)
231 						return "not(" + str + ")";
232 					if (negative)
233 						return "NOT " + str;
234 					else
235 						return str;
236 				},
237 				clone : function(){
238 					var cloneRange = TREEObjects.RANGE(this.type, this.rangeName);
239 					cloneRange.negative = this.isNegative();
240 					cloneRange.setRange(this.fromCell, this.toCell);
241 					cloneRange.setVariables(this.vars);
242 					return cloneRange;
243 				}
244 			};
245 			return range;
246 		},
247 		CELL : function(type, colVal, rowVal, rowFix, colFix) {
248 			var type = type;
249 			var row = rowVal;
250 			var col = colVal;
251 			var rowFixed = false;
252 			var colFixed = false;
253 			if (rowFix)
254 				rowFixed = true;
255 			if (colFix)
256 				colFixed = true;
257 			var cellBase = {
258 				getRow : function() {
259 					return row;
260 				},
261 				getCol : function() {
262 					return col;
263 				},
264 				type : function() {
265 					return type;
266 				},
267 				isRowFixed : function() {
268 					return rowFixed;
269 				},
270 				isColFixed : function() {
271 					return colFixed;
272 				},
273 				toString : function() {
274 					return colVal + row;
275 				},
276 				clone : function(){
277 					var cloneCell = TREEObjects.CELL(this.type,this.col,this.row,this.rowFixed,this.colFixed);
278 					cloneCell.rowFixed = this.isRowFixed();
279 					cloneCell.colFixed = this.isColFixed();
280 					return cloneCell;
281 				}
282 			};
283 			return cellBase;
284 		},
285 		IF : function() {
286 			var type = ObjectType.IF;
287 			var LHS = [];
288 			var RHS = [];
289 			var ifFunc = {
290 				addLHS : function(obj) {
291 					LSH = LHS.push(obj);
292 					return this;
293 				},
294 				addRHS : function(obj) {
295 					RHS = RHS.push(obj);
296 					return this;
297 				},
298 				type : function() {
299 					return type;
300 				},
301 				clone : function(){
302 					var cloneIF = TREEObjects.IF();
303 					cloneIF.addLHS(this.LHS.clone());
304 					cloneIF.addRHS(this.RHS.clone());
305 					return cloneIF;
306 				}
307 			};
308 			return ifFunc;
309 		},
310 		CONSTRAINT : function(constrType) {
311 			var type = constrType;
312 			var LHS = [];
313 			var RHS = [];
314 			var constr = {
315 				addLHS : function(obj) {
316 					LHS = LHS.push(obj);
317 					return this;
318 				},
319 				addRHS : function(obj) {
320 					RHS = RHS.push(obj);
321 					return this;
322 				},
323 				type : function() {
324 					return type;
325 				},
326 				toString : function() {
327 					return LHS + '' + RHS;
328 				},
329 				clone : function(){
330 					var cloneConstraint = TREEObjects.CONSTRAINT(this.type);
331 					cloneConstraints.addLHS(this.LHS.clone());
332 					cloneConstraints.addRHS(this.RHS.clone());
333 					return cloneConstraints;
334 				}
335 			};
336 			return constr;
337 		},
338 		EXPRESSION : function(eType, eValue, e_exps) {
339 			var type = eType;
340 			var value = eValue;
341 			var exps = e_exps;
342 			var negative = false;
343 			var expression = {
344 				type : function() {
345 					return type;
346 				},
347 				value : function() {
348 					return value;
349 				},
350 				setValue : function(val) {
351 					value = val;
352 				},
353 				// Negative used to indicate the expression is negative. like -12 or test = -V
354 				setNegative:function(){
355 					negative = true;
356 				},
357 				isNegative:function(){
358 					return negative;
359 				},
360 				exps : function() {
361 					return exps;
362 				},
363 				toString : function() {
364 					var str ="";
365 					if(negative)
366 						str = "-";
367 					if (exps)
368 						return str+value + '(' + exps.toString() + ')';
369 					else if (type == 4)
370 						return str+value.toString();
371 					else
372 						return str+ value;
373 				},
374 				clone : function(){
375 					var cloneExpression = TREEObjects.EXPRESSION(this.type,this.value,this.exps);
376 					cloneExpression.negative = this.negative;
377 					return cloneExpression;
378 				}
379 			};
380 			return expression;
381 		},
382 		CONSTANT : function(cType, cValue) {
383 			var type = cType;
384 			var value = cValue;
385 			var negative = false;
386 			var constant = {
387 				type : function() {
388 					return type;
389 				},
390 				value : function() {
391 					return value;
392 				},
393 				setNegative:function(){
394 					negative = true;
395 				},
396 				isNegative:function(){
397 					return negative;
398 				},
399 				toString : function(prolog) {
400 					var str ="";
401 					if(negative)
402 						str = "-";
403 					if (type == ObjectType.CONSTANT_NAM) {
404 						if (prolog)
405 							return "'" + value + "'";
406 						else
407 							return '"' + value + '"';
408 					} else{
409 						if(negative)
410 							return -1*value;
411 						else
412 							return value;
413 					}
414 				},
415 				clone : function(){
416 					var cloneConst = TREEObjects.CONSTANT(this.type, this.value);
417 					cloneConst.negative = this.negative;
418 					return cloneConst;
419 				}
420 			};
421 			return constant;
422 		},
423 		BIN_OP : function(binOp) {
424 			var type = ObjectType.BIN_OP;
425 			var oper = binOp;
426 			var lhs;
427 			var rhs;
428 			var bracket = false;
429 			var binOper = {
430 				type : function() {
431 					return type;
432 				},
433 				op : function() {/*The Operation */
434 					return oper;
435 				},
436 				setBracket : function() {
437 					bracket = true;
438 					return this;
439 				},
440 				setLhs : function(lhsObj) {
441 					lhs = lhsObj;
442 					return this;
443 				},
444 				getLhs : function() {
445 					return lhs;
446 				},
447 				setRhs : function(rhsObj) {
448 					rhs = rhsObj;
449 					return this;
450 				},
451 				getRhs : function() {
452 					return rhs;
453 				},
454 				toString : function(prolog) {
455 					if (lhs && rhs && bracket)// TODO Delete this Line
456 						return "(" + lhs.toString(prolog) + oper + rhs.toString(prolog) + ")";
457 					else
458 						return lhs.toString(prolog) + oper + rhs.toString(prolog);
459 				},
460 				clone : function(){
461 					var cloneBinOp = TREEObjects.BIN_OP(this.oper);
462 					cloneBinOp.setLhs(this.lhs);
463 					cloneBinOp.setRhs(this.rhs);
464 					cloneBinOp.setBracket(this.bracket);
465 				}
466 			};
467 			return binOper;
468 		},
469 		BIN_REL : function(binRel) {
470 			var type = ObjectType.BIN_REL;
471 			var rel = binRel;
472 			var lhs;
473 			var rhs;
474 			var binRel = {
475 				type : function() {
476 					return type;
477 				},
478 				rel : function() {/*The Operation */
479 					return rel;
480 				},
481 				setLhs : function(lhsObj) {
482 					lhs = lhsObj;
483 					return this;
484 				},
485 				getLhs : function() {
486 					return lhs;
487 				},
488 				setRhs : function(rhsObj) {
489 					rhs = rhsObj;
490 					return this;
491 				},
492 				getRhs : function() {
493 					return rhs;
494 				},
495 				toString : function(prolog) {
496 					if (lhs && rhs)// TODO Delete this Line
497 						return lhs.toString(prolog) + rel + rhs.toString(prolog);
498 				},
499 				clone : function(){
500 					var cloneBR = TREEObjects.BIN_REL(this.rel);
501 					cloneBR.setLhs(this.lhs);
502 					cloneBR.setRhs(this.rhs);
503 					return cloneBR;
504 				}
505 			};
506 			return binRel;
507 		},
508 		OPER_EQUAL : function() {
509 			var variable;
510 			var type = ObjectType.OPER_EQUAL;
511 			var rhs;
512 			var operEqual = {
513 				type : function() {
514 					return type;
515 				},
516 				variable : function() {/*The Operation */
517 					return variable;
518 				},
519 				setVariable : function(relVar) {
520 					variable = relVar;
521 					return this;
522 				},
523 				setRhs : function(rhsObj) {
524 					rhs = rhsObj;
525 					return this;
526 				},
527 				getRhs : function() {
528 					return rhs;
529 				},
530 				toString : function(prolog) {
531 					if (rhs)// TODO Delete this Line
532 						return variable + '=' + rhs.toString(prolog);
533 				},
534 				clone : function(){
535 					var cloneOE = TREEObjects.OPER_EQUAL();
536 					cloneOE.setVariable(this.variable);
537 					cloneOE.setRhs(this.rhs);
538 					return cloneOE;
539 				}
540 			};
541 			return operEqual;
542 		}
543 	};
544 
545 	return TREEObjects;
546 });