|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 #include "FormulaTree.h" |
|
18 #include "FormulaParser.h" |
|
19 #include <sstream> |
|
20 #include <iostream> |
|
21 using namespace std; |
|
22 |
|
23 FormulaTreeNode* FormulaTreeNode::Parse(const string& aFormula) |
|
24 { |
|
25 return NewTree(ParseFormula(aFormula), aFormula); |
|
26 } |
|
27 |
|
28 FormulaTreeNode::~FormulaTreeNode() |
|
29 { |
|
30 for (int i=0; i<Size(); i++) |
|
31 delete iSubNodes[i]; |
|
32 } |
|
33 |
|
34 int FormulaTreeNode::Size() const |
|
35 { |
|
36 return iSubNodes.size(); |
|
37 } |
|
38 |
|
39 FormulaTreeNode& FormulaTreeNode::operator[](int aIndex) |
|
40 { |
|
41 return *iSubNodes[aIndex]; |
|
42 } |
|
43 |
|
44 const FormulaTreeNode& FormulaTreeNode::operator[](int aIndex) const |
|
45 { |
|
46 return *iSubNodes[aIndex]; |
|
47 } |
|
48 |
|
49 FormulaTreeNode::TNodeType FormulaTreeNode::Type() const |
|
50 { |
|
51 return iType; |
|
52 } |
|
53 |
|
54 string FormulaTreeNode::Text() const |
|
55 { |
|
56 return iSource.substr(iStart, iLen); |
|
57 } |
|
58 |
|
59 char FormulaTreeNode::Char() const |
|
60 { |
|
61 return iSource[iStart]; |
|
62 } |
|
63 |
|
64 int FormulaTreeNode::Int() const |
|
65 { |
|
66 int r; |
|
67 stringstream(Text()) >> r; |
|
68 return r; |
|
69 } |
|
70 |
|
71 double FormulaTreeNode::Real() const |
|
72 { |
|
73 double r; |
|
74 stringstream(Text()) >> r; |
|
75 return r; |
|
76 } |
|
77 |
|
78 FormulaTreeNode* FormulaTreeNode::NewTree(const ParseResult& aParse, const string& aFormula) |
|
79 { |
|
80 FormulaTreeNode* node = 0; |
|
81 |
|
82 int parseId = aParse.iRuleId; |
|
83 if (parseId == cell_name_ParserId) |
|
84 { |
|
85 node = new FormulaTreeNode(ECell, aFormula, aParse.iStart, aParse.iEnd-aParse.iStart); |
|
86 } |
|
87 else if (parseId == parent_ParserId) |
|
88 { |
|
89 node = new FormulaTreeNode(EParent, aFormula, aParse.iStart, aParse.iEnd-aParse.iStart); |
|
90 } |
|
91 else if (parseId == parent_cell_ParserId) |
|
92 { |
|
93 const ParseResult& cell = aParse.iChildren[1]; |
|
94 node = new FormulaTreeNode(EParentCell, aFormula, cell.iStart, cell.iEnd-cell.iStart); |
|
95 } |
|
96 else if (parseId == table_cell_ParserId) |
|
97 { |
|
98 node = new FormulaTreeNode(ETableCell, aFormula, aParse.iStart, aParse.iEnd-aParse.iStart); |
|
99 } |
|
100 else if (parseId == comp_cell_ParserId) |
|
101 { |
|
102 const ParseResult& cellId = aParse.iChildren[0].iChildren[0]; |
|
103 node = new FormulaTreeNode(EComponent, aFormula, cellId.iStart, cellId.iEnd-cellId.iStart); |
|
104 node->iSubNodes.push_back(NewTree(aParse.iChildren[1], aFormula)); |
|
105 } |
|
106 else if (parseId == abs_cell_ParserId) |
|
107 { |
|
108 node = new FormulaTreeNode(EAbsolute, aFormula, aParse.iStart, aParse.iEnd-aParse.iStart); |
|
109 const ParseResult& part1 = aParse.iChildren[0].iChildren[0].iChildren[0].iChildren[0].iChildren[0].iChildren[1]; |
|
110 node->iSubNodes.push_back(new FormulaTreeNode(EReal, aFormula, part1.iStart, part1.iEnd-part1.iStart)); |
|
111 const ParseResult& part2 = aParse.iChildren[0].iChildren[0].iChildren[0].iChildren[1]; |
|
112 node->iSubNodes.push_back(new FormulaTreeNode(EReal, aFormula, part2.iStart, part2.iEnd-part2.iStart)); |
|
113 const ParseResult& part3 = aParse.iChildren[0].iChildren[1]; |
|
114 node->iSubNodes.push_back(NewTree(part3, aFormula)); |
|
115 } |
|
116 else if (parseId == units_ParserId) |
|
117 { |
|
118 const ParseResult& units = aParse.iChildren[0]; |
|
119 node = new FormulaTreeNode(EUnits, aFormula, units.iStart, units.iEnd-units.iStart); |
|
120 } |
|
121 else if (parseId == constant_ParserId) |
|
122 { |
|
123 const ParseResult& constant = aParse.iChildren[0]; |
|
124 node = new FormulaTreeNode(EConstant, aFormula, constant.iStart, constant.iEnd-constant.iStart); |
|
125 } |
|
126 else if (parseId == attribute_ParserId) |
|
127 { |
|
128 const ParseResult& attrib = aParse.iChildren[1]; |
|
129 node = new FormulaTreeNode(EAttribute, aFormula, attrib.iStart, attrib.iEnd-attrib.iStart); |
|
130 } |
|
131 else if (parseId == mystery_ParserId) |
|
132 { |
|
133 node = new FormulaTreeNode(EMystery, aFormula, aParse.iStart, aParse.iEnd-aParse.iStart); |
|
134 const ParseResult& part1 = aParse.iChildren[0].iChildren[0]; |
|
135 node->iSubNodes.push_back(new FormulaTreeNode(EInt, aFormula, part1.iStart, part1.iEnd-part1.iStart)); |
|
136 const ParseResult& part2 = aParse.iChildren[1]; |
|
137 node->iSubNodes.push_back(new FormulaTreeNode(EInt, aFormula, part2.iStart, part2.iEnd-part2.iStart)); |
|
138 } |
|
139 else if (parseId == func_ParserId) |
|
140 { |
|
141 const ParseResult& funcName = aParse.iChildren[0].iChildren[0].iChildren[0]; |
|
142 node = new FormulaTreeNode(EFunction, aFormula, funcName.iStart, funcName.iEnd-funcName.iStart); |
|
143 const ParseResult& expr= aParse.iChildren[0].iChildren[1]; |
|
144 node->iSubNodes.push_back(NewTree(expr, aFormula)); |
|
145 } |
|
146 else if (parseId == group_ParserId) |
|
147 { |
|
148 node = NewTree(aParse.iChildren[0].iChildren[1], aFormula); |
|
149 } |
|
150 else if (parseId == term_ParserId || parseId == expression_ParserId) |
|
151 { |
|
152 node = NewTree(aParse.iChildren[0], aFormula); |
|
153 const ParseResult* parse = &aParse; |
|
154 while (parse->iChildren[1].iChildren[0].iRuleId != Parser::Nul().Id()) |
|
155 { |
|
156 const ParseResult& oper = parse->iChildren[1].iChildren[0].iChildren[0].iChildren[0].iChildren[0]; |
|
157 FormulaTreeNode* newNode = new FormulaTreeNode(EArithmetic, aFormula, oper.iStart, oper.iEnd-oper.iStart); |
|
158 newNode->iSubNodes.push_back(node); |
|
159 const ParseResult& right = parse->iChildren[1].iChildren[0].iChildren[0].iChildren[0].iChildren[1]; |
|
160 newNode->iSubNodes.push_back(NewTree(right, aFormula)); |
|
161 node = newNode; |
|
162 parse = &parse->iChildren[1].iChildren[0]; |
|
163 } |
|
164 } |
|
165 else if (parseId == comp_group_ParserId) |
|
166 { |
|
167 node = NewTree(aParse.iChildren[0].iChildren[1], aFormula); |
|
168 } |
|
169 else if (parseId == comp_ParserId) |
|
170 { |
|
171 const ParseResult& oper = aParse.iChildren[0].iChildren[0].iChildren[1]; |
|
172 node = new FormulaTreeNode(ECondition, aFormula, oper.iStart, oper.iEnd-oper.iStart); |
|
173 const ParseResult& lhs = aParse.iChildren[0].iChildren[0].iChildren[0].iChildren[0]; |
|
174 node->iSubNodes.push_back(NewTree(lhs, aFormula)); |
|
175 const ParseResult& rhs = aParse.iChildren[1]; |
|
176 node->iSubNodes.push_back(NewTree(rhs, aFormula)); |
|
177 } |
|
178 else if (parseId == conditional_ParserId) |
|
179 { |
|
180 node = new FormulaTreeNode(EConditional, aFormula, aParse.iStart, 0); |
|
181 const ParseResult& cond = aParse.iChildren[0].iChildren[0].iChildren[0].iChildren[0].iChildren[1]; |
|
182 node->iSubNodes.push_back(NewTree(cond, aFormula)); |
|
183 const ParseResult& thenExpr = aParse.iChildren[0].iChildren[0].iChildren[1]; |
|
184 node->iSubNodes.push_back(NewTree(thenExpr, aFormula)); |
|
185 const ParseResult& elseExpr = aParse.iChildren[1]; |
|
186 node->iSubNodes.push_back(NewTree(elseExpr, aFormula)); |
|
187 } |
|
188 else // internal alt node, recurse down |
|
189 { |
|
190 node = NewTree(aParse.iChildren[0], aFormula); |
|
191 } |
|
192 |
|
193 return node; |
|
194 } |
|
195 |
|
196 FormulaTreeNode::FormulaTreeNode(TNodeType aType, const string& aSource, int aStart, int aLen) |
|
197 : iSource(aSource), iStart(aStart), iLen(aLen), iType(aType) |
|
198 { |
|
199 } |
|
200 |
|
201 FormulaTreeNode::FormulaTreeNode(const FormulaTreeNode& aOther) |
|
202 : iSource(aOther.iSource), iStart(aOther.iStart), iLen(aOther.iLen), iType(aOther.iType) |
|
203 { |
|
204 for (int i=0; i<iSubNodes.size(); i++) |
|
205 delete iSubNodes[i]; |
|
206 iSubNodes.clear(); |
|
207 for (int j=0; j<aOther.iSubNodes.size(); j++) |
|
208 iSubNodes.push_back(new FormulaTreeNode(*aOther.iSubNodes[j])); |
|
209 } |
|
210 |
|
211 void FormulaTreeNode::Print(const FormulaTreeNode& aNode) |
|
212 { |
|
213 switch (aNode.Type()) |
|
214 { |
|
215 case FormulaTreeNode::EReal: // Double() = the number |
|
216 cout << aNode.Real(); |
|
217 break; |
|
218 case FormulaTreeNode::EInt: // Int() = the number |
|
219 cout << aNode.Int(); |
|
220 break; |
|
221 case FormulaTreeNode::ECell: // Char() = cell name |
|
222 cout << aNode.Char(); |
|
223 break; |
|
224 case FormulaTreeNode::EParent: // nothing special |
|
225 cout << aNode.Char(); |
|
226 break; |
|
227 case FormulaTreeNode::EParentCell: // Char() = parent cell name |
|
228 cout << "P_" << aNode.Char(); |
|
229 break; |
|
230 case FormulaTreeNode::ETableCell: // Double() = target table |
|
231 cout << aNode.Real(); |
|
232 break; |
|
233 case FormulaTreeNode::EComponent: // Double() = component id, [0] = cell name |
|
234 cout << aNode.Real() << "_"; |
|
235 Print(aNode[0]); |
|
236 break; |
|
237 case FormulaTreeNode::EAbsolute: // Text() = whole thing, [0], [1] = real components, [2] = cell name |
|
238 cout << "Abs("; |
|
239 Print(aNode[0]); |
|
240 cout << ","; |
|
241 Print(aNode[1]); |
|
242 cout << ","; |
|
243 Print(aNode[2]); |
|
244 cout << ")"; |
|
245 break; |
|
246 case FormulaTreeNode::EUnits: // Double() = units |
|
247 cout << aNode.Real() << "units"; |
|
248 break; |
|
249 case FormulaTreeNode::EConstant: // Double() = constant |
|
250 cout << "const(" << aNode.Real() << ")"; |
|
251 break; |
|
252 case FormulaTreeNode::EAttribute: // Int() = attribute |
|
253 cout << "attrib(" << aNode.Int() << ")"; |
|
254 break; |
|
255 case FormulaTreeNode::EMystery: // Text() = whole thing, [0], [1] = int components |
|
256 cout << "mystery("; |
|
257 Print(aNode[0]); |
|
258 cout << ","; |
|
259 Print(aNode[1]); |
|
260 cout << ")"; |
|
261 break; |
|
262 case FormulaTreeNode::EFunction: // Text() = function name, [0] = parameter |
|
263 cout << aNode.Text() << "("; |
|
264 Print(aNode[0]); |
|
265 cout << ")"; |
|
266 break; |
|
267 case FormulaTreeNode::EArithmetic: // Char() = arithmetic operator, [0], [1] = sub expressions |
|
268 cout << aNode.Char() << "("; |
|
269 Print(aNode[0]); |
|
270 cout << ","; |
|
271 Print(aNode[1]); |
|
272 cout << ")"; |
|
273 break; |
|
274 case FormulaTreeNode::ECondition: // Text() = comparison operator, [0], [1] = sub expressions |
|
275 cout << aNode.Text() << "("; |
|
276 Print(aNode[0]); |
|
277 cout << ","; |
|
278 Print(aNode[1]); |
|
279 cout << ")"; |
|
280 break; |
|
281 case FormulaTreeNode::EConditional: // no content, [0] = condition, [1] = then expression, [2] = else expression |
|
282 cout << "IF "; |
|
283 Print(aNode[0]); |
|
284 cout << " THEN "; |
|
285 Print(aNode[1]); |
|
286 cout << " ELSE "; |
|
287 Print(aNode[2]); |
|
288 break; |
|
289 }; |
|
290 } |
|
291 |
|
292 void Print(const ParseResult& res); |
|
293 |
|
294 |
|
295 int TestFormulaTreeNode() |
|
296 { |
|
297 string formula("IF (P_W/25p*4.25p) <= P_H THEN P_W/25p*4.25p ELSE P_H"); |
|
298 // string formula("1*2/3"); |
|
299 Print(ParseFormula(formula)); |
|
300 FormulaTreeNode* tree = FormulaTreeNode::Parse(formula); |
|
301 FormulaTreeNode::Print(*tree); |
|
302 delete tree; |
|
303 return 0; |
|
304 } |
|
305 |
|
306 // int x = TestFormulaTreeNode() |