aknlayoutcompiler/src/FormulaTree.cpp
changeset 0 f58d6ec98e88
child 1 b700e12870ca
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/aknlayoutcompiler/src/FormulaTree.cpp	Thu Dec 17 09:14:18 2009 +0200
@@ -0,0 +1,306 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+#include "FormulaTree.h"
+#include "FormulaParser.h"
+#include <sstream>
+#include <iostream>
+using namespace std;
+
+FormulaTreeNode* FormulaTreeNode::Parse(const string& aFormula)
+	{
+	return NewTree(ParseFormula(aFormula), aFormula);
+	}
+
+FormulaTreeNode::~FormulaTreeNode()
+	{
+	for (int i=0; i<Size(); i++)
+		delete iSubNodes[i];
+	}
+
+int FormulaTreeNode::Size() const
+	{
+	return iSubNodes.size();
+	}
+
+FormulaTreeNode& FormulaTreeNode::operator[](int aIndex)
+	{
+	return *iSubNodes[aIndex];
+	}
+
+const FormulaTreeNode& FormulaTreeNode::operator[](int aIndex) const
+	{
+	return *iSubNodes[aIndex];
+	}
+
+FormulaTreeNode::TNodeType FormulaTreeNode::Type() const
+	{
+	return iType;
+	}
+
+string FormulaTreeNode::Text() const
+	{
+	return iSource.substr(iStart, iLen);
+	}
+
+char FormulaTreeNode::Char() const
+	{
+	return iSource[iStart];
+	}
+
+int FormulaTreeNode::Int() const
+	{
+	int r;
+	stringstream(Text()) >> r;
+	return r;
+	}
+
+double FormulaTreeNode::Real() const
+	{
+	double r;
+	stringstream(Text()) >> r;
+	return r;
+	}
+
+FormulaTreeNode* FormulaTreeNode::NewTree(const ParseResult& aParse, const string& aFormula)
+	{
+	FormulaTreeNode* node = 0;
+
+	int parseId = aParse.iRuleId;
+	if (parseId == cell_name_ParserId)
+		{
+		node = new FormulaTreeNode(ECell, aFormula, aParse.iStart, aParse.iEnd-aParse.iStart);
+		}
+	else if (parseId == parent_ParserId)
+		{
+		node = new FormulaTreeNode(EParent, aFormula, aParse.iStart, aParse.iEnd-aParse.iStart);
+		}
+	else if (parseId == parent_cell_ParserId)
+		{
+		const ParseResult& cell = aParse.iChildren[1];
+		node = new FormulaTreeNode(EParentCell, aFormula, cell.iStart, cell.iEnd-cell.iStart);
+		}
+	else if (parseId == table_cell_ParserId)
+		{
+		node = new FormulaTreeNode(ETableCell, aFormula, aParse.iStart, aParse.iEnd-aParse.iStart);
+		}
+	else if (parseId == comp_cell_ParserId)
+		{
+		const ParseResult& cellId = aParse.iChildren[0].iChildren[0];
+		node = new FormulaTreeNode(EComponent, aFormula, cellId.iStart, cellId.iEnd-cellId.iStart);
+		node->iSubNodes.push_back(NewTree(aParse.iChildren[1], aFormula));
+		}
+	else if (parseId == abs_cell_ParserId)
+		{
+		node = new FormulaTreeNode(EAbsolute, aFormula, aParse.iStart, aParse.iEnd-aParse.iStart);
+		const ParseResult& part1 = aParse.iChildren[0].iChildren[0].iChildren[0].iChildren[0].iChildren[0].iChildren[1];
+		node->iSubNodes.push_back(new FormulaTreeNode(EReal, aFormula, part1.iStart, part1.iEnd-part1.iStart));
+		const ParseResult& part2 = aParse.iChildren[0].iChildren[0].iChildren[0].iChildren[1];
+		node->iSubNodes.push_back(new FormulaTreeNode(EReal, aFormula, part2.iStart, part2.iEnd-part2.iStart));
+		const ParseResult& part3 = aParse.iChildren[0].iChildren[1];
+		node->iSubNodes.push_back(NewTree(part3, aFormula));
+		}
+	else if (parseId == units_ParserId)
+		{
+		const ParseResult& units = aParse.iChildren[0];
+		node = new FormulaTreeNode(EUnits, aFormula, units.iStart, units.iEnd-units.iStart);
+		}
+	else if (parseId == constant_ParserId)
+		{
+		const ParseResult& constant = aParse.iChildren[0];
+		node = new FormulaTreeNode(EConstant, aFormula, constant.iStart, constant.iEnd-constant.iStart);
+		}
+	else if (parseId == attribute_ParserId)
+		{
+		const ParseResult& attrib = aParse.iChildren[1];
+		node = new FormulaTreeNode(EAttribute, aFormula, attrib.iStart, attrib.iEnd-attrib.iStart);
+		}
+	else if (parseId == mystery_ParserId)
+		{
+		node = new FormulaTreeNode(EMystery, aFormula, aParse.iStart, aParse.iEnd-aParse.iStart);
+		const ParseResult& part1 = aParse.iChildren[0].iChildren[0];
+		node->iSubNodes.push_back(new FormulaTreeNode(EInt, aFormula, part1.iStart, part1.iEnd-part1.iStart));
+		const ParseResult& part2 = aParse.iChildren[1];
+		node->iSubNodes.push_back(new FormulaTreeNode(EInt, aFormula, part2.iStart, part2.iEnd-part2.iStart));
+		}
+	else if (parseId == func_ParserId)
+		{
+		const ParseResult& funcName = aParse.iChildren[0].iChildren[0].iChildren[0];
+		node = new FormulaTreeNode(EFunction, aFormula, funcName.iStart, funcName.iEnd-funcName.iStart);
+		const ParseResult& expr= aParse.iChildren[0].iChildren[1];
+		node->iSubNodes.push_back(NewTree(expr, aFormula));
+		}
+	else if (parseId == group_ParserId)
+		{
+		node = NewTree(aParse.iChildren[0].iChildren[1], aFormula);
+		}
+	else if (parseId == term_ParserId || parseId == expression_ParserId)
+		{
+		node = NewTree(aParse.iChildren[0], aFormula);
+		const ParseResult* parse = &aParse;
+		while (parse->iChildren[1].iChildren[0].iRuleId != Parser::Nul().Id())
+			{
+			const ParseResult& oper = parse->iChildren[1].iChildren[0].iChildren[0].iChildren[0].iChildren[0];
+			FormulaTreeNode* newNode = new FormulaTreeNode(EArithmetic, aFormula, oper.iStart, oper.iEnd-oper.iStart);
+			newNode->iSubNodes.push_back(node);
+			const ParseResult& right = parse->iChildren[1].iChildren[0].iChildren[0].iChildren[0].iChildren[1];
+			newNode->iSubNodes.push_back(NewTree(right, aFormula));
+			node = newNode;
+			parse = &parse->iChildren[1].iChildren[0];
+			}
+		}
+	else if (parseId == comp_group_ParserId)
+		{
+		node = NewTree(aParse.iChildren[0].iChildren[1], aFormula);
+		}
+	else if (parseId == comp_ParserId)
+		{
+		const ParseResult& oper = aParse.iChildren[0].iChildren[0].iChildren[1];
+		node = new FormulaTreeNode(ECondition, aFormula, oper.iStart, oper.iEnd-oper.iStart);
+		const ParseResult& lhs = aParse.iChildren[0].iChildren[0].iChildren[0].iChildren[0];
+		node->iSubNodes.push_back(NewTree(lhs, aFormula));
+		const ParseResult& rhs = aParse.iChildren[1];
+		node->iSubNodes.push_back(NewTree(rhs, aFormula));
+		}
+	else if (parseId == conditional_ParserId)
+		{
+		node = new FormulaTreeNode(EConditional, aFormula, aParse.iStart, 0);
+		const ParseResult& cond = aParse.iChildren[0].iChildren[0].iChildren[0].iChildren[0].iChildren[1];
+		node->iSubNodes.push_back(NewTree(cond, aFormula));
+		const ParseResult& thenExpr = aParse.iChildren[0].iChildren[0].iChildren[1];
+		node->iSubNodes.push_back(NewTree(thenExpr, aFormula));
+		const ParseResult& elseExpr = aParse.iChildren[1];
+		node->iSubNodes.push_back(NewTree(elseExpr, aFormula));
+		}
+	else	// internal alt node, recurse down
+		{
+		node = NewTree(aParse.iChildren[0], aFormula);
+		}
+
+	return node;
+	}
+
+FormulaTreeNode::FormulaTreeNode(TNodeType aType, const string& aSource, int aStart, int aLen)
+: iSource(aSource), iStart(aStart), iLen(aLen), iType(aType)
+	{
+	}
+
+FormulaTreeNode::FormulaTreeNode(const FormulaTreeNode& aOther)
+: iSource(aOther.iSource), iStart(aOther.iStart), iLen(aOther.iLen), iType(aOther.iType)
+	{
+	for (int i=0; i<iSubNodes.size(); i++)
+		delete iSubNodes[i];
+	iSubNodes.clear();
+	for (int j=0; j<aOther.iSubNodes.size(); j++)
+		iSubNodes.push_back(new FormulaTreeNode(*aOther.iSubNodes[j]));
+	}
+
+void FormulaTreeNode::Print(const FormulaTreeNode& aNode)
+	{
+	switch (aNode.Type())
+		{
+		case FormulaTreeNode::EReal:		// Double() = the number
+			cout << aNode.Real();
+			break;
+		case FormulaTreeNode::EInt:			// Int() = the number
+			cout << aNode.Int();
+			break;
+		case FormulaTreeNode::ECell:			// Char() = cell name
+			cout << aNode.Char();
+			break;
+		case FormulaTreeNode::EParent:		// nothing special
+			cout << aNode.Char();
+			break;
+		case FormulaTreeNode::EParentCell:	// Char() = parent cell name
+			cout << "P_" << aNode.Char();
+			break;
+		case FormulaTreeNode::ETableCell:		// Double() = target table
+			cout << aNode.Real();
+			break;
+		case FormulaTreeNode::EComponent:		// Double() = component id, [0] = cell name
+			cout << aNode.Real() << "_";
+			Print(aNode[0]);
+			break;
+		case FormulaTreeNode::EAbsolute:		// Text() = whole thing, [0], [1] = real components, [2] = cell name
+			cout << "Abs(";
+			Print(aNode[0]);
+			cout << ",";
+			Print(aNode[1]);
+			cout << ",";
+			Print(aNode[2]);
+			cout << ")";
+			break;
+		case FormulaTreeNode::EUnits:			// Double() = units
+			cout << aNode.Real() << "units";
+			break;
+		case FormulaTreeNode::EConstant:		// Double() = constant
+			cout << "const(" << aNode.Real() << ")";
+			break;
+		case FormulaTreeNode::EAttribute:		// Int() = attribute
+			cout << "attrib(" << aNode.Int() << ")";
+			break;
+		case FormulaTreeNode::EMystery:		// Text() = whole thing, [0], [1] = int components
+			cout << "mystery(";
+			Print(aNode[0]);
+			cout << ",";
+			Print(aNode[1]);
+			cout << ")";
+			break;
+		case FormulaTreeNode::EFunction:		// Text() = function name, [0] = parameter
+			cout << aNode.Text() << "(";
+			Print(aNode[0]);
+			cout << ")";
+			break;
+		case FormulaTreeNode::EArithmetic:	// Char() = arithmetic operator, [0], [1] = sub expressions
+			cout << aNode.Char() << "(";
+			Print(aNode[0]);
+			cout << ",";
+			Print(aNode[1]);
+			cout << ")";
+			break;
+		case FormulaTreeNode::ECondition:		// Text() = comparison operator, [0], [1] = sub expressions
+			cout << aNode.Text() << "(";
+			Print(aNode[0]);
+			cout << ",";
+			Print(aNode[1]);
+			cout << ")";
+			break;
+		case FormulaTreeNode::EConditional:	// no content, [0] = condition, [1] = then expression, [2] = else expression
+			cout << "IF ";
+			Print(aNode[0]);
+			cout << " THEN ";
+			Print(aNode[1]);
+			cout << " ELSE ";
+			Print(aNode[2]);
+			break;
+		};
+	}
+
+void Print(const ParseResult& res);
+
+
+int TestFormulaTreeNode()
+	{
+	string formula("IF (P_W/25p*4.25p) <= P_H THEN P_W/25p*4.25p ELSE P_H");
+//	string formula("1*2/3");
+	Print(ParseFormula(formula));
+	FormulaTreeNode* tree = FormulaTreeNode::Parse(formula);
+	FormulaTreeNode::Print(*tree);
+	delete tree;
+	return 0;
+	}
+
+// int x = TestFormulaTreeNode()