]> git.mxchange.org Git - simgear.git/blob - simgear/structure/SGExpression.cxx
4c746d885d74a34e5314058ab1706c86c71b7004
[simgear.git] / simgear / structure / SGExpression.cxx
1 /* -*-c++-*-
2  *
3  * Copyright (C) 2006-2007 Mathias Froehlich 
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18  * MA 02110-1301, USA.
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #  include <simgear_config.h>
24 #endif
25
26 #include "SGExpression.hxx"
27 #include "Singleton.hxx"
28
29 #include <algorithm>
30 #include <functional>
31 #include <map>
32 #include <utility>
33 #include <string>
34 #include <sstream>
35 #include <boost/bind.hpp>
36
37 #include <simgear/props/props.hxx>
38
39 using namespace std;
40
41 namespace simgear
42 {
43 template<typename T>
44 const expression::Value evalValue(const Expression* exp,
45                                   const expression::Binding* b)
46 {
47     T val;
48     static_cast<const SGExpression<T>*>(exp)->eval(val, b);
49     return expression::Value(val);
50 }
51
52 const expression::Value eval(const Expression* exp,
53                              const expression::Binding* b)
54 {
55     using namespace expression;
56     switch (exp->getType()) {
57     case BOOL:
58         return evalValue<bool>(exp, b);
59     case INT:
60         return evalValue<int>(exp, b);
61     case FLOAT:
62         return evalValue<float>(exp, b);
63     case DOUBLE:
64         return evalValue<double>(exp, b);
65     default:
66         throw "invalid type.";
67     }
68 }
69 }
70
71 template<typename T>
72 static bool
73 SGReadValueFromString(const char* str, T& value)
74 {
75     if (!str) {
76         SG_LOG(SG_IO, SG_ALERT, "Cannot read string content.");
77         return false;
78     }
79     std::stringstream s;
80     s.str(std::string(str));
81     s >> value;
82     if (s.fail()) {
83         SG_LOG(SG_IO, SG_ALERT, "Cannot read string content.");
84         return false;
85     }
86     return true;
87 }
88
89 template<>
90 bool
91 SGReadValueFromString(const char* str, bool& value)
92 {
93     if (!str) {
94         SG_LOG(SG_IO, SG_ALERT, "Cannot read string content.");
95         return false;
96     }
97     std::stringstream s;
98     s.str(std::string(str));
99     s >> value;
100     if (!s.fail())
101         return true;
102
103     std::string stdstr;
104     if (!SGReadValueFromString(str, stdstr))
105         return false;
106
107     if (stdstr == "true" || stdstr == "True" || stdstr == "TRUE") {
108         value = true;
109         return true;
110     }
111     if (stdstr == "false" || stdstr == "False" || stdstr == "FALSE") {
112         value = true;
113         return true;
114     }
115     return false;
116 }
117
118 template<typename T>
119 static bool
120 SGReadValueFromContent(const SGPropertyNode *node, T& value)
121 {
122     if (!node)
123         return false;
124     return SGReadValueFromString(node->getStringValue(), value);
125 }
126
127 template<typename T>
128 static SGExpression<T>*
129 SGReadIExpression(SGPropertyNode *inputRoot, const SGPropertyNode *expression);
130
131 template<typename T>
132 static bool
133 SGReadNaryOperands(SGNaryExpression<T>* nary,
134                    SGPropertyNode *inputRoot, const SGPropertyNode *expression)
135 {
136     for (int i = 0; i < expression->nChildren(); ++i) {
137         SGExpression<T>* inputExpression;
138         inputExpression = SGReadIExpression<T>(inputRoot, expression->getChild(i));
139         if (!inputExpression)
140             return false;
141         nary->addOperand(inputExpression);
142     }
143     return true;
144 }
145
146 // template<typename T>
147 // static SGExpression<T>*
148 // SGReadBExpression(SGPropertyNode *inputRoot, const SGPropertyNode *expression)
149 // {
150 //   if (!expression)
151 //     return 0;
152
153 //   std::string name = expression->getName();
154 //   if (name == "value") {
155 //     T value;
156 //     if (!SGReadValueFromContent(expression, value)) {
157 //       SG_LOG(SG_IO, SG_ALERT, "Cannot read \"value\" expression.");
158 //       return 0;
159 //     }
160 //     return new SGConstExpression<T>(value);
161 //   }
162
163 //   return 0;
164 // }
165
166 template<typename T>
167 static SGExpression<T>*
168 SGReadIExpression(SGPropertyNode *inputRoot, const SGPropertyNode *expression)
169 {
170     if (!expression)
171         return 0;
172
173     std::string name = expression->getName();
174     if (name == "value") {
175         T value;
176         if (!SGReadValueFromContent(expression, value)) {
177             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"value\" expression.");
178             return 0;
179         }
180         return new SGConstExpression<T>(value);
181     }
182
183     if (name == "property") {
184         if (!inputRoot) {
185             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.\n"
186                    "No inputRoot argument given!");
187             return 0;
188         }
189         if (!expression->getStringValue()) {
190             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
191             return 0;
192         }
193         SGPropertyNode* inputNode;
194         inputNode = inputRoot->getNode(expression->getStringValue(), true);
195         return new SGPropertyExpression<T>(inputNode);
196     }
197
198     if (name == "abs" || name == "fabs") {
199         if (expression->nChildren() != 1) {
200             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
201             return 0;
202         }
203         SGSharedPtr<SGExpression<T> > inputExpression;
204         inputExpression = SGReadIExpression<T>(inputRoot, expression->getChild(0));
205         if (!inputExpression) {
206             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
207             return 0;
208         }
209         return new SGAbsExpression<T>(inputExpression);
210     }
211
212     if (name == "sqr") {
213         if (expression->nChildren() != 1) {
214             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
215             return 0;
216         }
217         SGSharedPtr<SGExpression<T> > inputExpression;
218         inputExpression = SGReadIExpression<T>(inputRoot, expression->getChild(0));
219         if (!inputExpression) {
220             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
221             return 0;
222         }
223         return new SGSqrExpression<T>(inputExpression);
224     }
225
226     if (name == "clip") {
227         if (expression->nChildren() != 3) {
228             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
229             return 0;
230         }
231         const SGPropertyNode* minProperty = expression->getChild("clipMin");
232         T clipMin;
233         if (!SGReadValueFromContent(minProperty, clipMin))
234             clipMin = SGMisc<T>::min(SGLimits<T>::min(), -SGLimits<T>::max());
235
236         const SGPropertyNode* maxProperty = expression->getChild("clipMax");
237         T clipMax;
238         if (!SGReadValueFromContent(maxProperty, clipMax))
239             clipMin = SGLimits<T>::max();
240
241         SGSharedPtr<SGExpression<T> > inputExpression;
242         for (int i = 0; !inputExpression && i < expression->nChildren(); ++i)
243             inputExpression = SGReadIExpression<T>(inputRoot, expression->getChild(i));
244         if (!inputExpression) {
245             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
246             return 0;
247         }
248         return new SGClipExpression<T>(inputExpression, clipMin, clipMax);
249     }
250
251     if (name == "div") {
252         if (expression->nChildren() != 2) {
253             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
254             return 0;
255         }
256         SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
257             SGReadIExpression<T>(inputRoot, expression->getChild(0)),
258             SGReadIExpression<T>(inputRoot, expression->getChild(1))
259         };
260         if (!inputExpressions[0] || !inputExpressions[1]) {
261             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
262             return 0;
263         }
264         return new SGDivExpression<T>(inputExpressions[0], inputExpressions[1]);
265     }
266     if (name == "mod") {
267         if (expression->nChildren() != 2) {
268             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
269             return 0;
270         }
271         SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
272             SGReadIExpression<T>(inputRoot, expression->getChild(0)),
273             SGReadIExpression<T>(inputRoot, expression->getChild(1))
274         };
275         if (!inputExpressions[0] || !inputExpressions[1]) {
276             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
277             return 0;
278         }
279         return new SGModExpression<T>(inputExpressions[0], inputExpressions[1]);
280     }
281
282     if (name == "sum") {
283         if (expression->nChildren() < 1) {
284             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
285             return 0;
286         }
287         SGSumExpression<T>* output = new SGSumExpression<T>;
288         if (!SGReadNaryOperands(output, inputRoot, expression)) {
289             delete output;
290             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
291             return 0;
292         }
293         return output;
294     }
295     if (name == "prod" || name == "product") {
296         if (expression->nChildren() < 1) {
297             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
298             return 0;
299         }
300         SGProductExpression<T>* output = new SGProductExpression<T>;
301         if (!SGReadNaryOperands(output, inputRoot, expression)) {
302             delete output;
303             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
304             return 0;
305         }
306         return output;
307     }
308     if (name == "min") {
309         if (expression->nChildren() < 1) {
310             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
311             return 0;
312         }
313         SGMinExpression<T>* output = new SGMinExpression<T>;
314         if (!SGReadNaryOperands(output, inputRoot, expression)) {
315             delete output;
316             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
317             return 0;
318         }
319         return output;
320     }
321     if (name == "max") {
322         if (expression->nChildren() < 1) {
323             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
324             return 0;
325         }
326         SGMaxExpression<T>* output = new SGMaxExpression<T>;
327         if (!SGReadNaryOperands(output, inputRoot, expression)) {
328             delete output;
329             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
330             return 0;
331         }
332         return output;
333     }
334
335     return 0;
336 }
337
338
339 template<typename T>
340 static SGExpression<T>*
341 SGReadFExpression(SGPropertyNode *inputRoot, const SGPropertyNode *expression)
342 {
343     SGExpression<T>* r = SGReadIExpression<T>(inputRoot, expression);
344     if (r)
345         return r;
346
347     if (!expression)
348         return 0;
349
350     std::string name = expression->getName();
351     if (name == "acos") {
352         if (expression->nChildren() != 1) {
353             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
354             return 0;
355         }
356         SGSharedPtr<SGExpression<T> > inputExpression;
357         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
358         if (!inputExpression) {
359             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
360             return 0;
361         }
362         return new SGACosExpression<T>(inputExpression);
363     }
364
365     if (name == "asin") {
366         if (expression->nChildren() != 1) {
367             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
368             return 0;
369         }
370         SGSharedPtr<SGExpression<T> > inputExpression;
371         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
372         if (!inputExpression) {
373             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
374             return 0;
375         }
376         return new SGASinExpression<T>(inputExpression);
377     }
378
379     if (name == "atan") {
380         if (expression->nChildren() != 1) {
381             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
382             return 0;
383         }
384         SGSharedPtr<SGExpression<T> > inputExpression;
385         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
386         if (!inputExpression) {
387             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
388             return 0;
389         }
390         return new SGATanExpression<T>(inputExpression);
391     }
392
393     if (name == "ceil") {
394         if (expression->nChildren() != 1) {
395             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
396             return 0;
397         }
398         SGSharedPtr<SGExpression<T> > inputExpression;
399         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
400         if (!inputExpression) {
401             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
402             return 0;
403         }
404         return new SGCeilExpression<T>(inputExpression);
405     }
406
407     if (name == "cos") {
408         if (expression->nChildren() != 1) {
409             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
410             return 0;
411         }
412         SGSharedPtr<SGExpression<T> > inputExpression;
413         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
414         if (!inputExpression) {
415             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
416             return 0;
417         }
418         return new SGCosExpression<T>(inputExpression);
419     }
420
421     if (name == "cosh") {
422         if (expression->nChildren() != 1) {
423             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
424             return 0;
425         }
426         SGSharedPtr<SGExpression<T> > inputExpression;
427         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
428         if (!inputExpression) {
429             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
430             return 0;
431         }
432         return new SGCoshExpression<T>(inputExpression);
433     }
434
435     if (name == "deg2rad") {
436         if (expression->nChildren() != 1) {
437             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
438             return 0;
439         }
440         SGSharedPtr<SGExpression<T> > inputExpression;
441         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
442         if (!inputExpression) {
443             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
444             return 0;
445         }
446         return new SGScaleExpression<T>(inputExpression, SGMisc<T>::pi()/180);
447     }
448
449     if (name == "exp") {
450         if (expression->nChildren() != 1) {
451             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
452             return 0;
453         }
454         SGSharedPtr<SGExpression<T> > inputExpression;
455         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
456         if (!inputExpression) {
457             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
458             return 0;
459         }
460         return new SGExpExpression<T>(inputExpression);
461     }
462
463     if (name == "floor") {
464         if (expression->nChildren() != 1) {
465             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
466             return 0;
467         }
468         SGSharedPtr<SGExpression<T> > inputExpression;
469         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
470         if (!inputExpression) {
471             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
472             return 0;
473         }
474         return new SGFloorExpression<T>(inputExpression);
475     }
476
477     if (name == "log") {
478         if (expression->nChildren() != 1) {
479             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
480             return 0;
481         }
482         SGSharedPtr<SGExpression<T> > inputExpression;
483         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
484         if (!inputExpression) {
485             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
486             return 0;
487         }
488         return new SGLogExpression<T>(inputExpression);
489     }
490
491     if (name == "log10") {
492         if (expression->nChildren() != 1) {
493             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
494             return 0;
495         }
496         SGSharedPtr<SGExpression<T> > inputExpression;
497         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
498         if (!inputExpression) {
499             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
500             return 0;
501         }
502         return new SGLog10Expression<T>(inputExpression);
503     }
504
505     if (name == "rad2deg") {
506         if (expression->nChildren() != 1) {
507             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
508             return 0;
509         }
510         SGSharedPtr<SGExpression<T> > inputExpression;
511         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
512         if (!inputExpression) {
513             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
514             return 0;
515         }
516         return new SGScaleExpression<T>(inputExpression, 180/SGMisc<T>::pi());
517     }
518
519     if (name == "sin") {
520         if (expression->nChildren() != 1) {
521             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
522             return 0;
523         }
524         SGSharedPtr<SGExpression<T> > inputExpression;
525         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
526         if (!inputExpression) {
527             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
528             return 0;
529         }
530         return new SGSinExpression<T>(inputExpression);
531     }
532
533     if (name == "sinh") {
534         if (expression->nChildren() != 1) {
535             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
536             return 0;
537         }
538         SGSharedPtr<SGExpression<T> > inputExpression;
539         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
540         if (!inputExpression) {
541             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
542             return 0;
543         }
544         return new SGSinhExpression<T>(inputExpression);
545     }
546
547     if (name == "sqrt") {
548         if (expression->nChildren() != 1) {
549             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
550             return 0;
551         }
552         SGSharedPtr<SGExpression<T> > inputExpression;
553         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
554         if (!inputExpression) {
555             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
556             return 0;
557         }
558         return new SGSqrtExpression<T>(inputExpression);
559     }
560
561     if (name == "tan") {
562         if (expression->nChildren() != 1) {
563             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
564             return 0;
565         }
566         SGSharedPtr<SGExpression<T> > inputExpression;
567         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
568         if (!inputExpression) {
569             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
570             return 0;
571         }
572         return new SGTanExpression<T>(inputExpression);
573     }
574
575     if (name == "tanh") {
576         if (expression->nChildren() != 1) {
577             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
578             return 0;
579         }
580         SGSharedPtr<SGExpression<T> > inputExpression;
581         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
582         if (!inputExpression) {
583             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
584             return 0;
585         }
586         return new SGTanhExpression<T>(inputExpression);
587     }
588
589 // if (name == "table") {
590 // }
591 // if (name == "step") {
592 // }
593 // if (name == "condition") {
594 // }
595
596     if (name == "atan2") {
597         if (expression->nChildren() != 2) {
598             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
599             return 0;
600         }
601         SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
602             SGReadFExpression<T>(inputRoot, expression->getChild(0)),
603             SGReadFExpression<T>(inputRoot, expression->getChild(1))
604         };
605         if (!inputExpressions[0] || !inputExpressions[1]) {
606             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
607             return 0;
608         }
609         return new SGAtan2Expression<T>(inputExpressions[0], inputExpressions[1]);
610     }
611     if (name == "div") {
612         if (expression->nChildren() != 2) {
613             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
614             return 0;
615         }
616         SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
617             SGReadFExpression<T>(inputRoot, expression->getChild(0)),
618             SGReadFExpression<T>(inputRoot, expression->getChild(1))
619         };
620         if (!inputExpressions[0] || !inputExpressions[1]) {
621             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
622             return 0;
623         }
624         return new SGDivExpression<T>(inputExpressions[0], inputExpressions[1]);
625     }
626     if (name == "mod") {
627         if (expression->nChildren() != 2) {
628             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
629             return 0;
630         }
631         SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
632             SGReadFExpression<T>(inputRoot, expression->getChild(0)),
633             SGReadFExpression<T>(inputRoot, expression->getChild(1))
634         };
635         if (!inputExpressions[0] || !inputExpressions[1]) {
636             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
637             return 0;
638         }
639         return new SGModExpression<T>(inputExpressions[0], inputExpressions[1]);
640     }
641     if (name == "pow") {
642         if (expression->nChildren() != 2) {
643             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
644             return 0;
645         }
646         SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
647             SGReadIExpression<T>(inputRoot, expression->getChild(0)),
648             SGReadIExpression<T>(inputRoot, expression->getChild(1))
649         };
650         if (!inputExpressions[0] || !inputExpressions[1]) {
651             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
652             return 0;
653         }
654         return new SGPowExpression<T>(inputExpressions[0], inputExpressions[1]);
655     }
656
657     return 0;
658 }
659
660 SGExpression<int>*
661 SGReadIntExpression(SGPropertyNode *inputRoot,
662                     const SGPropertyNode *configNode)
663 { return SGReadIExpression<int>(inputRoot, configNode); }
664
665 SGExpression<float>*
666 SGReadFloatExpression(SGPropertyNode *inputRoot,
667                       const SGPropertyNode *configNode)
668 { return SGReadFExpression<float>(inputRoot, configNode); }
669
670 SGExpression<double>*
671 SGReadDoubleExpression(SGPropertyNode *inputRoot,
672                        const SGPropertyNode *configNode)
673 { return SGReadFExpression<double>(inputRoot, configNode); }
674
675 // SGExpression<bool>*
676 // SGReadBoolExpression(SGPropertyNode *inputRoot,
677 //                      const SGPropertyNode *configNode)
678 // { return SGReadBExpression<bool>(inputRoot, configNode); }
679
680 namespace simgear
681 {
682 namespace expression
683 {
684
685 class Parser {
686 public:
687     void addParser(const std::string& name, exp_parser parser)
688     {
689         _parserTable.insert(std::make_pair(name, parser));
690     }
691     Expression* read(const SGPropertyNode* exp)
692     {
693         ParserMap::iterator itr = _parserTable.find(exp->getName());
694         if (itr == _parserTable.end())
695             throw ParseError(string("unknown expression ") + exp->getName());
696         exp_parser parser = itr->second;
697         return (*parser)(exp, this);
698     }
699     // XXX vector of SGSharedPtr?
700     bool readChildren(const SGPropertyNode* exp,
701                       vector<Expression*>& result);
702 protected:
703     typedef std::map<const std::string, exp_parser> ParserMap;
704     ParserMap _parserTable;
705 };
706
707 class ExpressionParser : public Parser, public Singleton<ExpressionParser>
708 {
709 };
710
711 void addExpParser(const string& token, exp_parser parsefn)
712 {
713     ExpressionParser::instance()->addParser(token, parsefn);
714 }
715
716 Expression* read(const SGPropertyNode* exp, Parser* parser)
717 {
718     if (!parser)
719         parser = ExpressionParser::instance();
720     return parser->read(exp);
721 }
722
723 bool Parser::readChildren(const SGPropertyNode* exp,
724                           vector<Expression*>& result)
725 {
726     for (int i = 0; i < exp->nChildren(); ++i)
727         result.push_back(read(exp->getChild(i)));
728     return true;
729 }
730
731 Expression* valueParser(const SGPropertyNode* exp, Parser* parser)
732 {
733     switch (exp->getType()) {
734     case props::BOOL:
735         return new SGConstExpression<bool>(getValue<bool>(exp));        
736     case props::INT:
737         return new SGConstExpression<int>(getValue<int>(exp));        
738     case props::FLOAT:
739         return new SGConstExpression<float>(getValue<float>(exp));
740     case props::DOUBLE:
741         return new SGConstExpression<double>(getValue<double>(exp));
742     default:
743         return 0;
744     }
745 }
746
747 ExpParserRegistrar valueRegistrar("value", valueParser);
748
749 template<typename T, typename OpType>
750 inline Expression* makeConvert(Expression* e)
751 {
752     return new ConvertExpression<T,
753         OpType>(static_cast<SGExpression<OpType>*>(e));
754 }
755
756 Type promoteAndConvert(vector<Expression*>& exps, Type minType = BOOL)
757 {
758     vector<Expression*>::iterator maxElem
759         = max_element(exps.begin(), exps.end());
760     Type maxType = (*maxElem)->getType();
761     Type resultType = minType < maxType ? maxType : minType;
762     for (vector<Expression*>::iterator itr = exps.begin(), end = exps.end();
763          itr != end;
764          ++itr) {
765         if ((*itr)->getType() != resultType) {
766             switch ((*itr)->getType()) {
767             case BOOL:
768                 switch (resultType) {
769                 case INT:
770                     *itr = makeConvert<int, bool>(*itr);
771                     break;
772                 case FLOAT:
773                     *itr = makeConvert<float, bool>(*itr);
774                     break;
775                 case DOUBLE:
776                     *itr = makeConvert<double, bool>(*itr);
777                     break;
778                 default:
779                     break;
780                 }
781                 break;
782             case INT:
783                 switch (resultType) {
784                 case FLOAT:
785                     *itr = makeConvert<float, int>(*itr);
786                     break;
787                 case DOUBLE:
788                     *itr = makeConvert<double, int>(*itr);
789                     break;
790                 default:
791                     break;
792                 }
793                 break;
794             case FLOAT:
795                 *itr = makeConvert<double, float>(*itr);
796                 break;
797             default:
798                 break;
799             }
800         }
801     }
802     return resultType;
803 }
804
805 template<template<typename OpType> class Expr>
806 Expression* makeTypedOperandExp(Type operandType, vector<Expression*> children)
807 {
808     switch (operandType) {
809     case BOOL:
810     {
811         Expr<bool> *expr = new Expr<bool>();
812         expr->addOperands(children.begin(), children.end());
813         return expr;
814     }
815     case INT:
816     {
817         Expr<int> *expr = new Expr<int>();
818         expr->addOperands(children.begin(), children.end());
819         return expr;
820     }
821     case FLOAT:
822     {
823         Expr<float> *expr = new Expr<float>();
824         expr->addOperands(children.begin(), children.end());
825         return expr;
826     }
827     case DOUBLE:
828     {
829         Expr<double> *expr = new Expr<double>();
830         expr->addOperands(children.begin(), children.end());
831         return expr;
832     }
833     default:
834         return 0;
835     }
836 }
837
838 template<template<typename OpType> class PredExp>
839 Expression* predParser(const SGPropertyNode* exp, Parser* parser)
840 {
841     vector<Expression*> children;
842     parser->readChildren(exp, children);
843     Type operandType = promoteAndConvert(children);
844     return makeTypedOperandExp<PredExp>(operandType, children);
845 }
846
847 ExpParserRegistrar equalRegistrar("equal", predParser<EqualToExpression>);
848 ExpParserRegistrar lessRegistrar("less", predParser<LessExpression>);
849 ExpParserRegistrar leRegistrar("less-equal", predParser<LessEqualExpression>);
850
851 template<typename Logicop>
852 Expression* logicopParser(const SGPropertyNode* exp, Parser* parser)
853 {
854     using namespace boost;
855     vector<Expression*> children;
856     parser->readChildren(exp, children);
857     vector<Expression*>::iterator notBool =
858         find_if(children.begin(), children.end(),
859                 bind(&Expression::getType, _1) != BOOL);
860     if (notBool != children.end())
861         throw("non boolean operand to logical expression");
862     Logicop *expr = new Logicop;
863     expr->addOperands(children.begin(), children.end());
864     return expr;
865 }
866
867 ExpParserRegistrar andRegistrar("and", logicopParser<AndExpression>);
868 ExpParserRegistrar orRegistrar("or", logicopParser<OrExpression>);
869
870
871 int BindingLayout::addBinding(const string& name, Type type)
872 {
873     //XXX error checkint
874     int result = bindings.size();
875     bindings.push_back(VariableBinding(name, type, bindings.size()));
876     return result;
877 }
878
879 bool BindingLayout::findBinding(const std::string& name,
880                                 VariableBinding& result) const
881 {
882     using namespace std;
883     using namespace boost;
884     vector<VariableBinding>::const_iterator itr
885         = find_if(bindings.begin(), bindings.end(),
886                   bind(&VariableBinding::name, _1) == name);
887     if (itr != bindings.end()) {
888         result = *itr;
889         return true;
890     } else {
891         return false;
892     }
893 }
894 }
895 }