]> git.mxchange.org Git - simgear.git/blob - simgear/structure/SGExpression.cxx
Fix for libCurl pipelining and connection count.
[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 <map>
31 #include <utility>
32 #include <string>
33 #include <sstream>
34 #include <boost/bind.hpp>
35 #include <cstring> // for strcmp
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 SGReadExpression(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 = SGReadExpression<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 SGReadExpression(SGPropertyNode *inputRoot, const SGPropertyNode *expression)
169 {
170     if (!expression)
171         return 0;
172
173     std::string name = expression->getName();
174
175     if (name == "value") {
176         T value;
177         if (!SGReadValueFromContent(expression, value)) {
178             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"value\" expression.");
179             return 0;
180         }
181         return new SGConstExpression<T>(value);
182     }
183
184     if (name == "property") {
185         if (!inputRoot) {
186             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.\n"
187                    "No inputRoot argument given!");
188             return 0;
189         }
190         if (!expression->getStringValue()) {
191             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
192             return 0;
193         }
194         SGPropertyNode* inputNode;
195         inputNode = inputRoot->getNode(expression->getStringValue(), true);
196         return new SGPropertyExpression<T>(inputNode);
197     }
198
199     if (name == "abs" || name == "fabs") {
200         if (expression->nChildren() != 1) {
201             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
202             return 0;
203         }
204         SGSharedPtr<SGExpression<T> > inputExpression;
205         inputExpression = SGReadExpression<T>(inputRoot, expression->getChild(0));
206         if (!inputExpression) {
207             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
208             return 0;
209         }
210         return new SGAbsExpression<T>(inputExpression);
211     }
212
213     if (name == "sqr") {
214         if (expression->nChildren() != 1) {
215             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
216             return 0;
217         }
218         SGSharedPtr<SGExpression<T> > inputExpression;
219         inputExpression = SGReadExpression<T>(inputRoot, expression->getChild(0));
220         if (!inputExpression) {
221             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
222             return 0;
223         }
224         return new SGSqrExpression<T>(inputExpression);
225     }
226
227     if (name == "clip") {
228         if (expression->nChildren() != 3) {
229             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
230             return 0;
231         }
232         const SGPropertyNode* minProperty = expression->getChild("clipMin");
233         T clipMin;
234         if (!SGReadValueFromContent(minProperty, clipMin))
235             clipMin = SGMisc<T>::min(SGLimits<T>::min(), -SGLimits<T>::max());
236
237         const SGPropertyNode* maxProperty = expression->getChild("clipMax");
238         T clipMax;
239         if (!SGReadValueFromContent(maxProperty, clipMax))
240             clipMin = SGLimits<T>::max();
241
242         SGSharedPtr<SGExpression<T> > inputExpression;
243         for (int i = 0; !inputExpression && i < expression->nChildren(); ++i)
244             inputExpression = SGReadExpression<T>(inputRoot, expression->getChild(i));
245         if (!inputExpression) {
246             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
247             return 0;
248         }
249         return new SGClipExpression<T>(inputExpression, clipMin, clipMax);
250     }
251
252     if (name == "div") {
253         if (expression->nChildren() != 2) {
254             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
255             return 0;
256         }
257         SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
258             SGReadExpression<T>(inputRoot, expression->getChild(0)),
259             SGReadExpression<T>(inputRoot, expression->getChild(1))
260         };
261         if (!inputExpressions[0] || !inputExpressions[1]) {
262             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
263             return 0;
264         }
265         return new SGDivExpression<T>(inputExpressions[0], inputExpressions[1]);
266     }
267     if (name == "mod") {
268         if (expression->nChildren() != 2) {
269             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
270             return 0;
271         }
272         SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
273             SGReadExpression<T>(inputRoot, expression->getChild(0)),
274             SGReadExpression<T>(inputRoot, expression->getChild(1))
275         };
276         if (!inputExpressions[0] || !inputExpressions[1]) {
277             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
278             return 0;
279         }
280         return new SGModExpression<T>(inputExpressions[0], inputExpressions[1]);
281     }
282
283     if (name == "sum") {
284         if (expression->nChildren() < 1) {
285             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
286             return 0;
287         }
288         SGSumExpression<T>* output = new SGSumExpression<T>;
289         if (!SGReadNaryOperands(output, inputRoot, expression)) {
290             delete output;
291             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
292             return 0;
293         }
294         return output;
295     }
296
297     if (name == "difference" || name == "dif" ) {
298         if (expression->nChildren() < 1) {
299             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
300             return 0;
301         }
302         SGDifferenceExpression<T>* output = new SGDifferenceExpression<T>;
303         if (!SGReadNaryOperands(output, inputRoot, expression)) {
304             delete output;
305             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
306             return 0;
307         }
308         return output;
309     }
310
311     if (name == "prod" || name == "product") {
312         if (expression->nChildren() < 1) {
313             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
314             return 0;
315         }
316         SGProductExpression<T>* output = new SGProductExpression<T>;
317         if (!SGReadNaryOperands(output, inputRoot, expression)) {
318             delete output;
319             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
320             return 0;
321         }
322         return output;
323     }
324     if (name == "min") {
325         if (expression->nChildren() < 1) {
326             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
327             return 0;
328         }
329         SGMinExpression<T>* output = new SGMinExpression<T>;
330         if (!SGReadNaryOperands(output, inputRoot, expression)) {
331             delete output;
332             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
333             return 0;
334         }
335         return output;
336     }
337     if (name == "max") {
338         if (expression->nChildren() < 1) {
339             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
340             return 0;
341         }
342         SGMaxExpression<T>* output = new SGMaxExpression<T>;
343         if (!SGReadNaryOperands(output, inputRoot, expression)) {
344             delete output;
345             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
346             return 0;
347         }
348         return output;
349     }
350
351     if (name == "table") {
352         SGInterpTable* tab = new SGInterpTable(expression);
353         if (!tab) {
354             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression: malformed table");
355             return 0;
356         }
357         
358         // find input expression - i.e a child not named 'entry'
359         const SGPropertyNode* inputNode = NULL;
360         for (int i=0; (i<expression->nChildren()) && !inputNode; ++i) {
361             if (strcmp(expression->getChild(i)->getName(), "entry") == 0) {
362                 continue;
363             }
364             
365             inputNode = expression->getChild(i);
366         }
367         
368         if (!inputNode) {
369             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression: no input found");
370             return 0;
371         }
372
373         SGSharedPtr<SGExpression<T> > inputExpression;
374         inputExpression = SGReadExpression<T>(inputRoot, inputNode);
375         if (!inputExpression) {
376             SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
377             return 0;
378         }
379         
380         return new SGInterpTableExpression<T>(inputExpression, tab);
381     }
382     
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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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 = SGReadExpression<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             SGReadExpression<T>(inputRoot, expression->getChild(0)),
633             SGReadExpression<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             SGReadExpression<T>(inputRoot, expression->getChild(0)),
648             SGReadExpression<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             SGReadExpression<T>(inputRoot, expression->getChild(0)),
663             SGReadExpression<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             SGReadExpression<T>(inputRoot, expression->getChild(0)),
678             SGReadExpression<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 SGReadExpression<int>(inputRoot, configNode); }
694
695 SGExpression<float>*
696 SGReadFloatExpression(SGPropertyNode *inputRoot,
697                       const SGPropertyNode *configNode)
698 { return SGReadExpression<float>(inputRoot, configNode); }
699
700 SGExpression<double>*
701 SGReadDoubleExpression(SGPropertyNode *inputRoot,
702                        const SGPropertyNode *configNode)
703 { return SGReadExpression<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 size_t 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     size_t 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 }