--- /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()