MADARA  3.2.3
Interpreter.cpp
Go to the documentation of this file.
1 #ifndef _INTERPRETER_CPP_
2 #define _INTERPRETER_CPP_
3 
4 #ifndef _MADARA_NO_KARL_
5 
6 #include <math.h>
7 #include <iostream>
8 #include <sstream>
9 #include <memory>
10 
86 
88 
89 namespace madara
90 {
91  namespace expression
92  {
93  enum
94  {
111  };
112 
117  class Symbol
118  {
119  public:
122  Symbol * left, Symbol * right, int precedence_ = 0);
123 
125  virtual ~Symbol (void);
126 
129  virtual int precedence (void)
130  {
131  return precedence_;
132  }
133 
134  virtual int add_precedence (int accumulated_precedence) = 0;
135 
137 
138  virtual ComponentNode * build (void) = 0;
139 
141 
146  };
147 
148  typedef std::vector <Symbol *> Symbols;
149 
155  class Operator : public Symbol
156  {
157  public:
160  Symbol * left, Symbol * right, int precedence_ = 1);
161 
163  virtual ~Operator (void);
164  };
165 
171  class TernaryOperator : public Operator
172  {
173  public:
176  Symbol * left, Symbol * right, int precedence_ = 1);
177 
179  virtual ~TernaryOperator (void);
180 
182  };
183 
190  {
191  public:
194 
196  virtual ~SystemCall (void);
197 
200  };
201 
206  class ClearVariable : public SystemCall
207  {
208  public:
210  ClearVariable (
212 
214  virtual int add_precedence (int accumulated_precedence);
215 
217  virtual ComponentNode * build (void);
218 
220  virtual ~ClearVariable (void);
221  };
222 
223 
228  class DeleteVariable : public SystemCall
229  {
230  public:
234 
236  virtual int add_precedence (int accumulated_precedence);
237 
239  virtual ComponentNode * build (void);
240 
242  virtual ~DeleteVariable (void);
243  };
244 
249  class Eval : public SystemCall
250  {
251  public:
254 
256  virtual int add_precedence (int accumulated_precedence);
257 
259  virtual ComponentNode * build (void);
260 
262  virtual ~Eval (void);
263  };
264 
269  class ExpandEnv : public SystemCall
270  {
271  public:
273  ExpandEnv (
275 
277  virtual int add_precedence (int accumulated_precedence);
278 
280  virtual ComponentNode * build (void);
281 
283  virtual ~ExpandEnv (void);
284  };
285 
291  {
292  public:
296 
298  virtual int add_precedence (int accumulated_precedence);
299 
301  virtual ComponentNode * build (void);
302 
304  virtual ~ExpandStatement (void);
305  };
306 
311  class Fragment : public SystemCall
312  {
313  public:
316 
318  virtual int add_precedence (int accumulated_precedence);
319 
321  virtual ComponentNode * build (void);
322 
324  virtual ~Fragment (void);
325  };
326 
331  class Print : public SystemCall
332  {
333  public:
336 
338  virtual int add_precedence (int accumulated_precedence);
339 
341  virtual ComponentNode * build (void);
342 
344  virtual ~Print (void);
345  };
346 
351  class Cos : public SystemCall
352  {
353  public:
355  Cos (
357 
359  virtual int add_precedence (int accumulated_precedence);
360 
362  virtual ComponentNode * build (void);
363 
365  virtual ~Cos (void);
366  };
367 
372  class Sin : public SystemCall
373  {
374  public:
376  Sin (
378 
380  virtual int add_precedence (int accumulated_precedence);
381 
383  virtual ComponentNode * build (void);
384 
386  virtual ~Sin (void);
387  };
388 
393  class Tan : public SystemCall
394  {
395  public:
397  Tan (
399 
401  virtual int add_precedence (int accumulated_precedence);
402 
404  virtual ComponentNode * build (void);
405 
407  virtual ~Tan (void);
408  };
409 
414  class Power : public SystemCall
415  {
416  public:
418  Power (
420 
422  virtual int add_precedence (int accumulated_precedence);
423 
425  virtual ComponentNode * build (void);
426 
428  virtual ~Power (void);
429  };
430 
435  class SquareRoot : public SystemCall
436  {
437  public:
439  SquareRoot (
441 
443  virtual int add_precedence (int accumulated_precedence);
444 
446  virtual ComponentNode * build (void);
447 
449  virtual ~SquareRoot (void);
450  };
451 
457  {
458  public:
462 
464  virtual int add_precedence (int accumulated_precedence);
465 
467  virtual ComponentNode * build (void);
468 
470  virtual ~PrintSystemCalls (void);
471  };
472 
477  class RandDouble : public SystemCall
478  {
479  public:
482 
484  virtual int add_precedence (int accumulated_precedence);
485 
487  virtual ComponentNode * build (void);
488 
490  virtual ~RandDouble (void);
491  };
492 
497  class RandInt : public SystemCall
498  {
499  public:
502 
504  virtual int add_precedence (int accumulated_precedence);
505 
507  virtual ComponentNode * build (void);
508 
510  virtual ~RandInt (void);
511  };
512 
517  class ReadFile : public SystemCall
518  {
519  public:
522 
524  virtual int add_precedence (int accumulated_precedence);
525 
527  virtual ComponentNode * build (void);
528 
530  virtual ~ReadFile (void);
531  };
532 
537  class WriteFile : public SystemCall
538  {
539  public:
542 
544  virtual int add_precedence (int accumulated_precedence);
545 
547  virtual ComponentNode * build (void);
548 
550  virtual ~WriteFile (void);
551  };
552 
557  class Size : public SystemCall
558  {
559  public:
562 
564  virtual int add_precedence (int accumulated_precedence);
565 
567  virtual ComponentNode * build (void);
568 
570  virtual ~Size (void);
571  };
572 
577  class SetFixed : public SystemCall
578  {
579  public:
582 
584  virtual int add_precedence (int accumulated_precedence);
585 
587  virtual ComponentNode * build (void);
588 
590  virtual ~SetFixed (void);
591  };
592 
597  class SetPrecision : public SystemCall
598  {
599  public:
602 
604  virtual int add_precedence (int accumulated_precedence);
605 
607  virtual ComponentNode * build (void);
608 
610  virtual ~SetPrecision (void);
611  };
612 
617  class SetScientific : public SystemCall
618  {
619  public:
622 
624  virtual int add_precedence (int accumulated_precedence);
625 
627  virtual ComponentNode * build (void);
628 
630  virtual ~SetScientific (void);
631  };
632 
637  class ToBuffer : public SystemCall
638  {
639  public:
642 
644  virtual int add_precedence (int accumulated_precedence);
645 
647  virtual ComponentNode * build (void);
648 
650  virtual ~ToBuffer (void);
651  };
652 
657  class ToDouble : public SystemCall
658  {
659  public:
662 
664  virtual int add_precedence (int accumulated_precedence);
665 
667  virtual ComponentNode * build (void);
668 
670  virtual ~ToDouble (void);
671  };
672 
677  class ToDoubles : public SystemCall
678  {
679  public:
682 
684  virtual int add_precedence (int accumulated_precedence);
685 
687  virtual ComponentNode * build (void);
688 
690  virtual ~ToDoubles (void);
691  };
692 
698  class ToHostDirs : public SystemCall
699  {
700  public:
703 
705  virtual int add_precedence (int accumulated_precedence);
706 
708  virtual ComponentNode * build (void);
709 
711  virtual ~ToHostDirs (void);
712  };
713 
718  class ToInteger : public SystemCall
719  {
720  public:
723 
725  virtual int add_precedence (int accumulated_precedence);
726 
728  virtual ComponentNode * build (void);
729 
731  virtual ~ToInteger (void);
732  };
733 
738  class ToIntegers : public SystemCall
739  {
740  public:
743 
745  virtual int add_precedence (int accumulated_precedence);
746 
748  virtual ComponentNode * build (void);
749 
751  virtual ~ToIntegers (void);
752  };
753 
758  class ToString : public SystemCall
759  {
760  public:
763 
765  virtual int add_precedence (int accumulated_precedence);
766 
768  virtual ComponentNode * build (void);
769 
771  virtual ~ToString (void);
772  };
773 
778  class Sleep : public SystemCall
779  {
780  public:
783 
785  virtual int add_precedence (int accumulated_precedence);
786 
788  virtual ComponentNode * build (void);
789 
791  virtual ~Sleep (void);
792  };
793 
798  class Type : public SystemCall
799  {
800  public:
803 
805  virtual int add_precedence (int accumulated_precedence);
806 
808  virtual ComponentNode * build (void);
809 
811  virtual ~Type (void);
812  };
813 
818  class Isinf : public SystemCall
819  {
820  public:
823 
825  virtual int add_precedence (int accumulated_precedence);
826 
828  virtual ComponentNode * build (void);
829 
831  virtual ~Isinf (void);
832  };
833 
838  class LogLevel : public SystemCall
839  {
840  public:
843 
845  virtual int add_precedence (int accumulated_precedence);
846 
848  virtual ComponentNode * build (void);
849 
851  virtual ~LogLevel (void);
852  };
853 
858  class GetClock : public SystemCall
859  {
860  public:
863 
865  virtual int add_precedence (int accumulated_precedence);
866 
868  virtual ComponentNode * build (void);
869 
871  virtual ~GetClock (void);
872  };
873 
878  class GetTime : public SystemCall
879  {
880  public:
883 
885  virtual int add_precedence (int accumulated_precedence);
886 
888  virtual ComponentNode * build (void);
889 
891  virtual ~GetTime (void);
892  };
893 
898  class GetTimeSeconds : public SystemCall
899  {
900  public:
903 
905  virtual int add_precedence (int accumulated_precedence);
906 
908  virtual ComponentNode * build (void);
909 
911  virtual ~GetTimeSeconds (void);
912  };
913 
918  class SetClock : public SystemCall
919  {
920  public:
923 
925  virtual int add_precedence (int accumulated_precedence);
926 
928  virtual ComponentNode * build (void);
929 
931  virtual ~SetClock (void);
932  };
933 
934 
940  class UnaryOperator : public Symbol
941  {
942  public:
945  Symbol * right, int precedence_ = 1);
946 
948  virtual ~UnaryOperator (void);
949  };
950 
956  class Number : public Symbol
957  {
958  public:
962  Number (logger::Logger & logger, double input);
963 
965  virtual ~Number (void);
966 
968  //virtual int precedence (void);
969  virtual int add_precedence (int accumulated_precedence);
970 
972  virtual ComponentNode *build (void);
973  // private:
976  };
977 
982  class Variable : public Symbol
983  {
984  public:
986  Variable (const std::string & key,
988 
990  virtual ~Variable (void);
991 
993  //virtual int precedence (void);
994  virtual int add_precedence (int accumulated_precedence);
995 
997  virtual ComponentNode * build (void);
998  //private:
1001 
1004  };
1005 
1010  class ArrayRef : public Symbol
1011  {
1012  public:
1014  ArrayRef (const std::string & key, Symbol * index,
1016 
1018  virtual ~ArrayRef (void);
1019 
1021  //virtual int precedence (void);
1022  virtual int add_precedence (int accumulated_precedence);
1023 
1025  virtual ComponentNode * build (void);
1026  //private:
1029 
1033  };
1034 
1041  {
1042  public:
1044  VariableDecrement (Symbol * lhs,
1046  Symbol * rhs,
1048 
1050  virtual ~VariableDecrement (void);
1051 
1053  //virtual int precedence (void);
1054  virtual int add_precedence (int accumulated_precedence);
1055 
1057  virtual ComponentNode *build (void);
1058  //private:
1060 
1063 
1066  };
1067 
1073  class VariableDivide : public Operator
1074  {
1075  public:
1077  VariableDivide (Symbol * lhs,
1079  Symbol * rhs,
1081 
1083  virtual ~VariableDivide (void);
1084 
1086  //virtual int precedence (void);
1087  virtual int add_precedence (int accumulated_precedence);
1088 
1090  virtual ComponentNode *build (void);
1091  //private:
1093 
1096 
1099  };
1100 
1107  {
1108  public:
1110  VariableIncrement (Symbol * lhs,
1112  Symbol * rhs,
1114 
1116  virtual ~VariableIncrement (void);
1117 
1119  //virtual int precedence (void);
1120  virtual int add_precedence (int accumulated_precedence);
1121 
1123  virtual ComponentNode *build (void);
1124  //private:
1126 
1129 
1132  };
1133 
1140  {
1141  public:
1143  VariableMultiply (Symbol * lhs,
1145  Symbol * rhs,
1147 
1149  virtual ~VariableMultiply (void);
1150 
1152  //virtual int precedence (void);
1153  virtual int add_precedence (int accumulated_precedence);
1154 
1156  virtual ComponentNode * build (void);
1157  //private:
1159 
1162 
1165  };
1166 
1172  class VariableCompare : public Symbol
1173  {
1174  public:
1176  VariableCompare (Symbol * lhs,
1178  Symbol * rhs, int compare_type,
1180 
1182  virtual ~VariableCompare (void);
1183 
1185  //virtual int precedence (void);
1186  virtual int add_precedence (int accumulated_precedence);
1187 
1189  virtual ComponentNode *build (void);
1190  //private:
1192 
1195 
1198 
1201 
1204  };
1205 
1206 
1212  class List : public Symbol
1213  {
1214  public:
1216  List (
1218 
1220  virtual ~List (void);
1221 
1223  //virtual int precedence (void);
1224  virtual int add_precedence (int accumulated_precedence);
1225 
1227  virtual ComponentNode * build (void);
1228  private:
1229 
1232  };
1233 
1239  class Subtract : public Operator
1240  {
1241  public:
1244 
1246  virtual ~Subtract (void);
1247 
1249  //virtual int precedence (void);
1250  virtual int add_precedence (int accumulated_precedence);
1251 
1253  virtual ComponentNode * build (void);
1254  };
1255 
1261  class Add : public TernaryOperator
1262  {
1263  public:
1266 
1268  virtual ~Add (void);
1269 
1271  virtual int add_precedence (int accumulated_precedence);
1272 
1274  virtual ComponentNode * build (void);
1275  };
1276 
1282  class And : public TernaryOperator
1283  {
1284  public:
1287 
1289  virtual ~And (void);
1290 
1292  //virtual int precedence (void);
1293  virtual int add_precedence (int accumulated_precedence);
1294 
1296  virtual ComponentNode * build (void);
1297  };
1298 
1304  class Or : public TernaryOperator
1305  {
1306  public:
1308  Or (logger::Logger & logger);
1309 
1311  virtual ~Or (void);
1312 
1314  //virtual int precedence (void);
1315  virtual int add_precedence (int accumulated_precedence);
1316 
1318  virtual ComponentNode * build (void);
1319  };
1320 
1326  class Both : public TernaryOperator
1327  {
1328  public:
1331 
1333  virtual ~Both (void);
1334 
1336  //virtual int precedence (void);
1337  virtual int add_precedence (int accumulated_precedence);
1338 
1340  virtual ComponentNode * build (void);
1341  };
1342 
1349  {
1350  public:
1353 
1355  virtual ~ReturnRight (void);
1356 
1358  virtual int add_precedence (int accumulated_precedence);
1359 
1361  virtual ComponentNode * build (void);
1362  };
1363 
1369  class Sequence : public TernaryOperator
1370  {
1371  public:
1374 
1376  virtual ~Sequence (void);
1377 
1379  //virtual int precedence (void);
1380  virtual int add_precedence (int accumulated_precedence);
1381 
1383  virtual ComponentNode * build (void);
1384  };
1385 
1391  class Implies : public Operator
1392  {
1393  public:
1396 
1398  virtual ~Implies (void);
1399 
1401  //virtual int precedence (void);
1402  virtual int add_precedence (int accumulated_precedence);
1403 
1405  virtual ComponentNode * build (void);
1406  };
1407 
1413  class Assignment : public Operator
1414  {
1415  public:
1418 
1420  virtual ~Assignment (void);
1421 
1423  //virtual int precedence (void);
1424  virtual int add_precedence (int accumulated_precedence);
1425 
1427  virtual ComponentNode * build (void);
1428  };
1429 
1435  class Equality : public Operator
1436  {
1437  public:
1440 
1442  virtual ~Equality (void);
1443 
1445  //virtual int precedence (void);
1446  virtual int add_precedence (int accumulated_precedence);
1447 
1449  virtual ComponentNode * build (void);
1450  };
1451 
1457  class Inequality : public Operator
1458  {
1459  public:
1462 
1464  virtual ~Inequality (void);
1465 
1467  //virtual int precedence (void);
1468  virtual int add_precedence (int accumulated_precedence);
1469 
1471  virtual ComponentNode * build (void);
1472  };
1473 
1480  {
1481  public:
1484 
1486  virtual ~GreaterThanEqual (void);
1487 
1489  //virtual int precedence (void);
1490  virtual int add_precedence (int accumulated_precedence);
1491 
1493  virtual ComponentNode * build (void);
1494  };
1495 
1501  class GreaterThan : public Operator
1502  {
1503  public:
1506 
1508  virtual ~GreaterThan (void);
1509 
1511  //virtual int precedence (void);
1512  virtual int add_precedence (int accumulated_precedence);
1513 
1515  virtual ComponentNode * build (void);
1516  };
1517 
1523  class LessThanEqual : public Operator
1524  {
1525  public:
1528 
1530  virtual ~LessThanEqual (void);
1531 
1533  //virtual int precedence (void);
1534  virtual int add_precedence (int accumulated_precedence);
1535 
1537  virtual ComponentNode * build (void);
1538  };
1539 
1545  class LessThan : public Operator
1546  {
1547  public:
1550 
1552  virtual ~LessThan (void);
1553 
1555  //virtual int precedence (void);
1556  virtual int add_precedence (int accumulated_precedence);
1557 
1559  virtual ComponentNode * build (void);
1560  };
1561 
1567  class Function : public TernaryOperator
1568  {
1569  public:
1571  Function (const std::string & name,
1573 
1575  virtual ~Function (void);
1576 
1578  //virtual int precedence (void);
1579  virtual int add_precedence (int accumulated_precedence);
1580 
1582  virtual ComponentNode * build (void);
1583 
1586  };
1587 
1594  {
1595  public:
1597  ConstArray (
1599 
1601  virtual ~ConstArray (void);
1602 
1604  //virtual int precedence (void);
1605  virtual int add_precedence (int accumulated_precedence);
1606 
1608  virtual ComponentNode *build (void);
1609 
1611  };
1612 
1618  class ForLoop : public UnaryOperator
1619  {
1620  public:
1622  ForLoop (Symbol * precondition, Symbol * condition,
1623  Symbol * postcondition, Symbol * body,
1625 
1627  virtual ~ForLoop (void);
1628 
1630  //virtual int precedence (void);
1631  virtual int add_precedence (int accumulated_precedence);
1632 
1634  virtual ComponentNode *build (void);
1635 
1641  };
1642 
1649  {
1650  public:
1653 
1655  virtual ~SquareRootUnary (void);
1656 
1658  //virtual int precedence (void);
1659  virtual int add_precedence (int accumulated_precedence);
1660 
1662  virtual ComponentNode * build (void);
1663  };
1664 
1670  class Negate : public UnaryOperator
1671  {
1672  public:
1675 
1677  virtual ~Negate (void);
1678 
1680  //virtual int precedence (void);
1681  virtual int add_precedence (int accumulated_precedence);
1682 
1684  virtual ComponentNode * build (void);
1685  };
1686 
1693  {
1694  public:
1697 
1699  virtual ~Postdecrement (void);
1700 
1702  //virtual int precedence (void);
1703  virtual int add_precedence (int accumulated_precedence);
1704 
1706  virtual ComponentNode * build (void);
1707  };
1708 
1715  {
1716  public:
1719 
1721  virtual ~Postincrement (void);
1722 
1724  //virtual int precedence (void);
1725  virtual int add_precedence (int accumulated_precedence);
1726 
1728  virtual ComponentNode * build (void);
1729  };
1730 
1737  {
1738  public:
1741 
1743  virtual ~Predecrement (void);
1744 
1746  //virtual int precedence (void);
1747  virtual int add_precedence (int accumulated_precedence);
1748 
1750  virtual ComponentNode * build (void);
1751  };
1752 
1759  {
1760  public:
1763 
1765  virtual ~Preincrement (void);
1766 
1768  //virtual int precedence (void);
1769  virtual int add_precedence (int accumulated_precedence);
1770 
1772  virtual ComponentNode * build (void);
1773  };
1774 
1780  class Not : public UnaryOperator
1781  {
1782  public:
1785 
1787  virtual ~Not (void);
1788 
1790  //virtual int precedence (void);
1791  virtual int add_precedence (int accumulated_precedence);
1792 
1794  virtual ComponentNode * build (void);
1795  };
1796 
1802  class Multiply : public TernaryOperator
1803  {
1804  public:
1807 
1809  virtual ~Multiply (void);
1810 
1812  //virtual int precedence (void);
1813  virtual int add_precedence (int accumulated_precedence);
1814 
1816  virtual ComponentNode * build (void);
1817  };
1818 
1824  class Modulus : public Operator
1825  {
1826  public:
1829 
1831  virtual ~Modulus (void);
1832 
1834  //virtual int precedence (void);
1835  virtual int add_precedence (int accumulated_precedence);
1836 
1838  virtual ComponentNode * build (void);
1839  };
1840 
1846  class Divide : public Operator
1847  {
1848  public:
1851 
1853  virtual ~Divide (void);
1854 
1856  //virtual int precedence (void);
1857  virtual int add_precedence (int accumulated_precedence);
1858 
1860  virtual ComponentNode * build (void);
1861  };
1862 
1863  }
1864 }
1865 
1866 // constructor
1871  : logger_ (&logger), left_ (left), right_ (right), precedence_ (precedence)
1872 {
1873 }
1874 
1875 // destructor
1877 {
1878  delete left_;
1879  delete right_;
1880 }
1881 
1882 // constructor
1884  Symbol * left, Symbol * right, int precedence)
1885  : Symbol (logger, left, right, precedence)
1886 {
1887 }
1888 
1889 // destructor
1891 {
1892 }
1893 
1894 // constructor
1896  Symbol * left, Symbol * right, int precedence)
1897  : Operator (logger, left, right, precedence)
1898 {
1899 }
1900 
1901 // destructor
1903 {
1904 }
1905 
1906 // constructor
1910  : madara::expression::Symbol (logger, 0, right, precedence)
1911 {
1912 }
1913 
1914 // destructor
1916 {
1917 }
1918 
1919 // constructor
1922  : Symbol (logger, 0, 0, NUMBER_PRECEDENCE)
1923 {
1924  item_.set_value (input);
1925 }
1926 
1927 // constructor
1929  double input)
1930  : Symbol (logger, 0, 0, NUMBER_PRECEDENCE)
1931 {
1932  item_.set_value (input);
1933 }
1934 
1935 // constructor
1937  std::string input)
1938  : Symbol (logger, 0, 0, NUMBER_PRECEDENCE)
1939 {
1940  item_.set_value (input);
1941 }
1942 
1943 // destructor
1945 {
1946 }
1947 
1948 // returns the precedence level
1949 int
1951 {
1952  return this->precedence_ = NUMBER_PRECEDENCE + precedence;
1953 }
1954 
1955 // builds an equivalent ExpressionTree node
1958 {
1959  if (left_ || right_)
1960  {
1961  std::string message =
1962  "Number::build: KARL COMPILE ERROR: "
1963  "Number ";
1964  message += item_.to_string ();
1965  message += " has a left or right child. Likely missing a semi-colon\n";
1966 
1967  madara_logger_ptr_log (logger_, logger::LOG_ERROR, message.c_str ());
1968 
1969  throw KarlException (message);
1970  }
1971 
1972  return new LeafNode (*(this->logger_), item_);
1973 }
1974 
1975 // constructor
1977  : UnaryOperator (logger, 0, NEGATE_PRECEDENCE)
1978 {
1979 }
1980 
1981 // destructor
1983 {
1984 }
1985 
1986 // returns the precedence level
1987 int
1989 {
1990  return this->precedence_ = NEGATE_PRECEDENCE + precedence;
1991 }
1992 
1993 // builds an equivalent ExpressionTree node
1996 {
1997  // check for cascading nots
1998  Negate * next = dynamic_cast <Negate *> (right_);
1999  Symbol * right = right_;
2000  unsigned int i;
2001 
2002  if (left_)
2003  {
2005  "Negate::build: KARL COMPILE ERROR: "
2006  "Negate(-) has a left child. Likely missing a semi-colon\n");
2007 
2008  throw KarlException ("Negate::build: KARL COMPILE ERROR: "
2009  "Negate(-) has a left child. Likely missing a semi-colon\n");
2010  }
2011 
2012  if (right_)
2013  {
2014  for (i = 1; next;
2015  ++i, right = next->right_, next = dynamic_cast <Negate *> (next->right_)) {}
2016 
2017  if (i % 2 == 1)
2018  return new CompositeNegateNode (*(this->logger_), right->build ());
2019  else
2020  return new CompositeNegateNode (*(this->logger_),
2021  new CompositeNegateNode (*(this->logger_), right->build ()));
2022  }
2023  else
2024  {
2025  return new CompositeNegateNode (*(this->logger_), 0);
2026  }
2027 }
2028 
2029 // constructor
2031  const std::string & name,
2033  : TernaryOperator (context.get_logger (), 0, 0, VARIABLE_PRECEDENCE), name_ (name), context_ (context)
2034 {
2035 }
2036 
2037 // destructor
2039 {
2040 }
2041 
2042 // returns the precedence level
2043 int
2045 {
2046  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2047 }
2048 
2049 // builds an equivalent ExpressionTree node
2052 {
2053  return new CompositeFunctionNode (name_, context_, nodes_);
2054 }
2055 
2056 
2057 
2058 // constructor
2061 : TernaryOperator (context.get_logger (), 0, 0, VARIABLE_PRECEDENCE),
2062  context_ (context)
2063 {
2064 }
2065 
2066 // destructor
2068 {
2069 }
2070 
2071 // returns the precedence level
2072 int
2074 {
2075  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2076 }
2077 
2078 // builds an equivalent ExpressionTree node
2081 {
2082  if (left_ || right_)
2083  {
2085  "array[]::build: KARL COMPILE ERROR: "
2086  "array[] has a left or right child. Likely missing a semi-colon\n");
2087 
2088  throw KarlException (
2089  "array[]::build: KARL COMPILE ERROR: "
2090  "array[] has a left or right child. Likely missing a semi-colon\n");
2091  }
2092 
2093  return new CompositeConstArray (*(this->logger_), nodes_);
2094 }
2095 
2096 
2097 
2098 
2099 
2100 // constructor
2103 : TernaryOperator (context.get_logger (), 0, 0, VARIABLE_PRECEDENCE),
2104  context_ (context)
2105 {
2106 }
2107 
2108 // destructor
2110 {
2111 }
2112 
2113 
2114 // constructor
2117  : SystemCall (context)
2118 {
2119 }
2120 
2121 // destructor
2123 {
2124 }
2125 
2126 // returns the precedence level
2127 int
2129 {
2130  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2131 }
2132 
2133 // builds an equivalent ExpressionTree node
2136 {
2137  if (left_ || right_)
2138  {
2140  "#clear_var::build: KARL COMPILE ERROR: "
2141  "#clear_var has a left or right child. Likely missing a semi-colon\n");
2142 
2143  throw KarlException (
2144  "#clear_var::build: KARL COMPILE ERROR: "
2145  "#clear_var has a left or right child. Likely missing a semi-colon\n");
2146  }
2147 
2148  return new SystemCallClearVariable (context_, nodes_);
2149 }
2150 
2151 
2152 // constructor
2155  : SystemCall (context)
2156 {
2157 }
2158 
2159 // destructor
2161 {
2162 }
2163 
2164 // returns the precedence level
2165 int
2167 {
2168  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2169 }
2170 
2171 // builds an equivalent ExpressionTree node
2174 {
2175  if (left_ || right_)
2176  {
2178  "#delete_var::build: KARL COMPILE ERROR: "
2179  "#delete_var has a left or right child. Likely missing a semi-colon\n");
2180 
2181  throw KarlException (
2182  "#delete_var::build: KARL COMPILE ERROR: "
2183  "#delete_var has a left or right child. Likely missing a semi-colon\n");
2184  }
2185 
2187 }
2188 
2189 
2190 
2191 // constructor
2194  : SystemCall (context)
2195 {
2196 }
2197 
2198 // destructor
2200 {
2201 }
2202 
2203 // returns the precedence level
2204 int
2206 {
2207  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2208 }
2209 
2210 // builds an equivalent ExpressionTree node
2213 {
2214  if (left_ || right_)
2215  {
2217  "#evaluate::build: KARL COMPILE ERROR: "
2218  "#evaluate has a left or right child. Likely missing a semi-colon\n");
2219 
2220  throw KarlException (
2221  "#evaluate::build: KARL COMPILE ERROR: "
2222  "#evaluate has a left or right child. Likely missing a semi-colon\n");
2223  }
2224 
2225  return new SystemCallEval (context_, nodes_);
2226 }
2227 
2228 
2229 
2230 // constructor
2233  : SystemCall (context)
2234 {
2235 }
2236 
2237 // destructor
2239 {
2240 }
2241 
2242 // returns the precedence level
2243 int
2245 {
2246  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2247 }
2248 
2249 // builds an equivalent ExpressionTree node
2252 {
2253  if (left_ || right_)
2254  {
2256  "#expand_env::build: KARL COMPILE ERROR: "
2257  "#expand_env has a left or right child. Likely missing a semi-colon\n");
2258 
2259  throw KarlException (
2260  "#expand_env::build: KARL COMPILE ERROR: "
2261  "#expand_env has a left or right child. Likely missing a semi-colon\n");
2262  }
2263 
2264  return new SystemCallExpandEnv (context_, nodes_);
2265 }
2266 
2267 
2268 
2269 // constructor
2272  : SystemCall (context)
2273 {
2274 }
2275 
2276 // destructor
2278 {
2279 }
2280 
2281 // returns the precedence level
2282 int
2284 {
2285  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2286 }
2287 
2288 // builds an equivalent ExpressionTree node
2291 {
2292  if (left_ || right_)
2293  {
2295  "#expand::build: KARL COMPILE ERROR: "
2296  "#expand has a left or right child. Likely missing a semi-colon\n");
2297 
2298  throw KarlException (
2299  "#expand::build: KARL COMPILE ERROR: "
2300  "#expand has a left or right child. Likely missing a semi-colon\n");
2301  }
2302 
2304 }
2305 
2306 
2307 
2308 
2309 // constructor
2312  : SystemCall (context)
2313 {
2314 }
2315 
2316 // destructor
2318 {
2319 }
2320 
2321 // returns the precedence level
2322 int
2324 {
2325  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2326 }
2327 
2328 // builds an equivalent ExpressionTree node
2331 {
2332  if (left_ || right_)
2333  {
2335  "#fragment::build: KARL COMPILE ERROR: "
2336  "#fragment has a left or right child. Likely missing a semi-colon\n");
2337 
2338  throw KarlException (
2339  "#fragment::build: KARL COMPILE ERROR: "
2340  "#fragment has a left or right child. Likely missing a semi-colon\n");
2341  }
2342 
2343  return new SystemCallFragment (context_, nodes_);
2344 }
2345 
2346 
2347 
2348 // constructor
2351  : SystemCall (context)
2352 {
2353 }
2354 
2355 // destructor
2357 {
2358 }
2359 
2360 // returns the precedence level
2361 int
2363 {
2364  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2365 }
2366 
2367 // builds an equivalent ExpressionTree node
2370 {
2371  if (left_ || right_)
2372  {
2374  "#log_level::build: KARL COMPILE ERROR: "
2375  "#log_level has a left or right child. Likely missing a semi-colon\n");
2376 
2377  throw KarlException (
2378  "#log_level::build: KARL COMPILE ERROR: "
2379  "#log_level has a left or right child. Likely missing a semi-colon\n");
2380  }
2381 
2382  return new SystemCallLogLevel (context_, nodes_);
2383 }
2384 
2385 
2386 
2387 
2388 // constructor
2391  : SystemCall (context)
2392 {
2393 }
2394 
2395 // destructor
2397 {
2398 }
2399 
2400 // returns the precedence level
2401 int
2403 {
2404  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2405 }
2406 
2407 // builds an equivalent ExpressionTree node
2410 {
2411  if (left_ || right_)
2412  {
2414  "#get_clock::build: KARL COMPILE ERROR: "
2415  "#get_clock has a left or right child. Likely missing a semi-colon\n");
2416 
2417  throw KarlException (
2418  "#get_clock::build: KARL COMPILE ERROR: "
2419  "#get_clock has a left or right child. Likely missing a semi-colon\n");
2420  }
2421 
2422  return new SystemCallGetClock (context_, nodes_);
2423 }
2424 
2425 
2426 // constructor
2429  : SystemCall (context)
2430 {
2431 }
2432 
2433 // destructor
2435 {
2436 }
2437 
2438 // returns the precedence level
2439 int
2441 {
2442  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2443 }
2444 
2445 // builds an equivalent ExpressionTree node
2448 {
2449  if (left_ || right_)
2450  {
2452  "#get_time::build: KARL COMPILE ERROR: "
2453  "#get_time has a left or right child. Likely missing a semi-colon\n");
2454 
2455  throw KarlException (
2456  "#get_time::build: KARL COMPILE ERROR: "
2457  "#get_time has a left or right child. Likely missing a semi-colon\n");
2458  }
2459 
2460  return new SystemCallGetTime (context_, nodes_);
2461 }
2462 
2463 
2464 // constructor
2467  : SystemCall (context)
2468 {
2469 }
2470 
2471 // destructor
2473 {
2474 }
2475 
2476 // returns the precedence level
2477 int
2479 {
2480  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2481 }
2482 
2483 // builds an equivalent ExpressionTree node
2486 {
2487  if (left_ || right_)
2488  {
2490  "#get_time_s::build: KARL COMPILE ERROR: "
2491  "#get_time_s has a left or right child. Likely missing a semi-colon\n");
2492 
2493  throw KarlException (
2494  "#get_time_s::build: KARL COMPILE ERROR: "
2495  "#get_time_s has a left or right child. Likely missing a semi-colon\n");
2496  }
2497 
2499 }
2500 
2501 
2502 // constructor
2505  : SystemCall (context)
2506 {
2507 }
2508 
2509 // destructor
2511 {
2512 }
2513 
2514 // returns the precedence level
2515 int
2517 {
2518  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2519 }
2520 
2521 // builds an equivalent ExpressionTree node
2524 {
2525  if (left_ || right_)
2526  {
2528  "#set_clock::build: KARL COMPILE ERROR: "
2529  "#set_clock has a left or right child. Likely missing a semi-colon\n");
2530 
2531  throw KarlException (
2532  "#set_clock::build: KARL COMPILE ERROR: "
2533  "#set_clock has a left or right child. Likely missing a semi-colon\n");
2534  }
2535 
2536  return new SystemCallSetClock (context_, nodes_);
2537 }
2538 
2539 // constructor
2542  : SystemCall (context)
2543 {
2544 }
2545 
2546 // destructor
2548 {
2549 }
2550 
2551 // returns the precedence level
2552 int
2554 {
2555  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2556 }
2557 
2558 // builds an equivalent ExpressionTree node
2561 {
2562  if (left_ || right_)
2563  {
2565  "#set_fixed::build: KARL COMPILE ERROR: "
2566  "#set_fixed has a left or right child. Likely missing a semi-colon\n");
2567 
2568  throw KarlException (
2569  "#set_fixed::build: KARL COMPILE ERROR: "
2570  "#set_fixed has a left or right child. Likely missing a semi-colon\n");
2571  }
2572 
2573  return new SystemCallSetFixed (context_, nodes_);
2574 }
2575 
2576 
2577 // constructor
2580  : SystemCall (context)
2581 {
2582 }
2583 
2584 // destructor
2586 {
2587 }
2588 
2589 // returns the precedence level
2590 int
2592 {
2593  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2594 }
2595 
2596 // builds an equivalent ExpressionTree node
2599 {
2600  if (left_ || right_)
2601  {
2603  "#set_precision::build: KARL COMPILE ERROR: "
2604  "#set_precision has a left or right child. Likely missing a semi-colon\n");
2605 
2606  throw KarlException (
2607  "#set_precision::build: KARL COMPILE ERROR: "
2608  "#set_precision has a left or right child. Likely missing a semi-colon\n");
2609  }
2610 
2611  return new SystemCallSetPrecision (context_, nodes_);
2612 }
2613 
2614 
2615 // constructor
2618  : SystemCall (context)
2619 {
2620 }
2621 
2622 // destructor
2624 {
2625 }
2626 
2627 // returns the precedence level
2628 int
2630 {
2631  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2632 }
2633 
2634 // builds an equivalent ExpressionTree node
2637 {
2638  if (left_ || right_)
2639  {
2641  "#scientific::build: KARL COMPILE ERROR: "
2642  "#scientific has a left or right child. Likely missing a semi-colon\n");
2643 
2644  throw KarlException (
2645  "#scientific::build: KARL COMPILE ERROR: "
2646  "#scientific has a left or right child. Likely missing a semi-colon\n");
2647  }
2648 
2649  return new SystemCallSetScientific (context_, nodes_);
2650 }
2651 
2652 
2653 
2654 // constructor
2657  : SystemCall (context)
2658 {
2659 }
2660 
2661 // destructor
2663 {
2664 }
2665 
2666 // returns the precedence level
2667 int
2669 {
2670  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2671 }
2672 
2673 // builds an equivalent ExpressionTree node
2676 {
2677  if (left_ || right_)
2678  {
2680  "#print::build: KARL COMPILE ERROR: "
2681  "#print has a left or right child. Likely missing a semi-colon\n");
2682 
2683  throw KarlException (
2684  "#print::build: KARL COMPILE ERROR: "
2685  "#print has a left or right child. Likely missing a semi-colon\n");
2686  }
2687 
2688  return new SystemCallPrint (context_, nodes_);
2689 }
2690 
2691 // constructor
2694  : SystemCall (context)
2695 {
2696 }
2697 
2698 // destructor
2700 {
2701 }
2702 
2703 // returns the precedence level
2704 int
2706 {
2707  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2708 }
2709 
2710 // builds an equivalent ExpressionTree node
2713 {
2714  if (left_ || right_)
2715  {
2717  "#cos::build: KARL COMPILE ERROR: "
2718  "#cos has a left or right child. Likely missing a semi-colon\n");
2719 
2720  throw KarlException (
2721  "#cos::build: KARL COMPILE ERROR: "
2722  "#cos has a left or right child. Likely missing a semi-colon\n");
2723  }
2724 
2725  return new SystemCallCos (context_, nodes_);
2726 }
2727 
2728 
2729 // constructor
2732  : SystemCall (context)
2733 {
2734 }
2735 
2736 // destructor
2738 {
2739 }
2740 
2741 // returns the precedence level
2742 int
2744 {
2745  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2746 }
2747 
2748 // builds an equivalent ExpressionTree node
2751 {
2752  if (left_ || right_)
2753  {
2755  "#sin::build: KARL COMPILE ERROR: "
2756  "#sin has a left or right child. Likely missing a semi-colon\n");
2757 
2758  throw KarlException (
2759  "#sin::build: KARL COMPILE ERROR: "
2760  "#sin has a left or right child. Likely missing a semi-colon\n");
2761  }
2762 
2763  return new SystemCallSin (context_, nodes_);
2764 }
2765 
2766 // constructor
2769  : SystemCall (context)
2770 {
2771 }
2772 
2773 // destructor
2775 {
2776 }
2777 
2778 // returns the precedence level
2779 int
2781 {
2782  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2783 }
2784 
2785 // builds an equivalent ExpressionTree node
2788 {
2789  if (left_ || right_)
2790  {
2792  "#tan::build: KARL COMPILE ERROR: "
2793  "#tan has a left or right child. Likely missing a semi-colon\n");
2794 
2795  throw KarlException (
2796  "#tan::build: KARL COMPILE ERROR: "
2797  "#tan has a left or right child. Likely missing a semi-colon\n");
2798  }
2799 
2800  return new SystemCallTan (context_, nodes_);
2801 }
2802 
2803 // constructor
2806  : SystemCall (context)
2807 {
2808 }
2809 
2810 // destructor
2812 {
2813 }
2814 
2815 // returns the precedence level
2816 int
2818 {
2819  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2820 }
2821 
2822 // builds an equivalent ExpressionTree node
2825 {
2826  if (left_ || right_)
2827  {
2829  "#pow::build: KARL COMPILE ERROR: "
2830  "#pow has a left or right child. Likely missing a semi-colon\n");
2831 
2832  throw KarlException (
2833  "#pow::build: KARL COMPILE ERROR: "
2834  "#pow has a left or right child. Likely missing a semi-colon\n");
2835  }
2836 
2837  return new SystemCallPow (context_, nodes_);
2838 }
2839 
2840 // constructor
2843  : SystemCall (context)
2844 {
2845 }
2846 
2847 // destructor
2849 {
2850 }
2851 
2852 // returns the precedence level
2853 int
2855 {
2856  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2857 }
2858 
2859 // builds an equivalent ExpressionTree node
2862 {
2863  if (left_ || right_)
2864  {
2866  "#sqrt::build: KARL COMPILE ERROR: "
2867  "#sqrt has a left or right child. Likely missing a semi-colon\n");
2868 
2869  throw KarlException (
2870  "#sqrt::build: KARL COMPILE ERROR: "
2871  "#sqrt has a left or right child. Likely missing a semi-colon\n");
2872  }
2873 
2874  return new SystemCallSqrt (context_, nodes_);
2875 }
2876 
2877 
2878 
2879 // constructor
2882  : SystemCall (context)
2883 {
2884 }
2885 
2886 // destructor
2888 {
2889 }
2890 
2891 // returns the precedence level
2892 int
2894 {
2895  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2896 }
2897 
2898 // builds an equivalent ExpressionTree node
2901 {
2902  if (left_ || right_)
2903  {
2905  "#print_system_calls::build: KARL COMPILE ERROR: "
2906  "#print_system_calls has a left or right child. Likely missing a semi-colon\n");
2907 
2908  throw KarlException (
2909  "#print_system_calls::build: KARL COMPILE ERROR: "
2910  "#print_system_calls has a left or right child. Likely missing a semi-colon\n");
2911  }
2912 
2914 }
2915 
2916 
2917 // constructor
2920  : SystemCall (context)
2921 {
2922 }
2923 
2924 // destructor
2926 {
2927 }
2928 
2929 // returns the precedence level
2930 int
2932 {
2933  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2934 }
2935 
2936 // builds an equivalent ExpressionTree node
2939 {
2940  if (left_ || right_)
2941  {
2943  "#rand_double::build: KARL COMPILE ERROR: "
2944  "#rand_double has a left or right child. Likely missing a semi-colon\n");
2945 
2946  throw KarlException (
2947  "#rand_double::build: KARL COMPILE ERROR: "
2948  "#rand_double has a left or right child. Likely missing a semi-colon\n");
2949  }
2950 
2951  return new SystemCallRandDouble (context_, nodes_);
2952 }
2953 
2954 
2955 // constructor
2958  : SystemCall (context)
2959 {
2960 }
2961 
2962 // destructor
2964 {
2965 }
2966 
2967 // returns the precedence level
2968 int
2970 {
2971  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2972 }
2973 
2974 // builds an equivalent ExpressionTree node
2977 {
2978  if (left_ || right_)
2979  {
2981  "#rand_int::build: KARL COMPILE ERROR: "
2982  "#rand_int has a left or right child. Likely missing a semi-colon\n");
2983 
2984  throw KarlException (
2985  "#rand_int::build: KARL COMPILE ERROR: "
2986  "#rand_int has a left or right child. Likely missing a semi-colon\n");
2987  }
2988 
2989  return new SystemCallRandInt (context_, nodes_);
2990 }
2991 
2992 
2993 // constructor
2996  : SystemCall (context)
2997 {
2998 }
2999 
3000 // destructor
3002 {
3003 }
3004 
3005 // returns the precedence level
3006 int
3008 {
3009  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
3010 }
3011 
3012 // builds an equivalent ExpressionTree node
3015 {
3016  if (left_ || right_)
3017  {
3019  "#read_file::build: KARL COMPILE ERROR: "
3020  "#read_file has a left or right child. Likely missing a semi-colon\n");
3021 
3022  throw KarlException (
3023  "#read_file::build: KARL COMPILE ERROR: "
3024  "#read_file has a left or right child. Likely missing a semi-colon\n");
3025  }
3026 
3027  return new SystemCallReadFile (context_, nodes_);
3028 }
3029 
3030 
3031 // constructor
3034  : SystemCall (context)
3035 {
3036 }
3037 
3038 // destructor
3040 {
3041 }
3042 
3043 // returns the precedence level
3044 int
3046 {
3047  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
3048 }
3049 
3050 // builds an equivalent ExpressionTree node
3053 {
3054  if (left_ || right_)
3055  {
3057  "#write_file::build: KARL COMPILE ERROR: "
3058  "#write_file has a left or right child. Likely missing a semi-colon\n");
3059 
3060  throw KarlException (
3061  "#write_file::build: KARL COMPILE ERROR: "
3062  "#write_file has a left or right child. Likely missing a semi-colon\n");
3063  }
3064 
3065  return new SystemCallWriteFile (context_, nodes_);
3066 }
3067 
3068 
3069 
3070 // constructor
3073  : SystemCall (context)
3074 {
3075 }
3076 
3077 // destructor
3079 {
3080 }
3081 
3082 // returns the precedence level
3083 int
3085 {
3086  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
3087 }
3088 
3089 // builds an equivalent ExpressionTree node
3092 {
3093  if (left_ || right_)
3094  {
3096  "#size::build: KARL COMPILE ERROR: "
3097  "#size has a left or right child. Likely missing a semi-colon\n");
3098 
3099  throw KarlException (
3100  "#size::build: KARL COMPILE ERROR: "
3101  "#size has a left or right child. Likely missing a semi-colon\n");
3102  }
3103 
3104  return new SystemCallSize (context_, nodes_);
3105 }
3106 
3107 
3108 // constructor
3111  : SystemCall (context)
3112 {
3113 }
3114 
3115 // destructor
3117 {
3118 }
3119 
3120 // returns the precedence level
3121 int
3123 {
3124  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
3125 }
3126 
3127 // builds an equivalent ExpressionTree node
3130 {
3131  if (left_ || right_)
3132  {
3134  "#sleep::build: KARL COMPILE ERROR: "
3135  "#sleep has a left or right child. Likely missing a semi-colon\n");
3136 
3137  throw KarlException (
3138  "#sleep::build: KARL COMPILE ERROR: "
3139  "#sleep has a left or right child. Likely missing a semi-colon\n");
3140  }
3141 
3142  return new SystemCallSleep (context_, nodes_);
3143 }
3144 
3145 
3146 // constructor
3149  : SystemCall (context)
3150 {
3151 }
3152 
3153 // destructor
3155 {
3156 }
3157 
3158 // returns the precedence level
3159 int
3161 {
3162  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
3163 }
3164 
3165 // builds an equivalent ExpressionTree node
3168 {
3169  if (left_ || right_)
3170  {
3172  "#to_buffer::build: KARL COMPILE ERROR: "
3173  "#to_buffer has a left or right child. Likely missing a semi-colon\n");
3174 
3175  throw KarlException (
3176  "#to_buffer::build: KARL COMPILE ERROR: "
3177  "#to_buffer has a left or right child. Likely missing a semi-colon\n");
3178  }
3179 
3180  return new SystemCallToBuffer (context_, nodes_);
3181 }
3182 
3183 
3184 // constructor
3187  : SystemCall (context)
3188 {
3189 }
3190 
3191 // destructor
3193 {
3194 }
3195 
3196 // returns the precedence level
3197 int
3199 {
3200  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
3201 }
3202 
3203 // builds an equivalent ExpressionTree node
3206 {
3207  if (left_ || right_)
3208  {
3210  "#to_double::build: KARL COMPILE ERROR: "
3211  "#to_double has a left or right child. Likely missing a semi-colon\n");
3212 
3213  throw KarlException (
3214  "#to_double::build: KARL COMPILE ERROR: "
3215  "#to_double has a left or right child. Likely missing a semi-colon\n");
3216  }
3217 
3218  return new SystemCallToDouble (context_, nodes_);
3219 }
3220 
3221 
3222 // constructor
3225  : SystemCall (context)
3226 {
3227 }
3228 
3229 // destructor
3231 {
3232 }
3233 
3234 // returns the precedence level
3235 int
3237 {
3238  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
3239 }
3240 
3241 // builds an equivalent ExpressionTree node
3244 {
3245  if (left_ || right_)
3246  {
3248  "#to_doubles::build: KARL COMPILE ERROR: "
3249  "#to_doubles has a left or right child. Likely missing a semi-colon\n");
3250 
3251  throw KarlException (
3252  "#to_doubles::build: KARL COMPILE ERROR: "
3253  "#to_doubles has a left or right child. Likely missing a semi-colon\n");
3254  }
3255 
3256  return new SystemCallToDoubles (context_, nodes_);
3257 }
3258 
3259 
3260 // constructor
3263  : SystemCall (context)
3264 {
3265 }
3266 
3267 // destructor
3269 {
3270 }
3271 
3272 // returns the precedence level
3273 int
3275 {
3276  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
3277 }
3278 
3279 // builds an equivalent ExpressionTree node
3282 {
3283  if (left_ || right_)
3284  {
3286  "#to_host_dirs::build: KARL COMPILE ERROR: "
3287  "#to_host_dirs has a left or right child. Likely missing a semi-colon\n");
3288 
3289  throw KarlException (
3290  "#to_host_dirs::build: KARL COMPILE ERROR: "
3291  "#to_host_dirs has a left or right child. Likely missing a semi-colon\n");
3292  }
3293 
3294  return new SystemCallToHostDirs (context_, nodes_);
3295 }
3296 
3297 
3298 // constructor
3301  : SystemCall (context)
3302 {
3303 }
3304 
3305 // destructor
3307 {
3308 }
3309 
3310 // returns the precedence level
3311 int
3313 {
3314  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
3315 }
3316 
3317 // builds an equivalent ExpressionTree node
3320 {
3321  if (left_ || right_)
3322  {
3324  "#to_integer::build: KARL COMPILE ERROR: "
3325  "#to_integer has a left or right child. Likely missing a semi-colon\n");
3326 
3327  throw KarlException (
3328  "#to_integer::build: KARL COMPILE ERROR: "
3329  "#to_integer has a left or right child. Likely missing a semi-colon\n");
3330  }
3331 
3332  return new SystemCallToInteger (context_, nodes_);
3333 }
3334 
3335 
3336 // constructor
3339  : SystemCall (context)
3340 {
3341 }
3342 
3343 // destructor
3345 {
3346 }
3347 
3348 // returns the precedence level
3349 int
3351 {
3352  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
3353 }
3354 
3355 // builds an equivalent ExpressionTree node
3358 {
3359  if (left_ || right_)
3360  {
3362  "#to_integers::build: KARL COMPILE ERROR: "
3363  "#to_integers has a left or right child. Likely missing a semi-colon\n");
3364 
3365  throw KarlException (
3366  "#to_integers::build: KARL COMPILE ERROR: "
3367  "#to_integers has a left or right child. Likely missing a semi-colon\n");
3368  }
3369 
3370  return new SystemCallToIntegers (context_, nodes_);
3371 }
3372 
3373 
3374 // constructor
3377  : SystemCall (context)
3378 {
3379 }
3380 
3381 // destructor
3383 {
3384 }
3385 
3386 // returns the precedence level
3387 int
3389 {
3390  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
3391 }
3392 
3393 // builds an equivalent ExpressionTree node
3396 {
3397  if (left_ || right_)
3398  {
3400  "#to_string::build: KARL COMPILE ERROR: "
3401  "#to_string has a left or right child. Likely missing a semi-colon\n");
3402 
3403  throw KarlException (
3404  "#to_string::build: KARL COMPILE ERROR: "
3405  "#to_string has a left or right child. Likely missing a semi-colon\n");
3406  }
3407 
3408  return new SystemCallToString (context_, nodes_);
3409 }
3410 
3411 
3412 // constructor
3415  : SystemCall (context)
3416 {
3417 }
3418 
3419 // destructor
3421 {
3422 }
3423 
3424 // returns the precedence level
3425 int
3427 {
3428  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
3429 }
3430 
3431 // builds an equivalent ExpressionTree node
3434 {
3435  if (left_ || right_)
3436  {
3438  "#type::build: KARL COMPILE ERROR: "
3439  "#type has a left or right child. Likely missing a semi-colon\n");
3440 
3441  throw KarlException (
3442  "#type::build: KARL COMPILE ERROR: "
3443  "#type has a left or right child. Likely missing a semi-colon\n");
3444  }
3445 
3446  return new SystemCallType (context_, nodes_);
3447 }
3448 
3449 
3450 // constructor
3453  : SystemCall (context)
3454 {
3455 }
3456 
3457 // destructor
3459 {
3460 }
3461 
3462 // returns the precedence level
3463 int
3465 {
3466  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
3467 }
3468 
3469 // builds an equivalent ExpressionTree node
3472 {
3473  if (left_ || right_)
3474  {
3476  "#is_inf::build: KARL COMPILE ERROR: "
3477  "#is_inf has a left or right child. Likely missing a semi-colon\n");
3478 
3479  throw KarlException (
3480  "#is_inf::build: KARL COMPILE ERROR: "
3481  "#is_inf has a left or right child. Likely missing a semi-colon\n");
3482  }
3483 
3484  return new SystemCallIsinf (context_, nodes_);
3485 }
3486 
3487 
3488 
3489 // constructor
3491  Symbol * condition, Symbol * postcondition,
3492  Symbol * body,
3494 : UnaryOperator (context.get_logger (), 0, VARIABLE_PRECEDENCE),
3495  precondition_ (precondition), condition_ (condition),
3496  postcondition_ (postcondition), body_ (body), context_ (context)
3497 {
3498 }
3499 
3500 // destructor
3502 {
3503  delete precondition_;
3504  delete postcondition_;
3505  delete condition_;
3506  delete body_;
3507 }
3508 
3509 // returns the precedence level
3510 int
3512 {
3513  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
3514 }
3515 
3516 // builds an equivalent ExpressionTree node
3519 {
3520  if (body_)
3521  return new CompositeForLoop (
3524  else
3525  {
3526  ComponentNode * left (0), * right (0);
3527 
3528  if (left_)
3529  left = precondition_->left_->build ();
3530 
3531  if (right_)
3532  right = condition_->right_->build ();
3533 
3534  return new CompositeAssignmentNode (
3535  context_.get_logger (), left, right);
3536  }
3537 }
3538 
3539 // constructor
3542 : UnaryOperator (logger, 0, NEGATE_PRECEDENCE)
3543 {
3544 }
3545 
3546 // destructor
3548 {
3549 }
3550 
3551 // returns the precedence level
3552 int
3554 {
3555  return this->precedence_ = NEGATE_PRECEDENCE + precedence;
3556 }
3557 
3558 // builds an equivalent ExpressionTree node
3561 {
3562  ComponentNode * right (0);
3563 
3564  if (left_)
3565  {
3567  "var--::build: KARL COMPILE ERROR: "
3568  "var-- has a left child. Likely missing a semi-colon\n");
3569 
3570  throw KarlException (
3571  "#var--::build: KARL COMPILE ERROR: "
3572  "#var-- has a left child. Likely missing a semi-colon\n");
3573  }
3574 
3575  if (right_)
3576  right = right_->build ();
3577 
3578  return new CompositePostdecrementNode (
3579  *(this->logger_), right);
3580 }
3581 
3582 // constructor
3584 : UnaryOperator (logger, 0, NEGATE_PRECEDENCE)
3585 {
3586 }
3587 
3588 // destructor
3590 {
3591 }
3592 
3593 // returns the precedence level
3594 int
3596 {
3597  return this->precedence_ = NEGATE_PRECEDENCE + precedence;
3598 }
3599 
3600 // builds an equivalent ExpressionTree node
3603 {
3604  ComponentNode * right (0);
3605 
3606  if (left_)
3607  {
3609  "var++::build: KARL COMPILE ERROR: "
3610  "var++ has a left child. Likely missing a semi-colon\n");
3611 
3612  throw KarlException (
3613  "#var++::build: KARL COMPILE ERROR: "
3614  "#var++ has a left child. Likely missing a semi-colon\n");
3615  }
3616 
3617  if (right_)
3618  right = right_->build ();
3619 
3620  return new CompositePostincrementNode (
3621  *(this->logger_), right);
3622 }
3623 
3624 // constructor
3626 : UnaryOperator (logger, 0, NEGATE_PRECEDENCE)
3627 {
3628 }
3629 
3630 // destructor
3632 {
3633 }
3634 
3635 // returns the precedence level
3636 int
3638 {
3639  return this->precedence_ = NEGATE_PRECEDENCE + precedence;
3640 }
3641 
3642 // builds an equivalent ExpressionTree node
3645 {
3646  ComponentNode * right (0);
3647 
3648  if (left_)
3649  {
3651  "--var::build: KARL COMPILE ERROR: "
3652  "--var has a left child. Likely missing a semi-colon\n");
3653 
3654  throw KarlException (
3655  "--var::build: KARL COMPILE ERROR: "
3656  "--var has a left child. Likely missing a semi-colon\n");
3657  }
3658 
3659  if (right_)
3660  right = right_->build ();
3661 
3662  return new CompositePredecrementNode (*(this->logger_), right);
3663 }
3664 
3665 // constructor
3667  : UnaryOperator (logger, 0, NEGATE_PRECEDENCE)
3668 {
3669 }
3670 
3671 // destructor
3673 {
3674 }
3675 
3676 // returns the precedence level
3677 int
3679 {
3680  return this->precedence_ = NEGATE_PRECEDENCE + precedence;
3681 }
3682 
3683 // builds an equivalent ExpressionTree node
3686 {
3687  ComponentNode * right (0);
3688 
3689  if (left_)
3690  {
3692  "++var::build: KARL COMPILE ERROR: "
3693  "++var has a left child. Likely missing a semi-colon\n");
3694 
3695  throw KarlException (
3696  "++var::build: KARL COMPILE ERROR: "
3697  "++var has a left child. Likely missing a semi-colon\n");
3698  }
3699 
3700  if (right_)
3701  right = right_->build ();
3702 
3703  return new CompositePreincrementNode (*(this->logger_), right);
3704 }
3705 
3706 // constructor
3708  : UnaryOperator (logger, 0, NEGATE_PRECEDENCE)
3709 {
3710 }
3711 
3712 // destructor
3714 {
3715 }
3716 
3717 // returns the precedence level
3718 int
3720 {
3721  return this->precedence_ = NEGATE_PRECEDENCE + precedence;
3722 }
3723 
3724 // builds an equivalent ExpressionTree node
3727 {
3728  // check for cascading nots
3729  Not * next = dynamic_cast <Not *> (right_);
3730  Symbol * right = right_;
3731  unsigned int i;
3732 
3733  if (left_)
3734  {
3736  "Not(!)::build: KARL COMPILE ERROR: "
3737  "Logical Not(!) has a left child. Likely missing a semi-colon\n");
3738 
3739  throw KarlException (
3740  "Not(!)::build: KARL COMPILE ERROR: "
3741  "Logical Not(!) has a left child. Likely missing a semi-colon\n");
3742  }
3743 
3744  if (right_)
3745  {
3746  for (i = 1; next;
3747  ++i, right = next->right_, next = dynamic_cast <Not *> (next->right_)) {}
3748 
3749  if (i % 2 == 1)
3750  return new CompositeNotNode (*(this->logger_), right->build ());
3751  else
3752  return new CompositeNotNode (*(this->logger_),
3753  new CompositeNotNode (*(this->logger_), right->build ()));
3754  }
3755  else
3756  {
3757  return new CompositeNotNode (*(this->logger_), 0);
3758  }
3759 }
3760 
3761 // constructor
3763  : UnaryOperator (logger, 0, NEGATE_PRECEDENCE)
3764 {
3765 }
3766 
3767 // destructor
3769 {
3770 }
3771 
3772 // returns the precedence level
3773 int
3775 {
3776  return this->precedence_ = NEGATE_PRECEDENCE + precedence;
3777 }
3778 
3779 // builds an equivalent ExpressionTree node
3782 {
3783  ComponentNode * right (0);
3784 
3785  if (left_)
3786  {
3788  "sqrt::build: KARL COMPILE ERROR: "
3789  "sqrt has a left child. Likely missing a semi-colon\n");
3790 
3791  throw KarlException (
3792  "sqrt::build: KARL COMPILE ERROR: "
3793  "sqrt has a left child. Likely missing a semi-colon\n");
3794  }
3795 
3796  if (right_)
3797  right = right_->build ();
3798 
3799  return new CompositeSquareRootNode (*(this->logger_), right);
3800 }
3801 
3802 // constructor
3805  : Symbol (context.get_logger (), 0, 0, VARIABLE_PRECEDENCE),
3806  key_ (key), context_ (context)
3807 {
3808 }
3809 
3810 // destructor
3812 {
3813 }
3814 
3815 // returns the precedence level
3816 int
3818 {
3819  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
3820 }
3821 
3822 // builds an equivalent ExpressionTree node
3825 {
3826  if (left_ || right_)
3827  {
3828  std::string message =
3829  "Variable::build: KARL COMPILE ERROR: "
3830  "Variable (";
3831  message += key_;
3832  message += ") has a left or right child. Likely missing a semi-colon\n";
3833 
3835  message.c_str ());
3836 
3837  throw KarlException (message);
3838  }
3839 
3840  // is reserved?
3841  if (key_ == "true")
3842  {
3843  return new LeafNode (context_.get_logger (), (Integer)1);
3844  }
3845  else if (key_ == "false")
3846  {
3847  return new LeafNode (context_.get_logger (), (Integer)0);
3848  }
3849  else if (key_ == "nan")
3850  {
3851  return new LeafNode (context_.get_logger (), NAN);
3852  }
3853  else if (key_ == "inf")
3854  {
3855  return new LeafNode (context_.get_logger (), INFINITY);
3856  }
3857  else
3858  {
3859  return new VariableNode (key_, context_);
3860  }
3861 }
3862 
3863 
3864 // constructor
3866  Symbol * index,
3868  : Symbol (context.get_logger (), 0, 0, VARIABLE_PRECEDENCE),
3869  key_ (key), context_ (context), index_ (index)
3870 {
3871 }
3872 
3873 // destructor
3875 {
3876 }
3877 
3878 // returns the precedence level
3879 int
3881 {
3882  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
3883 }
3884 
3885 // builds an equivalent ExpressionTree node
3888 {
3889  if (left_ || right_)
3890  {
3891  std::string message =
3892  "ArrayRef::build: KARL COMPILE ERROR: ";
3893  message += key_;
3894  message += "[] has a left or right child. Likely missing a semi-colon\n";
3895 
3897  message.c_str ());
3898 
3899  throw KarlException (message);
3900  }
3901 
3902  return new CompositeArrayReference (key_, index_->build (), context_);
3903 }
3904 
3905 
3906 // constructor
3908  Symbol * lhs,
3911  : Operator (context.get_logger (), 0, rhs, ASSIGNMENT_PRECEDENCE), left_ (lhs), value_ (value),
3912  context_ (context)
3913 {
3914 }
3915 
3916 // destructor
3918 {
3919 }
3920 
3921 // returns the precedence level
3922 int
3924 {
3925  return this->precedence_ = ASSIGNMENT_PRECEDENCE + precedence;
3926 }
3927 
3928 // builds an equivalent ExpressionTree node
3931 {
3932  if (this->right_)
3933  return new VariableDecrementNode (left_->build (), value_, this->right_->build (), context_);
3934  else
3935  return new VariableDecrementNode (left_->build (), value_, 0, context_);
3936 }
3937 
3938 
3939 // constructor
3941  knowledge::KnowledgeRecord value, Symbol * rhs,
3943  : Operator (context.get_logger (), 0, rhs, ASSIGNMENT_PRECEDENCE), left_ (lhs), value_ (value),
3944  context_ (context)
3945 {
3946 }
3947 
3948 // destructor
3950 {
3951 }
3952 
3953 // returns the precedence level
3954 int
3956 {
3957  return this->precedence_ = ASSIGNMENT_PRECEDENCE + precedence;
3958 }
3959 
3960 // builds an equivalent ExpressionTree node
3963 {
3964  if (this->right_)
3965  return new VariableDivideNode (left_->build (), value_, this->right_->build (), context_);
3966  else
3967  return new VariableDivideNode (left_->build (), value_, 0, context_);
3968 }
3969 
3970 // constructor
3974  : Operator (context.get_logger (), 0, rhs, ASSIGNMENT_PRECEDENCE),
3975  left_ (lhs), value_ (value),
3976  context_ (context)
3977 {
3978 }
3979 
3980 // destructor
3982 {
3983 }
3984 
3985 // returns the precedence level
3986 int
3988 {
3989  return this->precedence_ = ASSIGNMENT_PRECEDENCE + precedence;
3990 }
3991 
3992 // builds an equivalent ExpressionTree node
3995 {
3996  if (this->right_)
3997  return new VariableIncrementNode (left_->build (),
3998  value_, this->right_->build (), context_);
3999  else
4000  return new VariableIncrementNode (left_->build (), value_, 0, context_);
4001 }
4002 
4003 // constructor
4007  : Operator (context.get_logger (), 0, rhs, ASSIGNMENT_PRECEDENCE),
4008  left_ (lhs), value_ (value),
4009  context_ (context)
4010 {
4011 }
4012 
4013 // destructor
4015 {
4016 }
4017 
4018 // returns the precedence level
4019 int
4021 {
4022  return this->precedence_ = ASSIGNMENT_PRECEDENCE + precedence;
4023 }
4024 
4025 // builds an equivalent ExpressionTree node
4028 {
4029  if (this->right_)
4030  return new VariableMultiplyNode (left_->build (), value_, this->right_->build (), context_);
4031  else
4032  return new VariableMultiplyNode (left_->build (), value_, 0, context_);
4033 }
4034 
4035 
4036 // constructor
4038  madara::knowledge::KnowledgeRecord value, Symbol * rhs, int compare_type,
4040  : Symbol (context.get_logger (), 0, 0, VARIABLE_PRECEDENCE),
4041  left_ (lhs), value_ (value), rhs_ (rhs),
4042  compare_type_ (compare_type), context_ (context)
4043 {
4044 }
4045 
4046 // destructor
4048 {
4049 }
4050 
4051 // returns the precedence level
4052 int
4054 {
4055  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
4056 }
4057 
4058 // builds an equivalent ExpressionTree node
4061 {
4062  if (rhs_)
4064  rhs_->build (), context_);
4065  else
4067  0, context_);
4068 }
4069 
4070 
4071 
4072 // constructor
4075  : Symbol (context.get_logger (), 0, 0, VARIABLE_PRECEDENCE),
4076  context_ (context)
4077 {
4078 }
4079 
4080 // destructor
4082 {
4083 }
4084 
4085 // returns the precedence level
4086 int
4088 {
4089  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
4090 }
4091 
4092 // builds an equivalent ExpressionTree node
4095 {
4096  return new ListNode (context_);
4097 }
4098 
4099 // constructor
4101  : TernaryOperator (logger, 0, 0, ADD_PRECEDENCE)
4102 {
4103 }
4104 
4105 // destructor
4107 {
4108 }
4109 
4110 // returns the precedence level
4111 int
4113 {
4114  return this->precedence_ = ADD_PRECEDENCE + precedence;
4115 }
4116 
4117 // builds an equivalent ExpressionTree node
4120 {
4121  if (left_ && right_)
4122  {
4123  // check for cascading max
4124  Add * next = dynamic_cast <Add *> (left_);
4125  Symbol * left = left_;
4126 
4127  // push the right onto the deque
4128  nodes_.push_back (right_->build ());
4129  delete right_;
4130  right_ = 0;
4131 
4132  for (; next; next = dynamic_cast <Add *> (left))
4133  {
4134  // we have a chained max node. Move the left into our nodes list
4135  if (next->right_)
4136  {
4137  nodes_.push_front (next->right_->build ());
4138  delete next->right_;
4139  next->right_ = 0;
4140  }
4141 
4142  // set right to next->right_ and then clear next->right_ before deletion
4143  left = next->left_;
4144  next->left_ = 0;
4145  delete next;
4146  }
4147 
4148  // push the rightmost build from the compressed node and delete it.
4149  // then reset our right_, since we've already taken care of deletion
4150  if (left)
4151  {
4152  nodes_.push_front (left->build ());
4153  delete left;
4154  }
4155  left_ = 0;
4156 
4157  return new CompositeAddNode (*(this->logger_), nodes_);
4158  }
4159  else if (left_)
4160  // all we have is a valid left child, so there is no reason to build
4161  // an Add operator
4162  return left_->build ();
4163  else if (right_)
4164  // all we have is a valid right child, so there is no reason to build
4165  // a Add operator
4166  return right_->build ();
4167  else
4168  {
4169  // we've got nothing. This node should eventually be pruned out of the
4170  // picture if at all possible.
4171  return new CompositeAddNode (*(this->logger_), nodes_);
4172  }
4173 }
4174 
4175 
4176 // constructor
4178  : TernaryOperator (logger, 0, 0, LOGICAL_PRECEDENCE)
4179 {
4180 }
4181 
4182 // destructor
4184 {
4185 }
4186 
4187 // returns the precedence level
4188 int
4190 {
4191  return this->precedence_ = LOGICAL_PRECEDENCE + precedence;
4192 }
4193 
4194 // builds an equivalent ExpressionTree node
4197 {
4198  if (left_ && right_)
4199  {
4200  // check for cascading max
4201  And * next = dynamic_cast <And *> (left_);
4202  Symbol * left = left_;
4203 
4204  // push the right onto the deque
4205  nodes_.push_back (right_->build ());
4206  delete right_;
4207  right_ = 0;
4208 
4209  for (; next; next = dynamic_cast <And *> (left))
4210  {
4211  // we have a chained max node. Move the left into our nodes list
4212  if (next->right_)
4213  {
4214  nodes_.push_front (next->right_->build ());
4215  delete next->right_;
4216  next->right_ = 0;
4217  }
4218 
4219  // set right to next->right_ and then clear next->right_ before deletion
4220  left = next->left_;
4221  next->left_ = 0;
4222  delete next;
4223  }
4224 
4225  // push the rightmost build from the compressed node and delete it.
4226  // then reset our right_, since we've already taken care of deletion
4227  if (left)
4228  {
4229  nodes_.push_front (left->build ());
4230  delete left;
4231  }
4232  left_ = 0;
4233 
4234  return new CompositeAndNode (*(this->logger_), nodes_);
4235  }
4236  else if (left_)
4237  // all we have is a valid left child, so there is no reason to build
4238  // an And operator
4239  return left_->build ();
4240  else if (right_)
4241  // all we have is a valid right child, so there is no reason to build
4242  // an And operator
4243  return right_->build ();
4244  else
4245  {
4246  // we've got nothing. This node should eventually be pruned out of the
4247  // picture if at all possible.
4248  return new CompositeAndNode (*(this->logger_), nodes_);
4249  }
4250 }
4251 
4252 // constructor
4254  : TernaryOperator (logger, 0, 0, LOGICAL_PRECEDENCE)
4255 {
4256 }
4257 
4258 // destructor
4260 {
4261 }
4262 
4263 // returns the precedence level
4264 int
4266 {
4267  return this->precedence_ = LOGICAL_PRECEDENCE + precedence;
4268 }
4269 
4270 
4271 
4272 // builds an equivalent ExpressionTree node
4275 {
4276  if (left_ && right_)
4277  {
4278  // check for cascading max
4279  Or * next = dynamic_cast <Or *> (left_);
4280  Symbol * left = left_;
4281 
4282  // push the right onto the deque
4283  nodes_.push_back (right_->build ());
4284  delete right_;
4285  right_ = 0;
4286 
4287  for (; next; next = dynamic_cast <Or *> (left))
4288  {
4289  // we have a chained max node. Move the left into our nodes list
4290  if (next->right_)
4291  {
4292  nodes_.push_front (next->right_->build ());
4293  delete next->right_;
4294  next->right_ = 0;
4295  }
4296 
4297  // set right to next->right_ and then clear next->right_ before deletion
4298  left = next->left_;
4299  next->left_ = 0;
4300  delete next;
4301  }
4302 
4303  // push the rightmost build from the compressed node and delete it.
4304  // then reset our right_, since we've already taken care of deletion
4305  if (left)
4306  {
4307  nodes_.push_front (left->build ());
4308  delete left;
4309  }
4310  left_ = 0;
4311 
4312  return new CompositeOrNode (*(this->logger_), nodes_);
4313  }
4314  else if (left_)
4315  // all we have is a valid left child, so there is no reason to build
4316  // a Both operator
4317  return left_->build ();
4318  else if (right_)
4319  // all we have is a valid right child, so there is no reason to build
4320  // a Both operator
4321  return right_->build ();
4322  else
4323  {
4324  // we've got nothing. This node should eventually be pruned out of the
4325  // picture if at all possible.
4326  return new CompositeOrNode (*(this->logger_), nodes_);
4327  }
4328 }
4329 
4330 
4331 // constructor
4333  : TernaryOperator (logger, 0, 0, BOTH_PRECEDENCE)
4334 {
4335 }
4336 
4337 // destructor
4339 {
4340 }
4341 
4342 // returns the precedence level
4343 int
4345 {
4346  return this->precedence_ = BOTH_PRECEDENCE + precedence;
4347 }
4348 
4349 // builds an equivalent ExpressionTree node
4352 {
4353  // Since users can say something like ";;;;;;;;", it is very possible
4354  // that a both operation contains no valid children. So, we need
4355  // to check whether or not we have a valid child.
4356  if (left_ && right_)
4357  {
4358  // check for cascading max
4359  Both * next = dynamic_cast <Both *> (left_);
4360  Symbol * left = left_;
4361 
4362  // push the right onto the deque
4363  //nodes_.push_back (right_->build ());
4364  //delete right_;
4365  //right_ = 0;
4366 
4367  for (; next; next = dynamic_cast <Both *> (left))
4368  {
4369  // we have a chained max node. Move the left into our nodes list
4370  if (next->right_)
4371  {
4372  nodes_.push_front (next->right_->build ());
4373  delete next->right_;
4374  next->right_ = 0;
4375  }
4376 
4377  // set right to next->right_ and then clear next->right_ before deletion
4378  left = next->left_;
4379  next->left_ = 0;
4380  delete next;
4381  }
4382 
4383  // push the rightmost build from the compressed node and delete it.
4384  // then reset our right_, since we've already taken care of deletion
4385  if (left)
4386  {
4387  nodes_.push_front (left->build ());
4388  delete left;
4389  }
4390  left_ = 0;
4391 
4392 
4393  next = dynamic_cast <Both *> (right_);
4394  Symbol * right = right_;
4395 
4396  for (; next; next = dynamic_cast <Both *> (right))
4397  {
4398  // we have a chained max node. Move the left into our nodes list
4399  if (next->left_)
4400  {
4401  nodes_.push_back (next->left_->build ());
4402  delete next->left_;
4403  next->left_ = 0;
4404  }
4405 
4406  // set right to next->right_ and then clear next->right_ before deletion
4407  right = next->right_;
4408  next->right_ = 0;
4409  delete next;
4410  }
4411 
4412  // push the rightmost build from the compressed node and delete it.
4413  // then reset our right_, since we've already taken care of deletion
4414  if (right)
4415  {
4416  nodes_.push_back (right->build ());
4417  delete right;
4418  }
4419  right_ = 0;
4420 
4421  return new CompositeBothNode (*(this->logger_), nodes_);
4422  }
4423  else if (left_)
4424  // all we have is a valid left child, so there is no reason to build
4425  // a Both operator
4426  return left_->build ();
4427  else if (right_)
4428  // all we have is a valid right child, so there is no reason to build
4429  // a Both operator
4430  return right_->build ();
4431  else
4432  // we've got nothing. This node should eventually be pruned out of the
4433  // picture if at all possible.
4434  return new LeafNode (*(this->logger_),
4436 }
4437 
4438 
4439 // constructor
4441  : TernaryOperator (logger, 0, 0, BOTH_PRECEDENCE)
4442 {
4443 }
4444 
4445 // destructor
4447 {
4448 }
4449 
4450 // returns the precedence level
4451 int
4453 {
4454  return this->precedence_ = BOTH_PRECEDENCE + precedence;
4455 }
4456 
4457 // builds an equivalent ExpressionTree node
4460 {
4461  // Since users can say something like ";;;;;;;;", it is very possible
4462  // that a both operation contains no valid children. So, we need
4463  // to check whether or not we have a valid child.
4464  if (left_ && right_)
4465  {
4466  // check for cascading max
4467  ReturnRight * next = dynamic_cast <ReturnRight *> (left_);
4468  Symbol * left = left_;
4469 
4470  // push the right onto the deque
4471  //nodes_.push_back (right_->build ());
4472  //delete right_;
4473  //right_ = 0;
4474 
4475  for (; next; next = dynamic_cast <ReturnRight *> (left))
4476  {
4477  // we have a chained max node. Move the left into our nodes list
4478  if (next->right_)
4479  {
4480  nodes_.push_front (next->right_->build ());
4481  delete next->right_;
4482  next->right_ = 0;
4483  }
4484 
4485  // set right to next->right_ and then clear next->right_ before deletion
4486  left = next->left_;
4487  next->left_ = 0;
4488  delete next;
4489  }
4490 
4491  // push the rightmost build from the compressed node and delete it.
4492  // then reset our right_, since we've already taken care of deletion
4493  if (left)
4494  {
4495  nodes_.push_front (left->build ());
4496  delete left;
4497  }
4498  left_ = 0;
4499 
4500 
4501  next = dynamic_cast <ReturnRight *> (right_);
4502  Symbol * right = right_;
4503 
4504  for (; next; next = dynamic_cast <ReturnRight *> (right))
4505  {
4506  // we have a chained max node. Move the left into our nodes list
4507  if (next->left_)
4508  {
4509  nodes_.push_back (next->left_->build ());
4510  delete next->left_;
4511  next->left_ = 0;
4512  }
4513 
4514  // set right to next->right_ and then clear next->right_ before deletion
4515  right = next->right_;
4516  next->right_ = 0;
4517  delete next;
4518  }
4519 
4520  // push the rightmost build from the compressed node and delete it.
4521  // then reset our right_, since we've already taken care of deletion
4522  if (right)
4523  {
4524  nodes_.push_back (right->build ());
4525  delete right;
4526  }
4527  right_ = 0;
4528 
4529  return new CompositeReturnRightNode (*(this->logger_), nodes_);
4530  }
4531  else if (left_)
4532  // all we have is a valid left child, so there is no reason to build
4533  // a Both operator
4534  return left_->build ();
4535  else if (right_)
4536  // all we have is a valid right child, so there is no reason to build
4537  // a Both operator
4538  return right_->build ();
4539  else
4540  // we've got nothing. This node should eventually be pruned out of the
4541  // picture if at all possible.
4542  return new LeafNode (*(this->logger_),
4544 }
4545 
4546 // constructor
4548  : TernaryOperator (logger, 0, 0, BOTH_PRECEDENCE)
4549 {
4550 }
4551 
4552 // destructor
4554 {
4555 }
4556 
4557 // returns the precedence level
4558 int
4560 {
4561  return this->precedence_ = BOTH_PRECEDENCE + precedence;
4562 }
4563 
4564 // builds an equivalent ExpressionTree node
4567 {
4568  // Since users can say something like ";;;;;;;;", it is very possible
4569  // that a both operation contains no valid children. So, we need
4570  // to check whether or not we have a valid child.
4571  if (left_ && right_)
4572  {
4573  // check for cascading max
4574  Sequence * next = dynamic_cast <Sequence *> (left_);
4575  Symbol * left = left_;
4576 
4577  // push the right onto the deque
4578  //nodes_.push_back (right_->build ());
4579  //delete right_;
4580  //right_ = 0;
4581 
4582  for (; next; next = dynamic_cast <Sequence *> (left))
4583  {
4584  // we have a chained max node. Move the left into our nodes list
4585  if (next->right_)
4586  {
4587  nodes_.push_front (next->right_->build ());
4588  delete next->right_;
4589  next->right_ = 0;
4590  }
4591 
4592  // set right to next->right_ and then clear next->right_ before deletion
4593  left = next->left_;
4594  next->left_ = 0;
4595  delete next;
4596  }
4597 
4598  // push the rightmost build from the compressed node and delete it.
4599  // then reset our right_, since we've already taken care of deletion
4600  if (left)
4601  {
4602  nodes_.push_front (left->build ());
4603  delete left;
4604  }
4605  left_ = 0;
4606 
4607 
4608  next = dynamic_cast <Sequence *> (right_);
4609  Symbol * right = right_;
4610 
4611  for (; next; next = dynamic_cast <Sequence *> (right))
4612  {
4613  // we have a chained max node. Move the left into our nodes list
4614  if (next->left_)
4615  {
4616  nodes_.push_back (next->left_->build ());
4617  delete next->left_;
4618  next->left_ = 0;
4619  }
4620 
4621  // set right to next->right_ and then clear next->right_ before deletion
4622  right = next->right_;
4623  next->right_ = 0;
4624  delete next;
4625  }
4626 
4627  // push the rightmost build from the compressed node and delete it.
4628  // then reset our right_, since we've already taken care of deletion
4629  if (right)
4630  {
4631  nodes_.push_back (right->build ());
4632  delete right;
4633  }
4634  right_ = 0;
4635 
4636  return new CompositeSequentialNode (*(this->logger_), nodes_);
4637  }
4638  else if (left_)
4639  // all we have is a valid left child, so there is no reason to build
4640  // a Both operator
4641  return left_->build ();
4642  else if (right_)
4643  // all we have is a valid right child, so there is no reason to build
4644  // a Both operator
4645  return right_->build ();
4646  else
4647  // we've got nothing. This node should eventually be pruned out of the
4648  // picture if at all possible.
4649  return new LeafNode (*(this->logger_),
4651 }
4652 
4653 // constructor
4655  : Operator (logger, 0, 0, IMPLIES_PRECEDENCE)
4656 {
4657 }
4658 
4659 // destructor
4661 {
4662 }
4663 
4664 // returns the precedence level
4665 int
4667 {
4668  return this->precedence_ = IMPLIES_PRECEDENCE + precedence;
4669 }
4670 
4671 // builds an equivalent ExpressionTree node
4674 {
4675  ComponentNode * left (0), * right (0);
4676 
4677  if (left_)
4678  left = left_->build ();
4679 
4680  if (right_)
4681  right = right_->build ();
4682 
4683  return new CompositeImpliesNode (*(this->logger_), left, right);
4684 }
4685 
4686 
4687 // constructor
4689  : Operator (logger, 0, 0, ASSIGNMENT_PRECEDENCE)
4690 {
4691 }
4692 
4693 // destructor
4695 {
4696 }
4697 
4698 // returns the precedence level
4699 int
4701 {
4702  return this->precedence_ = ASSIGNMENT_PRECEDENCE + precedence;
4703 }
4704 
4705 // builds an equivalent ExpressionTree node
4708 {
4709  ComponentNode * left (0), * right (0);
4710 
4711  if (left_)
4712  left = left_->build ();
4713 
4714  if (right_)
4715  right = right_->build ();
4716 
4717  return new CompositeAssignmentNode (*(this->logger_), left, right);
4718 }
4719 
4720 
4721 // constructor
4723  : Operator (logger, 0, 0, CONDITIONAL_PRECEDENCE)
4724 {
4725 }
4726 
4727 // destructor
4729 {
4730 }
4731 
4732 // returns the precedence level
4733 int
4735 {
4737 }
4738 
4739 // builds an equivalent ExpressionTree node
4742 {
4743  ComponentNode * left (0), * right (0);
4744 
4745  if (left_)
4746  left = left_->build ();
4747 
4748  if (right_)
4749  right = right_->build ();
4750 
4751  return new CompositeEqualityNode (*(this->logger_), left, right);
4752 }
4753 
4754 // constructor
4756  : Operator (logger, 0, 0, CONDITIONAL_PRECEDENCE)
4757 {
4758 }
4759 
4760 // destructor
4762 {
4763 }
4764 
4765 // returns the precedence level
4766 int
4768 {
4770 }
4771 
4772 // builds an equivalent ExpressionTree node
4775 {
4776  ComponentNode * left (0), * right (0);
4777 
4778  if (left_)
4779  left = left_->build ();
4780 
4781  if (right_)
4782  right = right_->build ();
4783 
4784  return new CompositeInequalityNode (*(this->logger_), left, right);
4785 }
4786 
4787 // constructor
4790  : Operator (logger, 0, 0, CONDITIONAL_PRECEDENCE)
4791 {
4792 }
4793 
4794 // destructor
4796 {
4797 }
4798 
4799 // returns the precedence level
4800 int
4802 {
4804 }
4805 
4806 // builds an equivalent ExpressionTree node
4809 {
4810  ComponentNode * left (0), * right (0);
4811 
4812  if (left_)
4813  left = left_->build ();
4814 
4815  if (right_)
4816  right = right_->build ();
4817 
4818  return new CompositeGreaterThanEqualNode (
4819  *(this->logger_), left, right);
4820 }
4821 
4822 // constructor
4824  : Operator (logger, 0, 0, CONDITIONAL_PRECEDENCE)
4825 {
4826 }
4827 
4828 // destructor
4830 {
4831 }
4832 
4833 // returns the precedence level
4834 int
4836 {
4838 }
4839 
4840 // builds an equivalent ExpressionTree node
4843 {
4844  ComponentNode * left (0), * right (0);
4845 
4846  if (left_)
4847  left = left_->build ();
4848 
4849  if (right_)
4850  right = right_->build ();
4851 
4852  return new CompositeGreaterThanNode (*(this->logger_), left, right);
4853 }
4854 
4855 // constructor
4858  : Operator (logger, 0, 0, CONDITIONAL_PRECEDENCE)
4859 {
4860 }
4861 
4862 // destructor
4864 {
4865 }
4866 
4867 // returns the precedence level
4868 int
4870 {
4872 }
4873 
4874 // builds an equivalent ExpressionTree node
4877 {
4878  ComponentNode * left (0), * right (0);
4879 
4880  if (left_)
4881  left = left_->build ();
4882 
4883  if (right_)
4884  right = right_->build ();
4885 
4886  return new CompositeLessThanEqualNode (*(this->logger_), left, right);
4887 }
4888 
4889 // constructor
4891  : Operator (logger, 0, 0, CONDITIONAL_PRECEDENCE)
4892 {
4893 }
4894 
4895 // destructor
4897 {
4898 }
4899 
4900 // returns the precedence level
4901 int
4903 {
4905 }
4906 
4907 // builds an equivalent ExpressionTree node
4910 {
4911  ComponentNode * left (0), * right (0);
4912 
4913  if (left_)
4914  left = left_->build ();
4915 
4916  if (right_)
4917  right = right_->build ();
4918 
4919  return new CompositeLessThanNode (*(this->logger_), left, right);
4920 }
4921 
4922 
4923 // constructor
4925  : Operator (logger, 0, 0, SUBTRACT_PRECEDENCE)
4926 {
4927 }
4928 
4929 // destructor
4931 {
4932 }
4933 
4934 // returns the precedence level
4935 int
4937 {
4938  return this->precedence_ = ADD_PRECEDENCE + precedence;
4939 }
4940 
4941 // builds an equivalent ExpressionTree node
4944 {
4945  ComponentNode * left (0), * right (0);
4946 
4947  if (left_)
4948  left = left_->build ();
4949 
4950  if (right_)
4951  right = right_->build ();
4952 
4953  return new CompositeSubtractNode (*(this->logger_), left, right);
4954 }
4955 
4956 // constructor
4958  : TernaryOperator (logger, 0, 0, MULTIPLY_PRECEDENCE)
4959 {
4960 }
4961 
4962 // destructor
4964 {
4965 }
4966 
4967 // returns the precedence level
4968 int
4970 {
4971  return this->precedence_ = MULTIPLY_PRECEDENCE + precedence;
4972 }
4973 
4974 // builds an equivalent ExpressionTree node
4977 {
4978  if (left_ && right_)
4979  {
4980  Multiply * rhs = dynamic_cast <Multiply *> (right_);
4981 
4982  nodes_.push_back (left_->build ());
4983 
4984  if (rhs)
4985  {
4986  nodes_.insert (nodes_.end (), rhs->nodes_.begin (), rhs->nodes_.end ());
4987  rhs->nodes_.clear ();
4988  }
4989  else
4990  {
4991  nodes_.push_back (right_->build ());
4992  }
4993  return new CompositeMultiplyNode (*(this->logger_), nodes_);
4994  }
4995  else
4996  {
4997  return new CompositeMultiplyNode (*(this->logger_), nodes_);
4998  }
4999 }
5000 
5001 // constructor
5003  : Operator (logger, 0, 0, MODULUS_PRECEDENCE)
5004 {
5005 }
5006 
5007 // destructor
5009 {
5010 }
5011 
5012 // returns the precedence level
5013 int
5015 {
5016  return this->precedence_ = MODULUS_PRECEDENCE + precedence;
5017 }
5018 
5019 // builds an equivalent ExpressionTree node
5022 {
5023  ComponentNode * left (0), * right (0);
5024 
5025  if (left_)
5026  left = left_->build ();
5027 
5028  if (right_)
5029  right = right_->build ();
5030 
5031  return new CompositeModulusNode (*(this->logger_),
5032  left, right);
5033 }
5034 
5035 // constructor
5037  : Operator (logger, 0, 0, DIVIDE_PRECEDENCE)
5038 {
5039 }
5040 
5041 // destructor
5043 {
5044 }
5045 
5046 // returns the precedence level
5047 int
5049 {
5050  return this->precedence_ = DIVIDE_PRECEDENCE + precedence;
5051 }
5052 
5053 // builds an equivalent ExpressionTree node
5056 {
5057  ComponentNode * left (0), * right (0);
5058 
5059  if (left_)
5060  left = left_->build ();
5061 
5062  if (right_)
5063  right = right_->build ();
5064 
5065  return new CompositeDivideNode (*(this->logger_), left, right);
5066 }
5067 
5068 // constructor
5070 {
5071 }
5072 
5073 // destructor
5075 {
5076 }
5077 
5078 // extracts precondition, condition, postcondition, and body from input
5079 void
5082 std::string &variable,
5083 const std::string &input,
5084 std::string::size_type &i,
5085 int & accumulated_precedence,
5086 ::std::list<Symbol *>& list,
5087 Symbol *& returnableInput)
5088 {
5089  ::std::list <Symbol *> substr_list;
5090  Symbol * lastValidInput (0);
5091  std::string::size_type begin = i;
5092  Operator * precondition (0); //, * condition (0), * postcondition (0);
5093  Symbol * body (0), *user_pre (0), *user_cond (0), *user_post (0);
5094 
5095  // for extracting and using substrings of input
5096  std::string::size_type count (0);
5097  std::string substr;
5098 
5099  if (variable == "")
5100  {
5101  variable = ".MADARA_I";
5102  }
5103 
5104  bool delimiter_found = false, handled = false, equal_to = false;
5105  std::string::size_type delimiter_begin = 0;
5106  std::string::size_type delimiter_end = 0;
5107  int paren_depth = 0;
5108  int index_depth = 0;
5109 
5110  // search for end of for_loop conditions. Be on lookout for delimiter.
5111  for (; i < input.length (); ++i)
5112  {
5113  if (index_depth == 0 && paren_depth == 0 &&
5114  input[i] == '-' && !delimiter_found)
5115  {
5116  delimiter_found = true;
5117  delimiter_begin = i;
5118  }
5119  else if (index_depth == 0 && paren_depth == 0 &&
5120  delimiter_found && input[i] == '>')
5121  {
5122  delimiter_end = i;
5123  }
5124  else if (input[i] == ']')
5125  {
5126  if (index_depth == 0 && paren_depth == 0)
5127  {
5128  break;
5129  }
5130  else
5131  {
5132  --index_depth;
5133  }
5134  }
5135  else if (input[i] == '(')
5136  {
5137  ++paren_depth;
5138  }
5139  else if (input[i] == '[')
5140  {
5141  ++index_depth;
5142  }
5143  else if (input[i] == ')')
5144  {
5145  if (paren_depth == 0)
5146  {
5147  break;
5148  }
5149  else
5150  {
5151  --paren_depth;
5152  }
5153  }
5154  }
5155 
5160  if (delimiter_found && delimiter_end == 0)
5161  {
5162  delimiter_found = false;
5163  }
5164 
5165  // this is actually an array index
5166  if (!delimiter_found)
5167  {
5168  // variable
5169  // begin to end--the index
5170  substr = input.substr (begin, i - begin);
5171 
5172  Symbol * index = nullptr;
5173 
5174  for (count = 0;
5175  count < substr.length ();)
5176  {
5177  main_loop (context, substr, count, lastValidInput,
5178  handled, accumulated_precedence, substr_list);
5179  }
5180 
5182  "madara::expression::Interpreter: "
5183  "KaRL: For loop: Array reference created at %s\n",
5184  substr.c_str ());
5185 
5186  // we have a precondition
5187  if (!substr_list.empty ())
5188  {
5189  index = substr_list.back ();
5190  substr_list.clear ();
5191  }
5192 
5193  Symbol * op = new ArrayRef (variable, index, context);
5194  op->add_precedence (accumulated_precedence);
5195 
5196  // check for post increments and decrements
5197  if (i + 2 < input.size ())
5198  {
5199  if (input[i + 1] == '+' && input[i + 2] == '+')
5200  {
5201  Symbol * array_ref = op;
5202  op = new Postincrement (context.get_logger ());
5203  op->add_precedence (accumulated_precedence);
5204  op->right_ = array_ref;
5205  i += 2;
5206  }
5207  else if (input[i + 1] == '-' && input[i + 2] == '-')
5208  {
5209  Symbol * array_ref = op;
5210  op = new Postdecrement (context.get_logger ());
5211  op->add_precedence (accumulated_precedence);
5212  op->right_ = array_ref;
5213  i += 2;
5214  }
5215  }
5216 
5217  lastValidInput = op;
5218 
5219  precedence_insert (context, op, list);
5220 
5221  returnableInput = op;
5222  ++i;
5223  return;
5224  }
5225 
5227  "madara::expression::Interpreter: "
5228  "KaRL: For loop: Within input string, the for loop delimiter begins at %d"
5229  " and ends at %d (should be at least 1). Loop construct begins at "
5230  "%d and ends at %d\n",
5231  (int)delimiter_begin, (int)delimiter_end, (int)begin, (int)i);
5232 
5233 
5234  // What did we end with? Less than? Greater than?
5235  if (input[i] == ']')
5236  equal_to = true;
5237  else if (input[i] != ')')
5238  {
5239  // this is an error. Essentially, it means the user did not close the
5240  // for loop.
5242  "madara::expression::Interpreter: "
5243  "KARL COMPILE ERROR:: No closing delimiter (']' or ')')"
5244  " has been specified on the for loop.\n");
5245 
5246  throw KarlException ("madara::expression::Interpreter: "
5247  "KARL COMPILE ERROR:: No closing delimiter (']' or ')')"
5248  " has been specified on the for loop.\n");
5249  }
5250 
5251  // get the precondition, postcondition and condition ready
5252  precondition = new Assignment (context.get_logger ());
5253  precondition->left_ = new Variable (variable, context);
5254 
5255 
5256  // this is the non-short-hand way of specifying, e.g., var[0,30] {}
5257  if (delimiter_found)
5258  {
5259  // setup precondition
5260  if (delimiter_begin - begin > 0)
5261  {
5262  // run main_loop on the precondition substring
5263  substr = input.substr (begin, delimiter_begin - begin);
5264 
5265  for (count = 0;
5266  count < substr.length ();)
5267  {
5268  main_loop (context, substr, count, lastValidInput,
5269  handled, accumulated_precedence, substr_list);
5270  }
5271 
5273  "madara::expression::Interpreter: "
5274  "KaRL: For loop: Precondition is set to %s\n", substr.c_str ());
5275 
5276  // we have a precondition
5277  if (!substr_list.empty ())
5278  {
5279  user_pre = substr_list.back ();
5280  substr_list.clear ();
5281  }
5282  }
5283  else
5284  {
5286  "madara::expression::Interpreter: "
5287  "KaRL: For loop: No loop precondition was specified\n");
5288  }
5289 
5290  // check for special increment
5291  if (delimiter_end - delimiter_begin > 1)
5292  {
5293  count = 0;
5294  lastValidInput = 0;
5295  substr = input.substr (delimiter_begin + 1, delimiter_end - (delimiter_begin + 1));
5296 
5297  for (count = 0;
5298  count < substr.length ();)
5299  {
5300  main_loop (context, substr, count, lastValidInput,
5301  handled, accumulated_precedence, substr_list);
5302  }
5303 
5305  "madara::expression::Interpreter: "
5306  "KaRL: For loop: Postcondition is set to %s\n", substr.c_str ());
5307 
5308  // we have a postcondition
5309  if (!substr_list.empty ())
5310  {
5311  user_post = substr_list.back ();
5312 
5313  substr_list.clear ();
5314  }
5315  }
5316  else
5317  {
5319  "KaRL: For loop: No loop special increment was specified\n");
5320  }
5321 
5322  // set condition
5323  if (i - delimiter_end >= 2)
5324  {
5325  lastValidInput = 0;
5326  substr = input.substr (delimiter_end + 1, i - (delimiter_end + 1));
5327 
5328  for (count = 0;
5329  count < substr.length ();)
5330  {
5331  main_loop (context, substr, count, lastValidInput,
5332  handled, accumulated_precedence, substr_list);
5333  }
5334 
5335  // we have a condition
5336  if (!substr_list.empty ())
5337  {
5339  "KaRL: For loop: Condition is set to %s\n", substr.c_str ());
5340 
5341  user_cond = substr_list.back ();
5342  substr_list.clear ();
5343  }
5344  else
5345  {
5347  "KaRL: For loop: Condition was not set to %s\n", substr.c_str ());
5348  }
5349  }
5350  else
5351  {
5353  "KaRL: For loop: No loop condition was specified\n");
5354  }
5355  }
5356  // if no delimiter found, this is the shorthand
5357  else
5358  {
5359  lastValidInput = 0;
5360  substr = input.substr (begin, i - begin);
5361 
5362  for (count = 0;
5363  count < substr.length ();)
5364  {
5365  main_loop (context, substr, count, lastValidInput,
5366  handled, accumulated_precedence, substr_list);
5367  }
5368 
5370  "KaRL: For loop: Condition only is set to %s\n", substr.c_str ());
5371 
5372  // we have a condition
5373  if (!substr_list.empty ())
5374  {
5375  user_cond = substr_list.back ();
5376  substr_list.clear ();
5377  }
5378  }
5379 
5380  // if precondition not set, set to default
5381  if (!user_pre)
5382  {
5383  user_pre = new Number (context.get_logger (),
5385  }
5386 
5387  // set condition to default if not yet set
5388  if (!user_cond)
5389  {
5390  user_cond = new Number (context.get_logger (),
5392  }
5393 
5394  // set postcondition to default if not yet set
5395  if (!user_post)
5396  {
5397  user_post = new Number (context.get_logger (),
5400  "KaRL: For loop: Postcondition is set to 1 (def)\n");
5401  }
5402 
5403  // eat up whitespace so we can check for a parenthesis (function)
5404  for (++i; i < input.length () && is_whitespace (input[i]); ++i);
5405 
5406  // can't have a body without a parenthesis or brace
5407  if (i < input.length () && input[i] == '(')
5408  {
5409  ++i;
5410  lastValidInput = 0;
5411 
5413  "KaRL: For loop: Body is reading from %s\n",
5414  input.substr (i, input.size () - i).c_str ());
5415 
5416 
5417  // we have a function instead of a variable
5418  handle_parenthesis (context, input, i, lastValidInput, handled,
5419  accumulated_precedence, substr_list);
5420 
5421  if (!substr_list.empty ())
5422  {
5423  body = substr_list.back ();
5424  substr_list.clear ();
5425  }
5426  }
5427 
5428  // now, see if we can locate a body for the for loop
5429  if (body)
5430  {
5431  Assignment * assignment = dynamic_cast <Assignment *> (body);
5432  if (assignment)
5433  {
5434  Variable * variable_node = dynamic_cast <Variable *> (assignment->left_);
5435  Number * number = dynamic_cast <Number *> (assignment->right_);
5436 
5437  if (variable_node && number)
5438  {
5440  "KaRL: For loop: Body is a simple assignment of variable %s to %s\n",
5441  variable_node->key_.c_str (), number->item_.to_string ().c_str ());
5442  }
5443  else
5444  {
5446  "KaRL: For loop: For loop has a complex body\n");
5447  }
5448  }
5449 
5450  precondition->right_ = user_pre;
5453 
5454  // optimize postcondition
5455  Number * number = dynamic_cast <Number *> (user_post);
5456  if (number)
5457  {
5458  post_val = number->item_;
5459  delete number;
5460  user_post = 0;
5461  }
5462 
5463  // optimize condition
5464  number = dynamic_cast <Number *> (user_cond);
5465  if (number)
5466  {
5467  cond_val = number->item_;
5468  delete number;
5469  user_cond = 0;
5470  }
5471 
5472  int compare_type (0);
5473 
5474  if (equal_to)
5475  compare_type = 1;
5476 
5477  Variable * var_node = new Variable (variable, context);
5478 
5479  VariableIncrement * postcondition = new VariableIncrement (
5480  var_node, post_val, user_post, context);
5481  postcondition->add_precedence (
5482  accumulated_precedence + FOR_LOOP_PRECEDENCE);
5483 
5484  VariableCompare * condition = new VariableCompare (var_node, cond_val,
5485  user_cond, compare_type, context);
5486  condition->add_precedence (accumulated_precedence + FOR_LOOP_PRECEDENCE);
5487 
5488  Symbol * op = new ForLoop (
5489  precondition, condition, postcondition, body, context);
5490  op->add_precedence (accumulated_precedence);
5491 
5492  precedence_insert (context, op, list);
5493 
5494  lastValidInput = 0;
5495  }
5496  else
5497  {
5498  // user forgot to specify a for loop body, so they apparently just want us to loop
5499  // the variable from the precondition to the condition. Since we assume the user
5500  // doesn't want a busy loop, which this is, we instead create an assignment for
5501  // the variable to equal the condition and clean up the pointers
5502 
5503  // if they specified a ']', they actually want something 1 greater than the condition
5504  if (equal_to)
5505  {
5506  Number * number = dynamic_cast <Number *> (user_cond);
5507 
5508  if (number)
5509  ++number->item_;
5510  else
5511  {
5512  // if it wasn't already a number, then it must be something more complex. We'll
5513  // just add one to it and see if the prune () method can optimize it a bit.
5514  Add * add = new Add (context.get_logger ());
5515  add->left_ = new Number (context.get_logger (),
5517  add->right_ = user_cond;
5518  user_cond = add;
5519  }
5520  }
5521 
5522  delete precondition->right_;
5523  precondition->right_ = user_cond;
5524  precondition->add_precedence (accumulated_precedence);
5525 
5526  precedence_insert (context, precondition, list);
5527 
5528  lastValidInput = 0;
5529  }
5530 }
5531 
5532 // inserts a variable (leaf node / number) into the parse tree
5533 void
5536 const std::string &input,
5537 std::string::size_type &i,
5538 int & accumulated_precedence,
5539 ::std::list<Symbol *>& list,
5540 Symbol *& lastValidInput)
5541 {
5542  // build a potential variable name (this could also be a function)
5543  std::string::size_type j = 1;
5544 
5545  for (; i + j < input.length () && is_alphanumeric (input[i + j]); ++j)
5546  continue;
5547 
5548  // the variable or function name is stored in input.substr (i,j)
5549  // is the next char a parenthesis?
5550 
5551  std::string name = input.substr (i, j);
5552 
5553  i += j;
5554 
5555  // eat up whitespace so we can check for a parenthesis (function)
5556  for (; i < input.length () && is_whitespace (input[i]); ++i);
5557 
5558  // if this is a reserved word, then treat it as a Leaf
5559  if (is_reserved_word (name))
5560  {
5561  if (name == "true")
5562  {
5564  "madara::expression::Interpreter: "
5565  "Inserting true(1) into expression tree.\n");
5566 
5567  Number * number = new Number (context.get_logger (), (Integer)1);
5568  number->add_precedence (accumulated_precedence);
5569  lastValidInput = number;
5570 
5571  precedence_insert (context, number, list);
5572  }
5573  else if (name == "false")
5574  {
5576  "madara::expression::Interpreter: "
5577  "Inserting false(0) into expression tree.\n");
5578 
5579  Number * number = new Number (context.get_logger (), (Integer)0);
5580  number->add_precedence (accumulated_precedence);
5581  lastValidInput = number;
5582 
5583  precedence_insert (context, number, list);
5584  }
5585  else if (name == "nan")
5586  {
5588  "madara::expression::Interpreter: "
5589  "Inserting NAN into expression tree.\n");
5590 
5591  Number * number = new Number (context.get_logger (), NAN);
5592  number->add_precedence (accumulated_precedence);
5593  lastValidInput = number;
5594 
5595  precedence_insert (context, number, list);
5596  }
5597  else if (name == "inf")
5598  {
5600  "madara::expression::Interpreter: "
5601  "Inserting INFINITY into expression tree.\n");
5602 
5603  Number * number = new Number (context.get_logger (), INFINITY);
5604  number->add_precedence (accumulated_precedence);
5605  lastValidInput = number;
5606 
5607  precedence_insert (context, number, list);
5608  }
5609  }
5610 
5611  else if (i < input.length () && input[i] == '(')
5612  {
5613  // save the function name and update i
5614  Function * function = new Function (name, context);
5615  function->add_precedence (accumulated_precedence);
5616 
5617  bool handled = false;
5618 
5619  ::std::list<Symbol *> param_list;
5620 
5621  int local_precedence = 0;
5622  Symbol * local_last_valid = 0;
5623 
5624  ++i;
5625 
5626  // we have a function instead of a variable
5627  handle_parenthesis (context, input, i, local_last_valid, handled,
5628  local_precedence, param_list, true);
5629 
5630  //if (param_list.size () > 0)
5631  // function->right_ = param_list.back ();
5632 
5633  function->nodes_.resize (param_list.size ());
5634  int cur = 0;
5635 
5636  for (::std::list<Symbol *>::iterator arg = param_list.begin ();
5637  arg != param_list.end (); ++arg, ++cur)
5638  {
5639  function->nodes_[cur] = (*arg)->build ();
5640  }
5641 
5642  //function->right_ = new List (context);
5643 
5644  precedence_insert (context, function, list);
5645  lastValidInput = 0;
5646  }
5647  else if (i < input.length () && input[i] == '[')
5648  {
5649  ++i;
5650  handle_for_loop (context, name, input, i, accumulated_precedence,
5651  list, lastValidInput);
5652  }
5653  else
5654  {
5655  Symbol * op = new Variable (name, context);
5656  op->add_precedence (accumulated_precedence);
5657 
5658  // check for post increments and decrements
5659  if (i + 1 < input.size ())
5660  {
5661  if (input[i] == '+' && input[i + 1] == '+')
5662  {
5663  Symbol * variable = op;
5664  op = new Postincrement (context.get_logger ());
5665  op->add_precedence (accumulated_precedence);
5666  op->right_ = variable;
5667  i += 2;
5668  }
5669  else if (input[i] == '-' && input[i + 1] == '-')
5670  {
5671  Symbol * variable = op;
5672  op = new Postdecrement (context.get_logger ());
5673  op->add_precedence (accumulated_precedence);
5674  op->right_ = variable;
5675  i += 2;
5676  }
5677  }
5678 
5679  lastValidInput = op;
5680 
5681  precedence_insert (context, op, list);
5682  }
5683 }
5684 
5685 // inserts a leaf node / number into the parse tree
5686 void
5688  char opener,
5689  knowledge::ThreadSafeContext & context,
5690  const std::string &input,
5691  std::string::size_type &i, int & accumulated_precedence,
5692  ::std::list<madara::expression::Symbol *>& list,
5693  madara::expression::Symbol *& lastValidInput)
5694 {
5695  std::string::size_type j = 0;
5696  Number * number = 0;
5697 
5698  for (; i + j < input.length (); ++j)
5699  {
5700  if (input[i + j] == opener && input[i + j - 1] != '\\')
5701  break;
5702  }
5703 
5704  number = new Number (context.get_logger (), input.substr (i, j));
5705 
5706  number->add_precedence (accumulated_precedence);
5707 
5708  lastValidInput = number;
5709 
5710  // update i to next char for main loop or handle parenthesis.
5711 
5712  i += j + 1;
5713 
5714  precedence_insert (context, number, list);
5715 }
5716 
5717 // inserts a variable (leaf node / number) into the parse tree
5718 void
5721  const std::string &input,
5722  std::string::size_type &i,
5723  int & accumulated_precedence,
5724  ::std::list<Symbol *>& list,
5725  Symbol *& lastValidInput)
5726 {
5727  // build a potential variable name (this could also be a function)
5728  std::string::size_type j = 1;
5729 
5730  for (; i + j < input.length () && is_alphanumeric (input[i + j]); ++j)
5731  continue;
5732 
5733  // the variable or function name is stored in input.substr (i,j)
5734  // is the next char a parenthesis?
5735 
5736  std::string name = input.substr (i, j);
5737 
5738  i += j;
5739 
5740  // eat up whitespace so we can check for a parenthesis (function)
5741  for (; i < input.length () && is_whitespace (input[i]); ++i);
5742 
5743  if (i < input.length () && input[i] == '(')
5744  {
5745  // save the function name and update i
5746  SystemCall * call = 0;
5747  char first_char = 0;
5748 
5749  if (name.size () > 1)
5750  {
5751  first_char = name[1];
5752  }
5753 
5754  switch (first_char)
5755  {
5756  case 'b':
5757  if (name == "#buffer")
5758  {
5759  call = new ToBuffer (context);
5760  }
5761  break;
5762  case 'c':
5763  if (name == "#clear_var" || name == "#clear_variable")
5764  {
5765  call = new ClearVariable (context);
5766  }
5767  else if (name == "#cos")
5768  {
5769  call = new Cos (context);
5770  }
5771  break;
5772  case 'd':
5773  if (name == "#delete_var" || name == "#delete_variable")
5774  {
5775  call = new DeleteVariable (context);
5776  }
5777  else if (name == "#double")
5778  {
5779  call = new ToDouble (context);
5780  }
5781  else if (name == "#doubles")
5782  {
5783  call = new ToDoubles (context);
5784  }
5785  break;
5786  case 'e':
5787  if (name == "#eval" || name == "#evaluate")
5788  {
5789  call = new Eval (context);
5790  }
5791  else if (name == "#expand" || name == "#expand_statement")
5792  {
5793  call = new ExpandStatement (context);
5794  }
5795  else if (name == "#expand_env" || name == "#expand_envs")
5796  {
5797  call = new ExpandEnv (context);
5798  }
5799  break;
5800  case 'f':
5801  if (name == "#fragment")
5802  {
5803  call = new Fragment (context);
5804  }
5805  else if (name == "#fixed")
5806  {
5807  call = new SetFixed (context);
5808  }
5809  break;
5810  case 'g':
5811  if (name == "#get_clock")
5812  {
5813  call = new GetClock (context);
5814  }
5815  else if (name == "#get_time" || name == "#get_time_ns" || name == "#get_time_nano")
5816  {
5817  call = new GetTime (context);
5818  }
5819  else if (name == "#get_time_seconds" || name == "#get_time_s")
5820  {
5821  call = new GetTimeSeconds (context);
5822  }
5823  break;
5824  case 'i':
5825  if (name == "#integer")
5826  {
5827  call = new ToInteger (context);
5828  }
5829  else if (name == "#integers")
5830  {
5831  call = new ToIntegers (context);
5832  }
5833  else if (name == "#isinf")
5834  {
5835  call = new Isinf (context);
5836  }
5837  break;
5838  case 'l':
5839  if (name == "#log_level")
5840  {
5841  call = new LogLevel (context);
5842  }
5843  break;
5844  case 'p':
5845  if (name == "#pow")
5846  {
5847  call = new Power (context);
5848  }
5849  else if (name == "#print")
5850  {
5851  call = new Print (context);
5852  }
5853  else if (name == "#print_system_calls" || name == "#print_system_call")
5854  {
5855  call = new PrintSystemCalls (context);
5856  }
5857  else if (name == "#precision")
5858  {
5859  call = new SetPrecision (context);
5860  }
5861  break;
5862  case 'r':
5863  if (name == "#rand_double")
5864  {
5865  call = new RandDouble (context);
5866  }
5867  else if (name == "#rand_int" || name == "#rand_integer")
5868  {
5869  call = new RandInt (context);
5870  }
5871  else if (name == "#read_file")
5872  {
5873  call = new ReadFile (context);
5874  }
5875  break;
5876  case 's':
5877  if (name == "#scientific")
5878  {
5879  call = new SetScientific (context);
5880  }
5881  else if (name == "#set_clock")
5882  {
5883  call = new SetClock (context);
5884  }
5885  else if (name == "#set_fixed")
5886  {
5887  call = new SetFixed (context);
5888  }
5889  else if (name == "#set_precision")
5890  {
5891  call = new SetPrecision (context);
5892  }
5893  else if (name == "#set_scientific")
5894  {
5895  call = new SetScientific (context);
5896  }
5897  else if (name == "#sin")
5898  {
5899  call = new Sin (context);
5900  }
5901  else if (name == "#size")
5902  {
5903  call = new Size (context);
5904  }
5905  else if (name == "#sleep")
5906  {
5907  call = new Sleep (context);
5908  }
5909  else if (name == "#sqrt")
5910  {
5911  call = new SquareRoot (context);
5912  }
5913  else if (name == "#string")
5914  {
5915  call = new ToString (context);
5916  }
5917  break;
5918  case 't':
5919  if (name == "#tan")
5920  {
5921  call = new Tan (context);
5922  }
5923  else if (name == "#to_buffer")
5924  {
5925  call = new ToBuffer (context);
5926  }
5927  else if (name == "#to_double")
5928  {
5929  call = new ToDouble (context);
5930  }
5931  else if (name == "#to_doubles")
5932  {
5933  call = new ToDoubles (context);
5934  }
5935  else if (name == "#to_host_dirs")
5936  {
5937  call = new ToHostDirs (context);
5938  }
5939  else if (name == "#to_integer")
5940  {
5941  call = new ToInteger (context);
5942  }
5943  else if (name == "#to_integers")
5944  {
5945  call = new ToIntegers (context);
5946  }
5947  else if (name == "#to_string")
5948  {
5949  call = new ToString (context);
5950  }
5951  else if (name == "#type")
5952  {
5953  call = new Type (context);
5954  }
5955  break;
5956  case 'w':
5957  if (name == "#write_file")
5958  {
5959  call = new WriteFile (context);
5960  }
5961  break;
5962  default:
5963  break;
5964  }
5965 
5966  if (!call)
5967  {
5969  "madara::expression::Interpreter: "
5970  "System call %s is unsupported in this version of MADARA, "
5971  "defaulting to print_system_calls help menu.\n", name.c_str ());
5972 
5973  throw KarlException ("madara::expression::Interpreter: "
5974  "System call %s does not exist.");
5975  }
5976  else
5977  {
5978  call->add_precedence (accumulated_precedence);
5979  }
5980 
5981  bool handled = false;
5982 
5983  ::std::list<Symbol *> param_list;
5984 
5985  ++i;
5986 
5987  // we have a function instead of a variable
5988  handle_parenthesis (context, input, i, lastValidInput, handled,
5989  accumulated_precedence, param_list, true);
5990 
5991  call->nodes_.resize (param_list.size ());
5992  int cur = 0;
5993 
5994  for (::std::list<Symbol *>::iterator arg = param_list.begin ();
5995  arg != param_list.end (); ++arg, ++cur)
5996  {
5997  call->nodes_[cur] = (*arg)->build ();
5998  }
5999 
6000  precedence_insert (context, call, list);
6001  lastValidInput = 0;
6002  }
6003  else
6004  {
6005  std::string message =
6006  "madara::expression::Interpreter: "
6007  "KARL COMPILE ERROR: System call ";
6008  message += name;
6009  message += " does not have appropriate parentheses\n";
6010 
6012  message.c_str ());
6013 
6014  throw KarlException (message.c_str ());
6015  }
6016 }
6017 
6018 // inserts a leaf node / number into the parse tree
6019 void
6021  knowledge::ThreadSafeContext & context,
6022  const std::string &input,
6023  std::string::size_type &i,
6024  int & accumulated_precedence,
6025  ::std::list<madara::expression::Symbol *>& list,
6026  madara::expression::Symbol *& lastValidInput)
6027 {
6028  // merge all consecutive number chars into a single Number symbol,
6029  // eg '123' = int (123). Scope of j needs to be outside of the for
6030  // loop.
6031 
6032  std::string::size_type j = 1;
6033  Number * number = 0;
6034 
6035  for (; i + j <= input.length () && is_number (input[i + j]); ++j)
6036  continue;
6037 
6038  // do we have a float?
6039  if ((i + j <= input.length () && input[i + j] == '.') || input[i] == '.')
6040  {
6041  if (input[i] != '.')
6042  ++j;
6043 
6044  for (; i + j <= input.length () && is_number (input[i + j]); ++j)
6045  continue;
6046 
6047  // scientific notation
6048  if (i + j <= input.length () &&
6049  (input[i + j] == 'e' || input[i + j] == 'E'))
6050  {
6051  ++j;
6052  if (i + j <= input.length () &&
6053  (input[i + j] == '+' || input[i + j] == '-'))
6054  {
6055  ++j;
6056  }
6057 
6058  for (; i + j <= input.length () && is_number (input[i + j]); ++j)
6059  continue;
6060  }
6061 
6062  double new_number;
6063 
6064  std::stringstream buffer;
6065  buffer << input.substr (i, j);
6066  buffer >> new_number;
6067 
6068  number = new Number (context.get_logger (), new_number);
6069  }
6070  else
6071  {
6072  // we have an integer
6073 
6075 
6076  std::stringstream buffer;
6077  buffer << input.substr (i, j);
6078  buffer >> new_number;
6079 
6080  number = new Number (context.get_logger (), new_number);
6081  }
6082 
6083  number->add_precedence (accumulated_precedence);
6084 
6085  lastValidInput = number;
6086 
6087  // update i to next char for main loop or handle parenthesis.
6088 
6089  i += j;
6090 
6091  precedence_insert (context, number, list);
6092 }
6093 
6094 
6095 // inserts a multiplication or division into the parse tree
6096 void
6100 ::std::list<madara::expression::Symbol *>& list)
6101 {
6102  if (!list.empty ())
6103  {
6104  // if last element was a number, then make that our left_
6105 
6106  Symbol *parent = list.back ();
6107  Symbol *child = 0;
6108  Symbol *grandparent = 0;
6109 
6110  // check to see if op is an assignment or implication, which are treated
6111  // uniquely
6112  Assignment * op_assignment = dynamic_cast <Assignment *> (op);
6113  Implies * op_implies = dynamic_cast <Implies *> (op);
6114  UnaryOperator * op_unary = dynamic_cast <UnaryOperator *> (op);
6115 
6116  // move down the right side of the tree until we find either a null or
6117  // a precedence that is >= this operation's precedence. This puts us
6118  // in the situation that we know our op should be performed after child
6119  // or child should be null (assignment or implication not withstanding)
6120  for (child = parent->right_;
6121  child && child->precedence () < op->precedence ();
6122  child = child->right_)
6123  {
6124  grandparent = parent;
6125  parent = child;
6126  }
6127 
6128  // child casts
6129  Operator * child_operator = dynamic_cast <Operator *> (child);
6130  Operator * child_ternary = dynamic_cast <TernaryOperator *> (child);
6131 
6132  if (child && (child_operator == 0 && child_ternary == 0))
6133  {
6135  "Interpreter::precedence_insert: "
6136  "Level 1: child is neither an operator or ternary\n");
6137  }
6138 
6139  // parent->precedence is < op->precedence at this point
6140 
6141  if (op_assignment || op_implies || op_unary)
6142  {
6143  // if we are an assignment, implies, or unary op, we actually
6144  // need this op to have slightly higher precedence (it needs to be
6145  // evaluated first). This situation is signified by something like this
6146  // var1 = var2 = var3 = 1. In the list, will be var1 = var2 = var3, so parent will be
6147  // and assignment, and parent left will be var1, right and child will be assignment
6148  // and it will have a left of var2
6149 
6150 
6151  for (child = parent->right_;
6152  child && child->precedence () <= op->precedence ();
6153  child = child->right_)
6154  {
6155  grandparent = parent;
6156  parent = child;
6157  }
6158 
6159  // child casts
6160  child_operator = dynamic_cast <Operator *> (child);
6161  child_ternary = dynamic_cast <TernaryOperator *> (child);
6162 
6163  if (child && (child_operator == 0 && child_ternary == 0))
6164  {
6166  "Interpreter::precedence_insert: "
6167  "Level 2: child is neither an operator or ternary\n");
6168  }
6169  }
6170 
6171  // Now that we have our parent and child setup appropriately according
6172  // to precedence relationships, we should be able to modify or replace
6173  // the tree in the list
6174 
6175  if (parent->precedence () < op->precedence () ||
6176  (parent->precedence () == op->precedence () &&
6177  (op_assignment || op_implies || op_unary)))
6178  {
6179  // this op needs to be evaluated before the parent
6180 
6181  // first let's do some error checking, so we can give helpful compile errors
6182  Operator * parent_binary = dynamic_cast <Operator *> (parent);
6183  UnaryOperator * parent_unary = dynamic_cast <UnaryOperator *> (parent);
6184 
6185  // if the parent is a binary (like addition or &&), then it needs a left hand side
6186  // if it doesn't have this, let's report a warning and insert a Leaf Node with a value
6187  // of zero
6188  if (parent_binary && !parent->left_)
6189  {
6190  // try to give as specific message as possible
6191  Both * parent_both = dynamic_cast <Both *> (parent);
6192  if (parent_both)
6193  {
6195  "KARL COMPILE WARNING: Empty statements between ';' may"
6196  " cause slower execution, attempting to prune away the extra "
6197  "statement\n");
6198  }
6199  else
6200  {
6202  "madara::expression::Interpreter: "
6203  "KARL COMPILE WARNING: Binary operation has no left child. "
6204  "Inserting a zero\n");
6205 
6206  parent->left_ = new Number (context.get_logger (),
6208  }
6209  }
6210 
6211  // if the parent is a unary operator (like negate or not), then it should
6212  // NOT have a left child. This would only happen if someone input
6213  // something like 5 ! 3, which has no meaning. This is a compile error.
6214  if (parent_unary && parent->left_)
6215  {
6217  "madara::expression::Interpreter: "
6218  "KARL COMPILE ERROR: Unary operation shouldn't have a left child\n");
6219 
6220  throw KarlException ("madara::expression::Interpreter: "
6221  "KARL COMPILE ERROR: "
6222  "Parent unary node has a left child, shouldn't be possible\n");
6223  }
6224 
6225  // if we've gotten to this point, then we need to
6226  // replace the child with ourself in the tree
6227  if (child)
6228  {
6229  if (op_unary)
6230  {
6231  // This is a compile error. Unary cannot have a left
6232  // child, and that is the only way that being at this
6233  // point would make sense.
6235  "madara::expression::Interpreter: "
6236  "KARL COMPILE ERROR: unary operation shouldn't have a left child\n");
6237 
6238  throw KarlException ("madara::expression::Interpreter: "
6239  "KARL COMPILE ERROR: "
6240  "Unary node has a left child, shouldn't be possible\n");
6241  }
6242  else
6243  {
6245  "Interpreter::precedence_insert: "
6246  "Level 3: op is setting its left to the existing child\n");
6247 
6248  op->left_ = child;
6249  }
6250  }
6251 
6253  "Interpreter::precedence_insert: "
6254  "Level 3: parent->right is being set to current operator\n");
6255 
6256  parent->right_ = op;
6257  }
6258  else
6259  {
6260  // we are a lower precedence than our parent, so we need to replace
6261  // the tree in the list. This typically happens with assignment, implies,
6262  // logical operations (&&, ||) and equality checks
6263 
6264  op->left_ = parent;
6265 
6266  if (grandparent)
6267  grandparent->right_ = op;
6268  else
6269  {
6270  list.pop_back ();
6271  list.push_back (op);
6272  }
6273  }
6274  }
6275  else
6276  {
6277  list.push_back (op);
6278  }
6279 }
6280 
6281 void
6284 const std::string &input, std::string::size_type &i,
6285 madara::expression::Symbol *& lastValidInput,
6286 bool & handled, int & accumulated_precedence,
6287 ::std::list<madara::expression::Symbol *>& list,
6288 bool build_argument_list)
6289 {
6290  handled = false;
6291  if (is_number (input[i]) ||
6292  (i + 1 < input.size () && input[i] == '.' && is_number (input[i+1])))
6293  {
6294  handled = true;
6295  // leaf node
6296  number_insert (context, input, i, accumulated_precedence,
6297  list, lastValidInput);
6298  }
6299  else if (is_alphanumeric (input[i]))
6300  {
6301  handled = true;
6302  // variable leaf node
6303  variable_insert (context, input, i, accumulated_precedence,
6304  list, lastValidInput);
6305  }
6306  else if (is_string_literal (input[i]))
6307  {
6308  char opener = input[i];
6309  ++i;
6310  handled = true;
6311  // string
6312  string_insert (opener, context, input, i, accumulated_precedence,
6313  list, lastValidInput);
6314  }
6315  else if (i < input.length () && input[i] == '[')
6316  {
6317  // save the function name and update i
6318  ConstArray * object = new ConstArray (context);
6319  object->add_precedence (accumulated_precedence);
6320 
6321  handled = false;
6322 
6323  ::std::list<Symbol *> param_list;
6324 
6325  int local_precedence = 0;
6326  Symbol * local_last_valid = 0;
6327 
6328  ++i;
6329 
6330  // we have an array
6331  handle_array (context, input, i, local_last_valid, handled,
6332  local_precedence, param_list);
6333 
6334  object->nodes_.resize (param_list.size ());
6335  int cur = 0;
6336 
6337  for (::std::list<Symbol *>::iterator arg = param_list.begin ();
6338  arg != param_list.end (); ++arg, ++cur)
6339  {
6340  object->nodes_[cur] = (*arg)->build ();
6341  }
6342 
6343  precedence_insert (context, object, list);
6344  lastValidInput = 0;
6345  }
6346  else if (input[i] == '#')
6347  {
6348  handled = true;
6349  // variable leaf node
6350  system_call_insert (context, input, i, accumulated_precedence,
6351  list, lastValidInput);
6352  }
6353  else if (input[i] == '+')
6354  {
6355  handled = true;
6356  Symbol * op = 0;
6357 
6358  // is this a predecrement?
6359  if (i + 1 < input.size () && input[i + 1] == '+')
6360  {
6361  op = new Preincrement (context.get_logger ());
6362  ++i;
6363  }
6364  // is this an atomic increment?
6365  else if (i + 1 < input.size () && input[i + 1] == '=')
6366  {
6367  Variable * var = dynamic_cast <Variable *> (lastValidInput);
6368  ArrayRef * array_ref = dynamic_cast <ArrayRef *> (lastValidInput);
6369  if (var || array_ref)
6370  {
6371  op = new VariableIncrement (lastValidInput,
6372  madara::knowledge::KnowledgeRecord (), 0, context);
6373  }
6374  else
6375  {
6377  "madara::expression::Interpreter: "
6378  "KARL COMPILE ERROR (+=): "
6379  "Assignments must have a variable left hand side.\n");
6380 
6381  throw KarlException ("madara::expression::Interpreter: "
6382  "KARL COMPILE ERROR (+=): "
6383  "Assignments must have a variable left hand side");
6384  }
6385  ++i;
6386  }
6387  else
6388  op = new Add (context.get_logger ());
6389 
6390  // insert the op according to left-to-right relationships
6391  op->add_precedence (accumulated_precedence);
6392  lastValidInput = 0;
6393  precedence_insert (context, op, list);
6394  ++i;
6395  }
6396  else if (input[i] == '-')
6397  {
6398  handled = true;
6399  Symbol * op = 0;
6400 
6401  // is this a predecrement?
6402  if (i + 1 < input.size () && input[i + 1] == '-')
6403  {
6404  op = new Predecrement (context.get_logger ());
6405  ++i;
6406  }
6407  // is this an atomic decrement?
6408  else if (i + 1 < input.size () && input[i + 1] == '=')
6409  {
6410  Variable * var = dynamic_cast <Variable *> (lastValidInput);
6411  ArrayRef * array_ref = dynamic_cast <ArrayRef *> (lastValidInput);
6412  if (var || array_ref)
6413  {
6414  op = new VariableDecrement (lastValidInput, madara::knowledge::KnowledgeRecord (),
6415  0, context);
6416  }
6417  else
6418  {
6420  "madara::expression::Interpreter: "
6421  "KARL COMPILE ERROR (-=): "
6422  "Assignments must have a variable left hand side.\n");
6423 
6424  throw KarlException ("madara::expression::Interpreter: "
6425  "KARL COMPILE ERROR (-=): "
6426  "Assignments must have a variable left hand side");
6427  }
6428  ++i;
6429  }
6430  // is this a number literal? Handling this way allows for INT64_MIN
6431  else if (i + 1 < input.size () && is_number (input[i + 1]))
6432  {
6433  handled = true;
6434  // leaf node
6435  number_insert (context, input, i, accumulated_precedence,
6436  list, lastValidInput);
6437  }
6438  // Negate
6439  else if (!lastValidInput)
6440  op = new Negate (context.get_logger ());
6441  // Subtract
6442  else
6443  op = new Subtract (context.get_logger ());
6444 
6445  if (op)
6446  {
6447  // insert the op according to left-to-right relationships
6448  lastValidInput = 0;
6449  op->add_precedence (accumulated_precedence);
6450  precedence_insert (context, op, list);
6451  ++i;
6452  }
6453  }
6454  else if (input[i] == '*')
6455  {
6456  handled = true;
6457  Symbol * op = 0;
6458 
6459  // is this an atomic multiply?
6460  if (i + 1 < input.size () && input[i + 1] == '=')
6461  {
6462  Variable * var = dynamic_cast <Variable *> (lastValidInput);
6463  ArrayRef * array_ref = dynamic_cast <ArrayRef *> (lastValidInput);
6464  if (var || array_ref)
6465  {
6466  op = new VariableMultiply (lastValidInput, madara::knowledge::KnowledgeRecord (),
6467  0, context);
6468  }
6469  else
6470  {
6472  "madara::expression::Interpreter: "
6473  "KARL COMPILE ERROR (*=): "
6474  "Assignments must have a variable left hand side.\n");
6475 
6476  throw KarlException ("madara::expression::Interpreter: "
6477  "KARL COMPILE ERROR (*=): "
6478  "Assignments must have a variable left hand side");
6479  }
6480  ++i;
6481  }
6482  // multiplication operation
6483  else
6484  op = new Multiply (context.get_logger ());
6485 
6486  // insert the op according to precedence relationships
6487  op->add_precedence (accumulated_precedence);
6488  lastValidInput = 0;
6489  precedence_insert (context, op, list);
6490  ++i;
6491  }
6492  else if (input[i] == '%')
6493  {
6494  // multiplication operation
6495  handled = true;
6496  Modulus *op = new Modulus (context.get_logger ());
6497 
6498  // insert the op according to precedence relationships
6499  op->add_precedence (accumulated_precedence);
6500  lastValidInput = 0;
6501  precedence_insert (context, op, list);
6502  ++i;
6503  }
6504  else if (input[i] == '/')
6505  {
6506  // is this a one line comment?
6507  if (i + 1 < input.size () && input[i + 1] == '/')
6508  {
6509  // we have a one line comment
6510  for (; i < input.size () && input[i] != '\n'; ++i);
6511  }
6512  // is this a multi-line comment?
6513  else if (i + 1 < input.size () && input[i + 1] == '*')
6514  {
6515  // find the matching close
6516  std::string::size_type found = input.find ("*/", i + 1);
6517 
6518  // if we were able to find the matching close,
6519  // then set i to the '/' in '*/'
6520  if (found != std::string::npos)
6521  i = found + 1;
6522 
6523  // otherwise, the user apparently wanted to
6524  // comment out the rest of the file
6525  else
6526  i = input.size ();
6527  }
6528  // is this an atomic decrement?
6529  else
6530  {
6531  handled = true;
6532  // division operation
6533  Symbol * op = 0;
6534 
6535  // atomic division?
6536  if (i + 1 < input.size () && input[i + 1] == '=')
6537  {
6538  Variable * var = dynamic_cast <Variable *> (lastValidInput);
6539  ArrayRef * array_ref = dynamic_cast <ArrayRef *> (lastValidInput);
6540  if (var || array_ref)
6541  {
6542  op = new VariableDivide (lastValidInput, madara::knowledge::KnowledgeRecord (), 0, context);
6543  }
6544  else
6545  {
6547  "madara::expression::Interpreter: "
6548  "KARL COMPILE ERROR (/=): "
6549  "Assignments must have a variable left hand side.\n");
6550 
6551  throw KarlException ("madara::expression::Interpreter: "
6552  "KARL COMPILE ERROR (/=): "
6553  "Assignments must have a variable left hand side");
6554  }
6555  ++i;
6556  }
6557  else
6558  op = new Divide (context.get_logger ());
6559 
6560  op->add_precedence (accumulated_precedence);
6561  lastValidInput = 0;
6562  precedence_insert (context, op, list);
6563  }
6564  ++i;
6565  }
6566  else if (input[i] == '=')
6567  {
6568  handled = true;
6569  Symbol * op = 0;
6570 
6571  // is this an equality?
6572  if (i + 1 < input.size () && input[i + 1] == '=')
6573  {
6574  op = new Equality (context.get_logger ());
6575  op->add_precedence (accumulated_precedence);
6576 
6577  lastValidInput = 0;
6578  ++i;
6579 
6580  // insert the op according to precedence relationships
6581  precedence_insert (context, op, list);
6582  }
6583  // is this an implication?
6584  else if (i + 1 < input.size () && input[i + 1] == '>')
6585  {
6586  op = new Implies (context.get_logger ());
6587  op->add_precedence (accumulated_precedence);
6588 
6589  lastValidInput = 0;
6590  ++i;
6591 
6592  // insert the op according to precedence relationships
6593  precedence_insert (context, op, list);
6594  }
6595  // must be an assignment then
6596  else
6597  {
6598  op = new Assignment (context.get_logger ());
6599  op->add_precedence (accumulated_precedence);
6600 
6601  lastValidInput = 0;
6602 
6603  // insert the op according to precedence relationships
6604  // assignment_insert (op, list);
6605  precedence_insert (context, op, list);
6606  }
6607  ++i;
6608  }
6609  else if (input[i] == '!')
6610  {
6611  handled = true;
6612  Symbol * op = 0;
6613 
6614  // is this an inequality?
6615  if (i + 1 < input.size () && input[i + 1] == '=')
6616  {
6617  op = new Inequality (context.get_logger ());
6618  ++i;
6619  }
6620  // must be a logical not then
6621  else
6622  {
6623  op = new Not (context.get_logger ());
6624  }
6625 
6626  // insert the op according to precedence relationships
6627  op->add_precedence (accumulated_precedence);
6628  lastValidInput = 0;
6629  precedence_insert (context, op, list);
6630  ++i;
6631  }
6632  // square root is ASCII 251 (UTF 8 format)
6633  else if ((uint8_t)input[i] == 251)
6634  {
6635  handled = true;
6636  Symbol * op = 0;
6637 
6638  op = new SquareRootUnary (context.get_logger ());
6639 
6640  // insert the op according to precedence relationships
6641  op->add_precedence (accumulated_precedence);
6642  lastValidInput = 0;
6643  precedence_insert (context, op, list);
6644  ++i;
6645  }
6646  else if (input[i] == '&')
6647  {
6648  // is this a logical and?
6649  if (i + 1 < input.size () && input[i + 1] == '&')
6650  {
6651  handled = true;
6652  Symbol * op = new And (context.get_logger ());
6653  ++i;
6654 
6655  // insert the op according to precedence relationships
6656  op->add_precedence (accumulated_precedence);
6657  lastValidInput = 0;
6658  precedence_insert (context, op, list);
6659  }
6660  else
6661  {
6662  // error. We currently don't allow logical and (A & B)
6664  "madara::expression::Interpreter: "
6665  "KARL COMPILE ERROR: "
6666  "Logical And (&) not available. " \
6667  "You may want to use && instead in %s.\n", input.c_str ());
6668 
6669  throw KarlException ("madara::expression::Interpreter: "
6670  "KARL COMPILE ERROR: "
6671  "Logical And (&) not available.");
6672  }
6673  ++i;
6674  }
6675  else if (input[i] == '|')
6676  {
6677  // is this a logical and?
6678  if (i + 1 < input.size () && input[i + 1] == '|')
6679  {
6680  handled = true;
6681  Symbol * op = new Or (context.get_logger ());
6682  ++i;
6683 
6684  // insert the op according to precedence relationships
6685  op->add_precedence (accumulated_precedence);
6686  lastValidInput = 0;
6687  precedence_insert (context, op, list);
6688  }
6689  else
6690  {
6691  // error. We don't currently support logical or
6693  "KARL COMPILE ERROR: "
6694  "Logical Or (|) not available. " \
6695  "You may want to use || instead in %s.\n", input.c_str ());
6696 
6697  throw KarlException ("madara::expression::Interpreter: "
6698  "KARL COMPILE ERROR: "
6699  "Logical Or (|) not available.");
6700  }
6701  ++i;
6702  }
6703  else if (input[i] == ';')
6704  {
6705  handled = true;
6706  Symbol * op = 0;
6707 
6708  // is this a logical and?
6709  if (i + 1 < input.size () && input[i + 1] == '>')
6710  {
6711  op = new ReturnRight (context.get_logger ());
6712  ++i;
6713  }
6714  else
6715  {
6716  op = new Both (context.get_logger ());
6717  }
6718 
6719  // insert the op according to precedence relationships
6720  op->add_precedence (accumulated_precedence);
6721  lastValidInput = 0;
6722  precedence_insert (context, op, list);
6723  ++i;
6724  }
6725  else if (input[i] == ',')
6726  {
6727  if (build_argument_list)
6728  return;
6729 
6730  handled = true;
6731  Symbol * op = new Sequence (context.get_logger ());
6732 
6733  // insert the op according to precedence relationships
6734  op->add_precedence (accumulated_precedence);
6735  lastValidInput = 0;
6736  precedence_insert (context, op, list);
6737  ++i;
6738  }
6739  else if (input[i] == '<')
6740  {
6741  handled = true;
6742  Symbol * op = 0;
6743 
6744  // is this a less than or equal to operator?
6745  if (i + 1 < input.size () && input[i + 1] == '=')
6746  {
6747  op = new LessThanEqual (context.get_logger ());
6748  ++i;
6749  }
6750  // must be a less than operator
6751  else
6752  op = new LessThan (context.get_logger ());
6753 
6754  // insert the op according to precedence relationships
6755  op->add_precedence (accumulated_precedence);
6756  lastValidInput = 0;
6757  precedence_insert (context, op, list);
6758  ++i;
6759  }
6760  else if (input[i] == '>')
6761  {
6762  handled = true;
6763  Symbol * op = 0;
6764 
6765  // is this a less than or equal to operator?
6766  if (i + 1 < input.size () && input[i + 1] == '=')
6767  {
6768  op = new GreaterThanEqual (context.get_logger ());
6769  ++i;
6770  }
6771  // must be a less than operator
6772  else
6773  op = new GreaterThan (context.get_logger ());
6774 
6775  // insert the op according to precedence relationships
6776  op->add_precedence (accumulated_precedence);
6777  lastValidInput = 0;
6778  precedence_insert (context, op, list);
6779  ++i;
6780  }
6781  else if (input[i] == '(')
6782  {
6783  handled = true;
6784  ++i;
6785  handle_parenthesis (context, input, i, lastValidInput,
6786  handled, accumulated_precedence, list);
6787  }
6788  else if (input[i] == '\t' || input[i] == ' '
6789  || input[i] == '\r' || input[i] == '\n')
6790  {
6791  handled = true;
6792  ++i;
6793  // skip whitespace
6794  }
6795 }
6796 
6797 
6798 void
6801 const std::string &input, std::string::size_type &i,
6802 madara::expression::Symbol *& lastValidInput,
6803 bool & handled, int & accumulated_precedence,
6804 ::std::list<madara::expression::Symbol *>& master_list)
6805 {
6806  /* handle parenthesis is a lot like handling a new interpret.
6807  the difference is that we have to worry about how the calling
6808  function has its list setup */
6809 
6810  accumulated_precedence += PARENTHESIS_PRECEDENCE;
6811  int initial_precedence = accumulated_precedence;
6812 
6813  ::std::list<Symbol *> list;
6814 
6815  handled = false;
6816  bool closed = false;
6817  while (i < input.length ())
6818  {
6819  main_loop (context, input, i, lastValidInput,
6820  handled, accumulated_precedence, list, true);
6821 
6822  if (input[i] == ']')
6823  {
6824  handled = true;
6825  closed = true;
6826  ++i;
6827  accumulated_precedence -= PARENTHESIS_PRECEDENCE;
6828  break;
6829  }
6830  else if (input[i] == ',')
6831  {
6832  ++i;
6833  while (list.size ())
6834  {
6835  master_list.push_back (list.back ());
6836  list.pop_back ();
6837  }
6838  accumulated_precedence = initial_precedence;
6839  }
6840  else if (i == input.length () - 1)
6841  {
6842  break;
6843  }
6844  }
6845 
6846  if (!closed)
6847  {
6849  "madara::expression::Interpreter: "
6850  "KARL COMPILE ERROR: "
6851  "Forgot to close parenthesis in %s.\n", input.c_str ());
6852  }
6853 
6854  if (list.size () > 0)
6855  {
6856  if (list.size () > 1)
6857  {
6859  "madara::expression::Interpreter: "
6860  "KARL COMPILE ERROR: "
6861  "A parenthesis was closed, leaving multiple list items (there should "
6862  "be a max of 1) in %s.\n", input.c_str ());
6863  }
6864 
6865  while (list.size ())
6866  {
6867  master_list.push_back (list.back ());
6868  list.pop_back ();
6869  }
6870  }
6871 
6872  list.clear ();
6873 }
6874 
6875 
6876 
6877 void
6880  const std::string &input, std::string::size_type &i,
6881  madara::expression::Symbol *& lastValidInput,
6882  bool & handled, int & accumulated_precedence,
6883  ::std::list<madara::expression::Symbol *>& master_list,
6884  bool build_argument_list)
6885 {
6886  /* handle parenthesis is a lot like handling a new interpret.
6887  the difference is that we have to worry about how the calling
6888  function has its list setup */
6889 
6890  accumulated_precedence += PARENTHESIS_PRECEDENCE;
6891  int initial_precedence = accumulated_precedence;
6892 
6893  ::std::list<Symbol *> list;
6894 
6895  handled = false;
6896  bool closed = false;
6897  while (i < input.length ())
6898  {
6899  main_loop (context, input, i, lastValidInput,
6900  handled, accumulated_precedence, list, build_argument_list);
6901 
6902  if (input[i] == ')')
6903  {
6904  handled = true;
6905  closed = true;
6906  ++i;
6907  accumulated_precedence -= PARENTHESIS_PRECEDENCE;
6908  break;
6909  }
6910  else if (build_argument_list && input[i] == ',')
6911  {
6912  ++i;
6913  while (list.size ())
6914  {
6915  master_list.push_back (list.back ());
6916  list.pop_back ();
6917  }
6918  accumulated_precedence = initial_precedence;
6919  }
6920  else if (i == input.length () - 1)
6921  {
6922  break;
6923  }
6924  }
6925 
6926  if (!build_argument_list && !closed)
6927  {
6929  "madara::expression::Interpreter: "
6930  "KARL COMPILE ERROR: "
6931  "Forgot to close parenthesis in %s.\n", input.c_str ());
6932  }
6933 
6934  if (!build_argument_list && master_list.size () > 0 && list.size () > 0)
6935  {
6936  Symbol * lastSymbol = master_list.back ();
6937  Operator * op = dynamic_cast <Operator *> (lastSymbol);
6938  UnaryOperator * unary = dynamic_cast < UnaryOperator * >
6939  (lastSymbol);
6940 
6941 
6942  // is it a node with 2 children?
6943  if (op || unary)
6944  {
6945  precedence_insert (context, list.back (), master_list);
6946  }
6947  else
6948  {
6949  // is it a terminal node (Number)
6950  // error
6951  }
6952  }
6953  else if (list.size () > 0)
6954  {
6955  if (list.size () > 1)
6956  {
6958  "madara::expression::Interpreter: "
6959  "KARL COMPILE ERROR: "
6960  "A parenthesis was closed, leaving multiple list items (there should "
6961  "be a max of 1) in %s.\n", input.c_str ());
6962  }
6963 
6964  while (list.size ())
6965  {
6966  master_list.push_back (list.back ());
6967  list.pop_back ();
6968  }
6969  }
6970 
6971  list.clear ();
6972 }
6973 
6974 // converts a string and context into a parse tree, and builds an
6975 // expression tree out of the parse tree
6979  const std::string &input)
6980 {
6981  // return the cached expression tree if it exists
6982  ExpressionTreeMap::const_iterator found = cache_.find (input);
6983  if (found != cache_.end ())
6984  return found->second;
6985 
6986  ::std::list<Symbol *> list;
6987  //list.clear ();
6988  Symbol * lastValidInput = 0;
6989  bool handled = false;
6990  int accumulated_precedence = 0;
6991  std::string::size_type last_i = 0;
6992 
6993  for (std::string::size_type i = 0;
6994  i < input.length ();)
6995  {
6996  // we took out the loop update from the for loop
6997  // and the main_loop or handle_parenthesis call
6998  // should now take care of this.
6999  main_loop (context, input, i, lastValidInput,
7000  handled, accumulated_precedence, list);
7001 
7002  if (i == last_i)
7003  {
7004  size_t start = i > 10 ? i - 10 : 0;
7005  size_t end = input.size () - i > 10 ? i + 10 : input.size ();
7006 
7007  std::string snippet = input.substr (start, end - start);
7008 
7009  {
7011  "madara::expression::Interpreter: "
7012  "KARL: "
7013  "Compilation is spinning at %d in %s. Char is %c. Breaking out.\n",
7014  (int)i, snippet.c_str (), input[i]);
7015  }
7016  break;
7017  }
7018  else
7019  last_i = i;
7020 
7021  // store last valid input symbol. this is useful to the '-' operator
7022  // and will help us determine if '-' is a subtraction or a negation
7023  //if (input[i] != ' ' && input[i] != '\n')
7024  // lastValidInput = input[i];
7025  }
7026 
7027  // if the list has an element in it, then return the back of the list.
7028  if (!list.empty ())
7029  {
7030  // Invoke a recursive ExpressionTree build starting with the root
7031  // symbol. This is an example of the builder pattern. See pg 97
7032  // in GoF book.
7033 
7034  ExpressionTree tree (context.get_logger (),
7035  list.back ()->build (), false);
7036 
7037  // optimize the tree
7038  tree.prune ();
7039  delete list.back ();
7040 
7041  // store this optimized tree into cached memory
7042  cache_[input] = tree;
7043 
7044  return tree;
7045  }
7046 
7047  // If we reach this, we didn't have any symbols.
7048  return ExpressionTree (context.get_logger ());
7049 }
7050 
7051 #endif // _MADARA_NO_KARL_
7052 
7053 #endif // _INTERPRETER_CPP_
Calculates a base term taken to a power.
Definition: SystemCallPow.h:24
This class encapsulates an entry in a KnowledgeBase.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ~ReturnRight(void)
destructor
virtual ~Preincrement(void)
destructor
madara::knowledge::ThreadSafeContext & context_
Context for variables.
VariableDecrement(Symbol *lhs, madara::knowledge::KnowledgeRecord value, Symbol *rhs, madara::knowledge::ThreadSafeContext &context)
constructors
ExpressionTree interpret(madara::knowledge::ThreadSafeContext &context, const std::string &input)
Compiles an expression into an expression tree.
TernaryOperator(logger::Logger &logger, Symbol *left, Symbol *right, int precedence_=1)
constructor
virtual ~Assignment(void)
destructor
virtual ~VariableDivide(void)
destructor
Sets the system clock or a variable clock.
virtual ~Symbol(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
ToString(madara::knowledge::ThreadSafeContext &context_)
constructor
Fragment(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual ~Not(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Postincrement node of the parse tree.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ~ExpandEnv(void)
destructor
Returns the square root of a term.
virtual ~LessThan(void)
destructor
virtual ~Or(void)
destructor
std::vector< Symbol * > Symbols
Returns the time in nanoseconds since epoch.
Evaluates both left and right children, regardless of values.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
ToHostDirs(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ~Isinf(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
WriteFile(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Equality(logger::Logger &logger)
constructor
Returns the type of a specified knowledge record.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Composite node that divides a variable by some right hand side.
Sleeps for a certain amount of time.
Returns a double array.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Returns the cosine of a term (radians)
Function node of the parse tree.
Defines a terminal node of that references the current value stored in a variable.
Definition: VariableNode.h:28
Returns an integer.
Leaf node of parse tree.
A composite node that increments a right expression.
virtual ~ClearVariable(void)
destructor
Returns the cosine of a term in radians.
Definition: SystemCallCos.h:24
Returns whether the first argument is an infinite number.
Sets the output format to use std::scientific.
virtual ~UnaryOperator(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ~Modulus(void)
destructorm
Converts an argument to an array of doubles.
Type(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual ~Size(void)
destructor
Defines a terminal node of that references the current value stored in a variable.
VariableMultiply(Symbol *lhs, madara::knowledge::KnowledgeRecord value, Symbol *rhs, madara::knowledge::ThreadSafeContext &context)
constructors
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Check and left and right arguments for equality.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Division node of the parse tree.
madara::knowledge::ThreadSafeContext & context_
Context for variables.
virtual ~WriteFile(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
A composite node that encompasses addition of two expressions.
Expands a statement, e.g.
Encapsulates a MADARA KaRL expression into an evaluatable tree.
virtual ~ToIntegers(void)
destructor
Abstract base class for operators with 3+ potential subnodes.
A composite node that compares left and right children for inequality.
GetClock(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Check and left and right arguments for less than or equal to.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
SquareRootUnary(logger::Logger &logger)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Check and left and right arguments for less than.
virtual ~ToInteger(void)
destructor
Addition node of the parse tree.
Print(madara::knowledge::ThreadSafeContext &context_)
constructor
Returns a version that has a directory structure appropriate to the OS.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
List(madara::knowledge::ThreadSafeContext &context)
constructors
ForLoop(Symbol *precondition, Symbol *condition, Symbol *postcondition, Symbol *body, madara::knowledge::ThreadSafeContext &context)
constructor
And(logger::Logger &logger)
constructor
virtual ~Equality(void)
destructor
std::deque< ComponentNode * > ComponentNodes
a vector of Component Nodes
Composite node that subtracts a variable by some right hand side.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
A composite node that encompasses subtraction of a right expression from a left expression.
Cos(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Assign the value of an expression to a variable.
A composite node that iterates until a condition is met.
A composite node that divides a left expression by a right expression and returns the remainder of th...
virtual ~SquareRootUnary(void)
destructor
A composite node that compares left and right expressions for greater than or equal to...
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Generates a random double.
A composite node that evaluates both left and right expressions regardless of their evaluations...
A composite node that compares left and right children for less than or equal to. ...
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ~Sleep(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Converts an argument to a string.
Postincrement(logger::Logger &logger)
constructor
Returns the expansion of a statement.
virtual ~GetTime(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
A composite node that multiplies a left expression by a right expression.
RandDouble(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual ~VariableMultiply(void)
destructor
A composite node that evaluates both left and right expressions regardless of their evaluations...
A composite node that takes the square root of a term.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ~Both(void)
destructor
virtual ~Fragment(void)
destructor
virtual ~ExpandStatement(void)
destructor
virtual ~SystemCall(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Modulus node of the parse tree (10 % 4 == 2)
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
A composite node that decrements a left expression.
virtual ~ToDoubles(void)
destructor
Check and left and right arguments for inequality.
Returns the sin of a term in radians.
Definition: SystemCallSin.h:24
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
A composite node that performs an implication (inference rule)
A composite node that decrements a right expression.
Reads or sets the MADARA log level.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Sets the output format to std::fixed.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
This class stores variables and their values for use by any entity needing state information in a thr...
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
ArrayRef(const std::string &key, Symbol *index, madara::knowledge::ThreadSafeContext &context)
constructors
madara::knowledge::KnowledgeRecord value_
value can be faster than rhs_, so use it if possible
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
void precedence_insert(madara::knowledge::ThreadSafeContext &context, Symbol *op,::std::list< Symbol * > &list)
Inserts a mathematical operator into the tree.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Returns the clock of the argument or the system clock.
GetTime(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Returns a fragment of the knowledge record.
madara::knowledge::KnowledgeRecord prune(void)
Prunes the expression tree of unnecessary nodes.
Prints a Knowledge Record to the stderr.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
void main_loop(madara::knowledge::ThreadSafeContext &context, const std::string &input, std::string::size_type &i, Symbol *&lastValidInput, bool &handled, int &accumulated_precedence,::std::list< Symbol * > &list, bool build_argument_list=false)
Inserts a variable into the tree.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
A composite node that evaluates both left and right expressions regardless of their evaluations...
Number(logger::Logger &logger, std::string input)
constructors
Postdecrement(logger::Logger &logger)
constructor
VariableCompare(Symbol *lhs, madara::knowledge::KnowledgeRecord value, Symbol *rhs, int compare_type, madara::knowledge::ThreadSafeContext &context)
constructors
virtual ~GreaterThan(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ~SetClock(void)
destructor
A composite node that calls a function.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Defines a node that contains a madara::knowledge::KnowledgeRecord::Integer value. ...
Definition: LeafNode.h:23
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Provides knowledge logging services to files and terminals.
Definition: GlobalLogger.h:11
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ~Power(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ~DeleteVariable(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
madara::knowledge::ThreadSafeContext & context_
#define madara_logger_log(logger, level,...)
Fast version of the madara::logger::log method.
Definition: Logger.h:20
Writes a knowledge record to an user-specified file name.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Converts an argument into an unsigned char buffer.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ~VariableDecrement(void)
destructor
Returns the type of a specified knowledge record.
Returns a base term taken to a power (exponent)
Operator(logger::Logger &logger, Symbol *left, Symbol *right, int precedence_=1)
constructor
virtual ~Eval(void)
destructor
VariableIncrement(Symbol *lhs, madara::knowledge::KnowledgeRecord value, Symbol *rhs, madara::knowledge::ThreadSafeContext &context)
constructors
GreaterThanEqual(logger::Logger &logger)
constructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Predecrement(logger::Logger &logger)
constructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Multiply(logger::Logger &logger)
constructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Postdecrement node of the parse tree.
Divide a variable by a certain amount.
SetScientific(madara::knowledge::ThreadSafeContext &context_)
constructor
Abstract base class for all parse tree node operators.
madara::knowledge::KnowledgeRecord value_
value can be faster than rhs_, so use it if possible
Sets or returns the current MADARA logging level.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ~SetFixed(void)
destructor
Sequence(logger::Logger &logger)
constructor
Returns the size of a specified knowledge record.
virtual ~SetPrecision(void)
destructor
Returns the tangent of a term (radians)
SquareRoot(madara::knowledge::ThreadSafeContext &context_)
constructor
LessThan(logger::Logger &logger)
constructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
A multi-threaded logger for logging to one or more destinations.
Definition: Logger.h:88
virtual ~SquareRoot(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
void set_value(const KnowledgeRecord &new_value)
Sets the value from another KnowledgeRecord, does not copy clock and write_quality.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Power(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
A composite node that performs a logical and.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Returns the size of a record.
virtual ~ToBuffer(void)
destructor
Returns the expansion of a statement with environment vars.
virtual ~ToHostDirs(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ~Sequence(void)
destructor
virtual ~ForLoop(void)
destructor
Evaluates both left and right children, regardless of values.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
GreaterThan(logger::Logger &logger)
constructor
SetPrecision(madara::knowledge::ThreadSafeContext &context_)
constructor
Predecrement node of the parse tree.
Converts an argument to an array of integers.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Or(logger::Logger &logger)
constructor
void number_insert(madara::knowledge::ThreadSafeContext &context, const std::string &input, std::string::size_type &i, int &accumulated_precedence,::std::list< Symbol * > &list, Symbol *&lastValidInput)
Inserts a number into the tree.
void string_insert(char opener, madara::knowledge::ThreadSafeContext &context, const std::string &input, std::string::size_type &i, int &accumulated_precedence,::std::list< Symbol * > &list, Symbol *&lastValidInput)
Inserts a variable into the tree.
Fragment the Knowledge Record.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Sets the system or a variable clock.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ~RandDouble(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
static struct madara::knowledge::tags::string_t string
virtual ~Number(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Returns the square root of a term.
Composite node that multiplies a variable by some right hand side.
Sleep(madara::knowledge::ThreadSafeContext &context_)
constructor
Symbol(logger::Logger &logger, Symbol *left, Symbol *right, int precedence_=0)
constructor
virtual ComponentNode * build(void)=0
abstract method for building an Expression ExpressionTree Node
virtual ~TernaryOperator(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Leaf node of parse tree.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Check and left and right arguments for greater than.
int compare_type_
type of comparison. See madara/Globals.h
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
ReturnRight(logger::Logger &logger)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
A composite node that compares left and right expressions for equality.
Returns the current time in seconds since epoch.
Subtract(logger::Logger &logger)
constructor
virtual ~GetTimeSeconds(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Symbol * rhs_
rhs is used for complex rhs types (not a simple number)
Divide(logger::Logger &logger)
constructor
#define madara_logger_ptr_log(logger, level,...)
Fast version of the madara::logger::log method for Logger pointers.
Definition: Logger.h:32
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Preincrement(logger::Logger &logger)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
madara::knowledge::ThreadSafeContext & context_
A composite node that increments a right expression.
Converts an argument to a double.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
const std::string key_
Key for retrieving value of this variable.
Evaluates a knowledge::KnowledgeRecord and returns the evaluation result.
Sleeps for a certain amount of time.
ClearVariable(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
SystemCall(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ~ArrayRef(void)
destructor
Abstract base class of all parse tree nodes.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ~PrintSystemCalls(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Both(logger::Logger &logger)
constructor
Sets the double precision for converting doubles to a string and for printing.
ToDoubles(madara::knowledge::ThreadSafeContext &context_)
constructor
Negate node of the parse tree.
virtual ~ToDouble(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Isinf(madara::knowledge::ThreadSafeContext &context_)
constructor
Modulus(logger::Logger &logger)
constructor
virtual ~GetClock(void)
destructor
A composite node that logically nots a right expression.
A composite node that allows for variable assignment.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
A composite node that compares left and right children for greater than.
Returns the system clock or a variable clock.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Returns the type of a record.
ToBuffer(madara::knowledge::ThreadSafeContext &context_)
constructor
logger::Logger * logger_
left and right pointers
Tan(madara::knowledge::ThreadSafeContext &context_)
constructor
Returns the wall clock time in seconds.
Add(logger::Logger &logger)
constructor
Assign the value of an expression to a variable.
madara::knowledge::KnowledgeRecord::Integer Integer
Definition: Interpreter.cpp:87
madara::knowledge::ThreadSafeContext & context_
virtual ~ReadFile(void)
destructor
virtual ~Function(void)
destructor
An abstract base class defines a simple abstract implementation of an expression tree node...
Definition: ComponentNode.h:36
virtual ~Variable(void)
destructor
void handle_parenthesis(madara::knowledge::ThreadSafeContext &context, const std::string &input, std::string::size_type &i, Symbol *&lastValidInput, bool &handled, int &accumulated_precedence,::std::list< Symbol * > &list, bool build_argument_list=false)
Handles a parenthesis.
Preincrement node of the parse tree.
ConstArray(madara::knowledge::ThreadSafeContext &context)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Returns the tangent of a term in radians.
Definition: SystemCallTan.h:24
Logically and node of the parse tree.
LessThanEqual(logger::Logger &logger)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
A composite node that integrally negates a right expression.
virtual ~Negate(void)
destructor
LogLevel(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Negate(logger::Logger &logger)
constructor
void system_call_insert(madara::knowledge::ThreadSafeContext &context, const std::string &input, std::string::size_type &i, int &accumulated_precedence,::std::list< Symbol * > &list, Symbol *&lastValidInput)
Inserts a system call into the tree.
virtual ~Postdecrement(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Returns the wall clock time.
A composite node that contains an array of values.
VariableDivide(Symbol *lhs, madara::knowledge::KnowledgeRecord value, Symbol *rhs, madara::knowledge::ThreadSafeContext &context)
constructors
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Implies(logger::Logger &logger)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ~Implies(void)
destructor
madara::knowledge::ThreadSafeContext & context_
Context for variables.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
madara::knowledge::ThreadSafeContext & context_
Context for variables.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
An exception for unrecoverable KaRL compilation issues.
Definition: KarlException.h:18
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
UnaryOperator(logger::Logger &logger, Symbol *right, int precedence_=1)
constructor
Eval(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Clears a variable in the knowledge base.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
madara::knowledge::ThreadSafeContext & context_
Context for variables.
Sets the precision of doubles.
Deletes a variable from the knowledge base.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Function(const std::string &name, madara::knowledge::ThreadSafeContext &context)
constructor
virtual ~RandInt(void)
destructor
virtual ~Subtract(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ~GreaterThanEqual(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
RandInt(madara::knowledge::ThreadSafeContext &context_)
constructor
Sets the output format to use std::fixed.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ~Postincrement(void)
destructor
Logically or node of the parse tree.
Abstract base class for operators with 3+ potential subnodes.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
SetClock(madara::knowledge::ThreadSafeContext &context_)
constructor
madara::knowledge::KnowledgeRecord value_
value can be faster than rhs_, so use it if possible
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
void handle_for_loop(madara::knowledge::ThreadSafeContext &context, std::string &variable, const std::string &input, std::string::size_type &i, int &accumulated_precedence,::std::list< Symbol * > &list, Symbol *&returnableInput)
extracts precondition, condition, postcondition, and body from input
ExpandEnv(madara::knowledge::ThreadSafeContext &context_)
constructor
Sin(madara::knowledge::ThreadSafeContext &context_)
constructor
Variable(const std::string &key, madara::knowledge::ThreadSafeContext &context)
constructors
Returns the sin of a term (radians)
void handle_array(madara::knowledge::ThreadSafeContext &context, const std::string &input, std::string::size_type &i, Symbol *&lastValidInput, bool &handled, int &accumulated_precedence,::std::list< Symbol * > &list)
Handles a parenthesis.
virtual ~Sin(void)
destructor
virtual ~ConstArray(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
A composite node that performs a logical or.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ~Cos(void)
destructor
DeleteVariable(madara::knowledge::ThreadSafeContext &context_)
constructor
Subtraction node of the parse tree.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ~Divide(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Increment a variable by a certain amount.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Assignment(logger::Logger &logger)
constructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Ensures the directory delimiters are appropriate for the host operating system (e.g., on Windows, &#39;\&#39; and Linux, &#39;/&#39;)
virtual ~Predecrement(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
Multiply a variable by a certain amount.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
madara::knowledge::KnowledgeRecord item_
contains the value of the leaf node
Reads a file from an user-provided file name.
Decrement a variable by a certain amount.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ~Add(void)
destructor
Size(madara::knowledge::ThreadSafeContext &context_)
constructor
A composite node that divides a left expression by a right one.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
ToIntegers(madara::knowledge::ThreadSafeContext &context_)
constructor
Evaluates a Knowledge Record and returns result.
virtual ~And(void)
destructor
Copyright (c) 2015 Carnegie Mellon University.
logger::Logger & get_logger(void) const
Gets the logger used for information printing.
virtual ~Tan(void)
destructor
Leaf node for an array reference.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Sets the output to std::scientific.
Logically not the right node.
SetFixed(madara::knowledge::ThreadSafeContext &context_)
constructor
Expands a statement, e.g.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Inequality(logger::Logger &logger)
constructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
madara::knowledge::KnowledgeRecord value_
value can be faster than rhs_, so use it if possible
Defines a terminal node of that references the current value stored in a variable.
madara::knowledge::ThreadSafeContext & context_
Context for variables.
ToInteger(madara::knowledge::ThreadSafeContext &context_)
constructor
const std::string key_
Key for retrieving value of this variable.
virtual ~Print(void)
destructor
Increment a variable by a certain amount.
virtual ~Inequality(void)
destructor
GetTimeSeconds(madara::knowledge::ThreadSafeContext &context_)
constructor
Generates a random integer.
ReadFile(madara::knowledge::ThreadSafeContext &context_)
constructor
std::string to_string(const std::string &delimiter=", ") const
converts the value to a string.
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
madara::knowledge::ThreadSafeContext & context_
Context for variables.
virtual ~LogLevel(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual ~VariableIncrement(void)
destructor
PrintSystemCalls(madara::knowledge::ThreadSafeContext &context_)
constructor
Evaluates both left and right children and returns right value.
virtual ~List(void)
destructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ~Multiply(void)
destructor
Not(logger::Logger &logger)
constructor
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Check and left and right arguments for greater than or equal to.
virtual ~Interpreter()
Destructor.
Prints a Knowledge Record.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ~SetScientific(void)
destructor
virtual ~ToString(void)
destructor
ExpandStatement(madara::knowledge::ThreadSafeContext &context_)
constructor
Converts an argument to an integer.
Defines a terminal node that contains a list.
Definition: ListNode.h:27
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
virtual int precedence(void)
abstract method for returning precedence level (higher value means higher precedence ...
ToDouble(madara::knowledge::ThreadSafeContext &context_)
constructor
virtual ~VariableCompare(void)
destructor
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Prints a help menu for all system calls.
virtual int add_precedence(int accumulated_precedence)=0
Defines a terminal node of that references the current value stored in a variable.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual int add_precedence(int accumulated_precedence)
returns the precedence level
Multiplication node of the parse tree.
virtual ~Type(void)
destructor
virtual ~LessThanEqual(void)
destructor
A composite node that compares left and right children for less than.
Abstract base class for all parse tree node operators.
madara::knowledge::ThreadSafeContext & context_
Context for variables.
madara::knowledge::ThreadSafeContext & context_
Context for variables.
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
virtual ~Operator(void)
destructor
A constant array that should not be changed.
Iterative looping node of the parse tree.
madara::knowledge::KnowledgeRecord value_
value can be faster than rhs_, so use it if possible
virtual ComponentNode * build(void)
builds an equivalent ExpressionTree node
void variable_insert(madara::knowledge::ThreadSafeContext &context, const std::string &input, std::string::size_type &i, int &accumulated_precedence,::std::list< Symbol * > &list, Symbol *&lastValidInput)
Inserts a variable into the tree.
Returns an integers.