]> git.mxchange.org Git - simgear.git/blob - simgear/structure/SGExpression.cxx
dc0d3270baeacded83a09186f0447e8856050b06
[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     if (name == "table") {
336         SGInterpTable* tab = new SGInterpTable(expression);
337         if (!tab) {
338             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression: malformed table");
339             return 0;
340         }
341         
342         // find input expression - i.e a child not named 'entry'
343         const SGPropertyNode* inputNode = NULL;
344         for (int i=0; (i<expression->nChildren()) && !inputNode; ++i) {
345             if (strcmp(expression->getChild(i)->getName(), "entry") == 0) {
346                 continue;
347             }
348             
349             inputNode = expression->getChild(i);
350         }
351         
352         if (!inputNode) {
353             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression: no input found");
354             return 0;
355         }
356         
357         SGSharedPtr<SGExpression<T> > inputExpression;
358         inputExpression = SGReadIExpression<T>(inputRoot, inputNode);
359         if (!inputExpression) {
360             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
361             return 0;
362         }
363         
364         return new SGInterpTableExpression<T>(inputExpression, tab);
365     }
366     
367     return 0;
368 }
369
370
371 template<typename T>
372 static SGExpression<T>*
373 SGReadFExpression(SGPropertyNode *inputRoot, const SGPropertyNode *expression)
374 {
375     SGExpression<T>* r = SGReadIExpression<T>(inputRoot, expression);
376     if (r)
377         return r;
378
379     if (!expression)
380         return 0;
381
382     std::string name = expression->getName();
383     if (name == "acos") {
384         if (expression->nChildren() != 1) {
385             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
386             return 0;
387         }
388         SGSharedPtr<SGExpression<T> > inputExpression;
389         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
390         if (!inputExpression) {
391             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
392             return 0;
393         }
394         return new SGACosExpression<T>(inputExpression);
395     }
396
397     if (name == "asin") {
398         if (expression->nChildren() != 1) {
399             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
400             return 0;
401         }
402         SGSharedPtr<SGExpression<T> > inputExpression;
403         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
404         if (!inputExpression) {
405             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
406             return 0;
407         }
408         return new SGASinExpression<T>(inputExpression);
409     }
410
411     if (name == "atan") {
412         if (expression->nChildren() != 1) {
413             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
414             return 0;
415         }
416         SGSharedPtr<SGExpression<T> > inputExpression;
417         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
418         if (!inputExpression) {
419             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
420             return 0;
421         }
422         return new SGATanExpression<T>(inputExpression);
423     }
424
425     if (name == "ceil") {
426         if (expression->nChildren() != 1) {
427             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
428             return 0;
429         }
430         SGSharedPtr<SGExpression<T> > inputExpression;
431         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
432         if (!inputExpression) {
433             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
434             return 0;
435         }
436         return new SGCeilExpression<T>(inputExpression);
437     }
438
439     if (name == "cos") {
440         if (expression->nChildren() != 1) {
441             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
442             return 0;
443         }
444         SGSharedPtr<SGExpression<T> > inputExpression;
445         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
446         if (!inputExpression) {
447             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
448             return 0;
449         }
450         return new SGCosExpression<T>(inputExpression);
451     }
452
453     if (name == "cosh") {
454         if (expression->nChildren() != 1) {
455             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
456             return 0;
457         }
458         SGSharedPtr<SGExpression<T> > inputExpression;
459         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
460         if (!inputExpression) {
461             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
462             return 0;
463         }
464         return new SGCoshExpression<T>(inputExpression);
465     }
466
467     if (name == "deg2rad") {
468         if (expression->nChildren() != 1) {
469             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
470             return 0;
471         }
472         SGSharedPtr<SGExpression<T> > inputExpression;
473         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
474         if (!inputExpression) {
475             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
476             return 0;
477         }
478         return new SGScaleExpression<T>(inputExpression, SGMisc<T>::pi()/180);
479     }
480
481     if (name == "exp") {
482         if (expression->nChildren() != 1) {
483             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
484             return 0;
485         }
486         SGSharedPtr<SGExpression<T> > inputExpression;
487         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
488         if (!inputExpression) {
489             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
490             return 0;
491         }
492         return new SGExpExpression<T>(inputExpression);
493     }
494
495     if (name == "floor") {
496         if (expression->nChildren() != 1) {
497             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
498             return 0;
499         }
500         SGSharedPtr<SGExpression<T> > inputExpression;
501         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
502         if (!inputExpression) {
503             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
504             return 0;
505         }
506         return new SGFloorExpression<T>(inputExpression);
507     }
508
509     if (name == "log") {
510         if (expression->nChildren() != 1) {
511             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
512             return 0;
513         }
514         SGSharedPtr<SGExpression<T> > inputExpression;
515         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
516         if (!inputExpression) {
517             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
518             return 0;
519         }
520         return new SGLogExpression<T>(inputExpression);
521     }
522
523     if (name == "log10") {
524         if (expression->nChildren() != 1) {
525             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
526             return 0;
527         }
528         SGSharedPtr<SGExpression<T> > inputExpression;
529         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
530         if (!inputExpression) {
531             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
532             return 0;
533         }
534         return new SGLog10Expression<T>(inputExpression);
535     }
536
537     if (name == "rad2deg") {
538         if (expression->nChildren() != 1) {
539             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
540             return 0;
541         }
542         SGSharedPtr<SGExpression<T> > inputExpression;
543         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
544         if (!inputExpression) {
545             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
546             return 0;
547         }
548         return new SGScaleExpression<T>(inputExpression, 180/SGMisc<T>::pi());
549     }
550
551     if (name == "sin") {
552         if (expression->nChildren() != 1) {
553             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
554             return 0;
555         }
556         SGSharedPtr<SGExpression<T> > inputExpression;
557         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
558         if (!inputExpression) {
559             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
560             return 0;
561         }
562         return new SGSinExpression<T>(inputExpression);
563     }
564
565     if (name == "sinh") {
566         if (expression->nChildren() != 1) {
567             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
568             return 0;
569         }
570         SGSharedPtr<SGExpression<T> > inputExpression;
571         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
572         if (!inputExpression) {
573             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
574             return 0;
575         }
576         return new SGSinhExpression<T>(inputExpression);
577     }
578
579     if (name == "sqrt") {
580         if (expression->nChildren() != 1) {
581             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
582             return 0;
583         }
584         SGSharedPtr<SGExpression<T> > inputExpression;
585         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
586         if (!inputExpression) {
587             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
588             return 0;
589         }
590         return new SGSqrtExpression<T>(inputExpression);
591     }
592
593     if (name == "tan") {
594         if (expression->nChildren() != 1) {
595             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
596             return 0;
597         }
598         SGSharedPtr<SGExpression<T> > inputExpression;
599         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
600         if (!inputExpression) {
601             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
602             return 0;
603         }
604         return new SGTanExpression<T>(inputExpression);
605     }
606
607     if (name == "tanh") {
608         if (expression->nChildren() != 1) {
609             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
610             return 0;
611         }
612         SGSharedPtr<SGExpression<T> > inputExpression;
613         inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
614         if (!inputExpression) {
615             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
616             return 0;
617         }
618         return new SGTanhExpression<T>(inputExpression);
619     }
620     
621 // if (name == "step") {
622 // }
623 // if (name == "condition") {
624 // }
625
626     if (name == "atan2") {
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 SGAtan2Expression<T>(inputExpressions[0], inputExpressions[1]);
640     }
641     if (name == "div") {
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             SGReadFExpression<T>(inputRoot, expression->getChild(0)),
648             SGReadFExpression<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 SGDivExpression<T>(inputExpressions[0], inputExpressions[1]);
655     }
656     if (name == "mod") {
657         if (expression->nChildren() != 2) {
658             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
659             return 0;
660         }
661         SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
662             SGReadFExpression<T>(inputRoot, expression->getChild(0)),
663             SGReadFExpression<T>(inputRoot, expression->getChild(1))
664         };
665         if (!inputExpressions[0] || !inputExpressions[1]) {
666             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
667             return 0;
668         }
669         return new SGModExpression<T>(inputExpressions[0], inputExpressions[1]);
670     }
671     if (name == "pow") {
672         if (expression->nChildren() != 2) {
673             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
674             return 0;
675         }
676         SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
677             SGReadIExpression<T>(inputRoot, expression->getChild(0)),
678             SGReadIExpression<T>(inputRoot, expression->getChild(1))
679         };
680         if (!inputExpressions[0] || !inputExpressions[1]) {
681             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
682             return 0;
683         }
684         return new SGPowExpression<T>(inputExpressions[0], inputExpressions[1]);
685     }
686
687     return 0;
688 }
689
690 SGExpression<int>*
691 SGReadIntExpression(SGPropertyNode *inputRoot,
692                     const SGPropertyNode *configNode)
693 { return SGReadIExpression<int>(inputRoot, configNode); }
694
695 SGExpression<float>*
696 SGReadFloatExpression(SGPropertyNode *inputRoot,
697                       const SGPropertyNode *configNode)
698 { return SGReadFExpression<float>(inputRoot, configNode); }
699
700 SGExpression<double>*
701 SGReadDoubleExpression(SGPropertyNode *inputRoot,
702                        const SGPropertyNode *configNode)
703 { return SGReadFExpression<double>(inputRoot, configNode); }
704
705 // SGExpression<bool>*
706 // SGReadBoolExpression(SGPropertyNode *inputRoot,
707 //                      const SGPropertyNode *configNode)
708 // { return SGReadBExpression<bool>(inputRoot, configNode); }
709
710 namespace simgear
711 {
712 namespace expression
713 {
714
715 bool Parser::readChildren(const SGPropertyNode* exp,
716                           vector<Expression*>& result)
717 {
718     for (int i = 0; i < exp->nChildren(); ++i)
719         result.push_back(read(exp->getChild(i)));
720     return true;
721 }
722
723 void ExpressionParser::addExpParser(const string& token, exp_parser parsefn)
724 {
725     ParserMapSingleton::instance()
726         ->_parserTable.insert(std::make_pair(token, parsefn));
727 }
728
729 Expression* valueParser(const SGPropertyNode* exp, Parser* parser)
730 {
731     switch (exp->getType()) {
732     case props::BOOL:
733         return new SGConstExpression<bool>(getValue<bool>(exp));        
734     case props::INT:
735         return new SGConstExpression<int>(getValue<int>(exp));        
736     case props::FLOAT:
737         return new SGConstExpression<float>(getValue<float>(exp));
738     case props::DOUBLE:
739         return new SGConstExpression<double>(getValue<double>(exp));
740     default:
741         return 0;
742     }
743 }
744
745 ExpParserRegistrar valueRegistrar("value", valueParser);
746
747 template<typename T, typename OpType>
748 inline Expression* makeConvert(Expression* e)
749 {
750     return new ConvertExpression<T,
751         OpType>(static_cast<SGExpression<OpType>*>(e));
752 }
753
754 Type promoteAndConvert(vector<Expression*>& exps, Type minType = BOOL)
755 {
756     vector<Expression*>::iterator maxElem
757         = max_element(exps.begin(), exps.end());
758     Type maxType = (*maxElem)->getType();
759     Type resultType = minType < maxType ? maxType : minType;
760     for (vector<Expression*>::iterator itr = exps.begin(), end = exps.end();
761          itr != end;
762          ++itr) {
763         if ((*itr)->getType() != resultType) {
764             switch ((*itr)->getType()) {
765             case BOOL:
766                 switch (resultType) {
767                 case INT:
768                     *itr = makeConvert<int, bool>(*itr);
769                     break;
770                 case FLOAT:
771                     *itr = makeConvert<float, bool>(*itr);
772                     break;
773                 case DOUBLE:
774                     *itr = makeConvert<double, bool>(*itr);
775                     break;
776                 default:
777                     break;
778                 }
779                 break;
780             case INT:
781                 switch (resultType) {
782                 case FLOAT:
783                     *itr = makeConvert<float, int>(*itr);
784                     break;
785                 case DOUBLE:
786                     *itr = makeConvert<double, int>(*itr);
787                     break;
788                 default:
789                     break;
790                 }
791                 break;
792             case FLOAT:
793                 *itr = makeConvert<double, float>(*itr);
794                 break;
795             default:
796                 break;
797             }
798         }
799     }
800     return resultType;
801 }
802
803 template<template<typename OpType> class Expr>
804 Expression* makeTypedOperandExp(Type operandType, vector<Expression*> children)
805 {
806     switch (operandType) {
807     case BOOL:
808     {
809         Expr<bool> *expr = new Expr<bool>();
810         expr->addOperands(children.begin(), children.end());
811         return expr;
812     }
813     case INT:
814     {
815         Expr<int> *expr = new Expr<int>();
816         expr->addOperands(children.begin(), children.end());
817         return expr;
818     }
819     case FLOAT:
820     {
821         Expr<float> *expr = new Expr<float>();
822         expr->addOperands(children.begin(), children.end());
823         return expr;
824     }
825     case DOUBLE:
826     {
827         Expr<double> *expr = new Expr<double>();
828         expr->addOperands(children.begin(), children.end());
829         return expr;
830     }
831     default:
832         return 0;
833     }
834 }
835
836 template<template<typename OpType> class PredExp>
837 Expression* predParser(const SGPropertyNode* exp, Parser* parser)
838 {
839     vector<Expression*> children;
840     parser->readChildren(exp, children);
841     Type operandType = promoteAndConvert(children);
842     return makeTypedOperandExp<PredExp>(operandType, children);
843 }
844
845 ExpParserRegistrar equalRegistrar("equal", predParser<EqualToExpression>);
846 ExpParserRegistrar lessRegistrar("less", predParser<LessExpression>);
847 ExpParserRegistrar leRegistrar("less-equal", predParser<LessEqualExpression>);
848
849 template<typename Logicop>
850 Expression* logicopParser(const SGPropertyNode* exp, Parser* parser)
851 {
852     using namespace boost;
853     vector<Expression*> children;
854     parser->readChildren(exp, children);
855     vector<Expression*>::iterator notBool =
856         find_if(children.begin(), children.end(),
857                 boost::bind(&Expression::getType, _1) != BOOL);
858     if (notBool != children.end())
859         throw("non boolean operand to logical expression");
860     Logicop *expr = new Logicop;
861     expr->addOperands(children.begin(), children.end());
862     return expr;
863 }
864
865 ExpParserRegistrar andRegistrar("and", logicopParser<AndExpression>);
866 ExpParserRegistrar orRegistrar("or", logicopParser<OrExpression>);
867
868 int BindingLayout::addBinding(const string& name, Type type)
869 {
870     //XXX error checkint
871     vector<VariableBinding>::iterator itr
872         = find_if(bindings.begin(), bindings.end(),
873                   boost::bind(&VariableBinding::name, _1) == name);
874     if (itr != bindings.end())
875         return itr->location;
876     int result = bindings.size();
877     bindings.push_back(VariableBinding(name, type, bindings.size()));
878     return result;
879 }
880
881 bool BindingLayout::findBinding(const std::string& name,
882                                 VariableBinding& result) const
883 {
884     using namespace std;
885     using namespace boost;
886     vector<VariableBinding>::const_iterator itr
887         = find_if(bindings.begin(), bindings.end(),
888                   boost::bind(&VariableBinding::name, _1) == name);
889     if (itr != bindings.end()) {
890         result = *itr;
891         return true;
892     } else {
893         return false;
894     }
895 }
896 }
897 }