MADARA  3.1.8
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 <iostream>
7 #include <sstream>
8 
83 
84 
85 namespace madara
86 {
87  namespace expression
88  {
89  enum
90  {
107  };
108 
113  class Symbol
114  {
115  public:
118  Symbol * left, Symbol * right, int precedence_ = 0);
119 
121  virtual ~Symbol (void);
122 
125  virtual int precedence (void)
126  {
127  return precedence_;
128  }
129 
130  virtual int add_precedence (int accumulated_precedence) = 0;
131 
133 
134  virtual ComponentNode * build (void) = 0;
135 
137 
142  };
143 
144  typedef std::vector <Symbol *> Symbols;
145 
151  class Operator : public Symbol
152  {
153  public:
156  Symbol * left, Symbol * right, int precedence_ = 1);
157 
159  virtual ~Operator (void);
160  };
161 
167  class TernaryOperator : public Operator
168  {
169  public:
172  Symbol * left, Symbol * right, int precedence_ = 1);
173 
175  virtual ~TernaryOperator (void);
176 
178  };
179 
186  {
187  public:
190 
192  virtual ~SystemCall (void);
193 
196  };
197 
202  class ClearVariable : public SystemCall
203  {
204  public:
206  ClearVariable (
208 
210  virtual int add_precedence (int accumulated_precedence);
211 
213  virtual ComponentNode * build (void);
214 
216  virtual ~ClearVariable (void);
217  };
218 
219 
224  class DeleteVariable : public SystemCall
225  {
226  public:
230 
232  virtual int add_precedence (int accumulated_precedence);
233 
235  virtual ComponentNode * build (void);
236 
238  virtual ~DeleteVariable (void);
239  };
240 
245  class Eval : public SystemCall
246  {
247  public:
250 
252  virtual int add_precedence (int accumulated_precedence);
253 
255  virtual ComponentNode * build (void);
256 
258  virtual ~Eval (void);
259  };
260 
265  class ExpandEnv : public SystemCall
266  {
267  public:
269  ExpandEnv (
271 
273  virtual int add_precedence (int accumulated_precedence);
274 
276  virtual ComponentNode * build (void);
277 
279  virtual ~ExpandEnv (void);
280  };
281 
287  {
288  public:
292 
294  virtual int add_precedence (int accumulated_precedence);
295 
297  virtual ComponentNode * build (void);
298 
300  virtual ~ExpandStatement (void);
301  };
302 
307  class Fragment : public SystemCall
308  {
309  public:
312 
314  virtual int add_precedence (int accumulated_precedence);
315 
317  virtual ComponentNode * build (void);
318 
320  virtual ~Fragment (void);
321  };
322 
327  class Print : public SystemCall
328  {
329  public:
332 
334  virtual int add_precedence (int accumulated_precedence);
335 
337  virtual ComponentNode * build (void);
338 
340  virtual ~Print (void);
341  };
342 
347  class Cos : public SystemCall
348  {
349  public:
351  Cos (
353 
355  virtual int add_precedence (int accumulated_precedence);
356 
358  virtual ComponentNode * build (void);
359 
361  virtual ~Cos (void);
362  };
363 
368  class Sin : public SystemCall
369  {
370  public:
372  Sin (
374 
376  virtual int add_precedence (int accumulated_precedence);
377 
379  virtual ComponentNode * build (void);
380 
382  virtual ~Sin (void);
383  };
384 
389  class Tan : public SystemCall
390  {
391  public:
393  Tan (
395 
397  virtual int add_precedence (int accumulated_precedence);
398 
400  virtual ComponentNode * build (void);
401 
403  virtual ~Tan (void);
404  };
405 
410  class Power : public SystemCall
411  {
412  public:
414  Power (
416 
418  virtual int add_precedence (int accumulated_precedence);
419 
421  virtual ComponentNode * build (void);
422 
424  virtual ~Power (void);
425  };
426 
431  class SquareRoot : public SystemCall
432  {
433  public:
435  SquareRoot (
437 
439  virtual int add_precedence (int accumulated_precedence);
440 
442  virtual ComponentNode * build (void);
443 
445  virtual ~SquareRoot (void);
446  };
447 
453  {
454  public:
458 
460  virtual int add_precedence (int accumulated_precedence);
461 
463  virtual ComponentNode * build (void);
464 
466  virtual ~PrintSystemCalls (void);
467  };
468 
473  class RandDouble : public SystemCall
474  {
475  public:
478 
480  virtual int add_precedence (int accumulated_precedence);
481 
483  virtual ComponentNode * build (void);
484 
486  virtual ~RandDouble (void);
487  };
488 
493  class RandInt : public SystemCall
494  {
495  public:
498 
500  virtual int add_precedence (int accumulated_precedence);
501 
503  virtual ComponentNode * build (void);
504 
506  virtual ~RandInt (void);
507  };
508 
513  class ReadFile : public SystemCall
514  {
515  public:
518 
520  virtual int add_precedence (int accumulated_precedence);
521 
523  virtual ComponentNode * build (void);
524 
526  virtual ~ReadFile (void);
527  };
528 
533  class WriteFile : public SystemCall
534  {
535  public:
538 
540  virtual int add_precedence (int accumulated_precedence);
541 
543  virtual ComponentNode * build (void);
544 
546  virtual ~WriteFile (void);
547  };
548 
553  class Size : public SystemCall
554  {
555  public:
558 
560  virtual int add_precedence (int accumulated_precedence);
561 
563  virtual ComponentNode * build (void);
564 
566  virtual ~Size (void);
567  };
568 
573  class SetFixed : public SystemCall
574  {
575  public:
578 
580  virtual int add_precedence (int accumulated_precedence);
581 
583  virtual ComponentNode * build (void);
584 
586  virtual ~SetFixed (void);
587  };
588 
593  class SetPrecision : public SystemCall
594  {
595  public:
598 
600  virtual int add_precedence (int accumulated_precedence);
601 
603  virtual ComponentNode * build (void);
604 
606  virtual ~SetPrecision (void);
607  };
608 
613  class SetScientific : public SystemCall
614  {
615  public:
618 
620  virtual int add_precedence (int accumulated_precedence);
621 
623  virtual ComponentNode * build (void);
624 
626  virtual ~SetScientific (void);
627  };
628 
633  class ToBuffer : public SystemCall
634  {
635  public:
638 
640  virtual int add_precedence (int accumulated_precedence);
641 
643  virtual ComponentNode * build (void);
644 
646  virtual ~ToBuffer (void);
647  };
648 
653  class ToDouble : public SystemCall
654  {
655  public:
658 
660  virtual int add_precedence (int accumulated_precedence);
661 
663  virtual ComponentNode * build (void);
664 
666  virtual ~ToDouble (void);
667  };
668 
673  class ToDoubles : public SystemCall
674  {
675  public:
678 
680  virtual int add_precedence (int accumulated_precedence);
681 
683  virtual ComponentNode * build (void);
684 
686  virtual ~ToDoubles (void);
687  };
688 
694  class ToHostDirs : public SystemCall
695  {
696  public:
699 
701  virtual int add_precedence (int accumulated_precedence);
702 
704  virtual ComponentNode * build (void);
705 
707  virtual ~ToHostDirs (void);
708  };
709 
714  class ToInteger : public SystemCall
715  {
716  public:
719 
721  virtual int add_precedence (int accumulated_precedence);
722 
724  virtual ComponentNode * build (void);
725 
727  virtual ~ToInteger (void);
728  };
729 
734  class ToIntegers : public SystemCall
735  {
736  public:
739 
741  virtual int add_precedence (int accumulated_precedence);
742 
744  virtual ComponentNode * build (void);
745 
747  virtual ~ToIntegers (void);
748  };
749 
754  class ToString : public SystemCall
755  {
756  public:
759 
761  virtual int add_precedence (int accumulated_precedence);
762 
764  virtual ComponentNode * build (void);
765 
767  virtual ~ToString (void);
768  };
769 
774  class Sleep : public SystemCall
775  {
776  public:
779 
781  virtual int add_precedence (int accumulated_precedence);
782 
784  virtual ComponentNode * build (void);
785 
787  virtual ~Sleep (void);
788  };
789 
794  class Type : public SystemCall
795  {
796  public:
799 
801  virtual int add_precedence (int accumulated_precedence);
802 
804  virtual ComponentNode * build (void);
805 
807  virtual ~Type (void);
808  };
809 
814  class LogLevel : public SystemCall
815  {
816  public:
819 
821  virtual int add_precedence (int accumulated_precedence);
822 
824  virtual ComponentNode * build (void);
825 
827  virtual ~LogLevel (void);
828  };
829 
834  class GetClock : public SystemCall
835  {
836  public:
839 
841  virtual int add_precedence (int accumulated_precedence);
842 
844  virtual ComponentNode * build (void);
845 
847  virtual ~GetClock (void);
848  };
849 
854  class GetTime : public SystemCall
855  {
856  public:
859 
861  virtual int add_precedence (int accumulated_precedence);
862 
864  virtual ComponentNode * build (void);
865 
867  virtual ~GetTime (void);
868  };
869 
874  class GetTimeSeconds : public SystemCall
875  {
876  public:
879 
881  virtual int add_precedence (int accumulated_precedence);
882 
884  virtual ComponentNode * build (void);
885 
887  virtual ~GetTimeSeconds (void);
888  };
889 
894  class SetClock : public SystemCall
895  {
896  public:
899 
901  virtual int add_precedence (int accumulated_precedence);
902 
904  virtual ComponentNode * build (void);
905 
907  virtual ~SetClock (void);
908  };
909 
910 
916  class UnaryOperator : public Symbol
917  {
918  public:
921  Symbol * right, int precedence_ = 1);
922 
924  virtual ~UnaryOperator (void);
925  };
926 
932  class Number : public Symbol
933  {
934  public:
938  Number (logger::Logger & logger, double input);
939 
941  virtual ~Number (void);
942 
944  //virtual int precedence (void);
945  virtual int add_precedence (int accumulated_precedence);
946 
948  virtual ComponentNode *build (void);
949  // private:
952  };
953 
958  class Variable : public Symbol
959  {
960  public:
962  Variable (const std::string & key,
964 
966  virtual ~Variable (void);
967 
969  //virtual int precedence (void);
970  virtual int add_precedence (int accumulated_precedence);
971 
973  virtual ComponentNode * build (void);
974  //private:
977 
980  };
981 
986  class ArrayRef : public Symbol
987  {
988  public:
990  ArrayRef (const std::string & key, Symbol * index,
992 
994  virtual ~ArrayRef (void);
995 
997  //virtual int precedence (void);
998  virtual int add_precedence (int accumulated_precedence);
999 
1001  virtual ComponentNode * build (void);
1002  //private:
1005 
1009  };
1010 
1017  {
1018  public:
1020  VariableDecrement (Symbol * lhs,
1022  Symbol * rhs,
1024 
1026  virtual ~VariableDecrement (void);
1027 
1029  //virtual int precedence (void);
1030  virtual int add_precedence (int accumulated_precedence);
1031 
1033  virtual ComponentNode *build (void);
1034  //private:
1036 
1039 
1042  };
1043 
1049  class VariableDivide : public Operator
1050  {
1051  public:
1053  VariableDivide (Symbol * lhs,
1055  Symbol * rhs,
1057 
1059  virtual ~VariableDivide (void);
1060 
1062  //virtual int precedence (void);
1063  virtual int add_precedence (int accumulated_precedence);
1064 
1066  virtual ComponentNode *build (void);
1067  //private:
1069 
1072 
1075  };
1076 
1083  {
1084  public:
1086  VariableIncrement (Symbol * lhs,
1088  Symbol * rhs,
1090 
1092  virtual ~VariableIncrement (void);
1093 
1095  //virtual int precedence (void);
1096  virtual int add_precedence (int accumulated_precedence);
1097 
1099  virtual ComponentNode *build (void);
1100  //private:
1102 
1105 
1108  };
1109 
1116  {
1117  public:
1119  VariableMultiply (Symbol * lhs,
1121  Symbol * rhs,
1123 
1125  virtual ~VariableMultiply (void);
1126 
1128  //virtual int precedence (void);
1129  virtual int add_precedence (int accumulated_precedence);
1130 
1132  virtual ComponentNode * build (void);
1133  //private:
1135 
1138 
1141  };
1142 
1148  class VariableCompare : public Symbol
1149  {
1150  public:
1152  VariableCompare (Symbol * lhs,
1154  Symbol * rhs, int compare_type,
1156 
1158  virtual ~VariableCompare (void);
1159 
1161  //virtual int precedence (void);
1162  virtual int add_precedence (int accumulated_precedence);
1163 
1165  virtual ComponentNode *build (void);
1166  //private:
1168 
1171 
1174 
1177 
1180  };
1181 
1182 
1188  class List : public Symbol
1189  {
1190  public:
1192  List (
1194 
1196  virtual ~List (void);
1197 
1199  //virtual int precedence (void);
1200  virtual int add_precedence (int accumulated_precedence);
1201 
1203  virtual ComponentNode * build (void);
1204  private:
1205 
1208  };
1209 
1215  class Subtract : public Operator
1216  {
1217  public:
1220 
1222  virtual ~Subtract (void);
1223 
1225  //virtual int precedence (void);
1226  virtual int add_precedence (int accumulated_precedence);
1227 
1229  virtual ComponentNode * build (void);
1230  };
1231 
1237  class Add : public TernaryOperator
1238  {
1239  public:
1242 
1244  virtual ~Add (void);
1245 
1247  virtual int add_precedence (int accumulated_precedence);
1248 
1250  virtual ComponentNode * build (void);
1251  };
1252 
1258  class And : public TernaryOperator
1259  {
1260  public:
1263 
1265  virtual ~And (void);
1266 
1268  //virtual int precedence (void);
1269  virtual int add_precedence (int accumulated_precedence);
1270 
1272  virtual ComponentNode * build (void);
1273  };
1274 
1280  class Or : public TernaryOperator
1281  {
1282  public:
1284  Or (logger::Logger & logger);
1285 
1287  virtual ~Or (void);
1288 
1290  //virtual int precedence (void);
1291  virtual int add_precedence (int accumulated_precedence);
1292 
1294  virtual ComponentNode * build (void);
1295  };
1296 
1302  class Both : public TernaryOperator
1303  {
1304  public:
1307 
1309  virtual ~Both (void);
1310 
1312  //virtual int precedence (void);
1313  virtual int add_precedence (int accumulated_precedence);
1314 
1316  virtual ComponentNode * build (void);
1317  };
1318 
1325  {
1326  public:
1329 
1331  virtual ~ReturnRight (void);
1332 
1334  virtual int add_precedence (int accumulated_precedence);
1335 
1337  virtual ComponentNode * build (void);
1338  };
1339 
1345  class Sequence : public TernaryOperator
1346  {
1347  public:
1350 
1352  virtual ~Sequence (void);
1353 
1355  //virtual int precedence (void);
1356  virtual int add_precedence (int accumulated_precedence);
1357 
1359  virtual ComponentNode * build (void);
1360  };
1361 
1367  class Implies : public Operator
1368  {
1369  public:
1372 
1374  virtual ~Implies (void);
1375 
1377  //virtual int precedence (void);
1378  virtual int add_precedence (int accumulated_precedence);
1379 
1381  virtual ComponentNode * build (void);
1382  };
1383 
1389  class Assignment : public Operator
1390  {
1391  public:
1394 
1396  virtual ~Assignment (void);
1397 
1399  //virtual int precedence (void);
1400  virtual int add_precedence (int accumulated_precedence);
1401 
1403  virtual ComponentNode * build (void);
1404  };
1405 
1411  class Equality : public Operator
1412  {
1413  public:
1416 
1418  virtual ~Equality (void);
1419 
1421  //virtual int precedence (void);
1422  virtual int add_precedence (int accumulated_precedence);
1423 
1425  virtual ComponentNode * build (void);
1426  };
1427 
1433  class Inequality : public Operator
1434  {
1435  public:
1438 
1440  virtual ~Inequality (void);
1441 
1443  //virtual int precedence (void);
1444  virtual int add_precedence (int accumulated_precedence);
1445 
1447  virtual ComponentNode * build (void);
1448  };
1449 
1456  {
1457  public:
1460 
1462  virtual ~GreaterThanEqual (void);
1463 
1465  //virtual int precedence (void);
1466  virtual int add_precedence (int accumulated_precedence);
1467 
1469  virtual ComponentNode * build (void);
1470  };
1471 
1477  class GreaterThan : public Operator
1478  {
1479  public:
1482 
1484  virtual ~GreaterThan (void);
1485 
1487  //virtual int precedence (void);
1488  virtual int add_precedence (int accumulated_precedence);
1489 
1491  virtual ComponentNode * build (void);
1492  };
1493 
1499  class LessThanEqual : public Operator
1500  {
1501  public:
1504 
1506  virtual ~LessThanEqual (void);
1507 
1509  //virtual int precedence (void);
1510  virtual int add_precedence (int accumulated_precedence);
1511 
1513  virtual ComponentNode * build (void);
1514  };
1515 
1521  class LessThan : public Operator
1522  {
1523  public:
1526 
1528  virtual ~LessThan (void);
1529 
1531  //virtual int precedence (void);
1532  virtual int add_precedence (int accumulated_precedence);
1533 
1535  virtual ComponentNode * build (void);
1536  };
1537 
1543  class Function : public TernaryOperator
1544  {
1545  public:
1547  Function (const std::string & name,
1549 
1551  virtual ~Function (void);
1552 
1554  //virtual int precedence (void);
1555  virtual int add_precedence (int accumulated_precedence);
1556 
1558  virtual ComponentNode * build (void);
1559 
1562  };
1563 
1570  {
1571  public:
1573  ConstArray (
1575 
1577  virtual ~ConstArray (void);
1578 
1580  //virtual int precedence (void);
1581  virtual int add_precedence (int accumulated_precedence);
1582 
1584  virtual ComponentNode *build (void);
1585 
1587  };
1588 
1594  class ForLoop : public UnaryOperator
1595  {
1596  public:
1598  ForLoop (Symbol * precondition, Symbol * condition,
1599  Symbol * postcondition, Symbol * body,
1601 
1603  virtual ~ForLoop (void);
1604 
1606  //virtual int precedence (void);
1607  virtual int add_precedence (int accumulated_precedence);
1608 
1610  virtual ComponentNode *build (void);
1611 
1617  };
1618 
1625  {
1626  public:
1629 
1631  virtual ~SquareRootUnary (void);
1632 
1634  //virtual int precedence (void);
1635  virtual int add_precedence (int accumulated_precedence);
1636 
1638  virtual ComponentNode * build (void);
1639  };
1640 
1646  class Negate : public UnaryOperator
1647  {
1648  public:
1651 
1653  virtual ~Negate (void);
1654 
1656  //virtual int precedence (void);
1657  virtual int add_precedence (int accumulated_precedence);
1658 
1660  virtual ComponentNode * build (void);
1661  };
1662 
1669  {
1670  public:
1673 
1675  virtual ~Postdecrement (void);
1676 
1678  //virtual int precedence (void);
1679  virtual int add_precedence (int accumulated_precedence);
1680 
1682  virtual ComponentNode * build (void);
1683  };
1684 
1691  {
1692  public:
1695 
1697  virtual ~Postincrement (void);
1698 
1700  //virtual int precedence (void);
1701  virtual int add_precedence (int accumulated_precedence);
1702 
1704  virtual ComponentNode * build (void);
1705  };
1706 
1713  {
1714  public:
1717 
1719  virtual ~Predecrement (void);
1720 
1722  //virtual int precedence (void);
1723  virtual int add_precedence (int accumulated_precedence);
1724 
1726  virtual ComponentNode * build (void);
1727  };
1728 
1735  {
1736  public:
1739 
1741  virtual ~Preincrement (void);
1742 
1744  //virtual int precedence (void);
1745  virtual int add_precedence (int accumulated_precedence);
1746 
1748  virtual ComponentNode * build (void);
1749  };
1750 
1756  class Not : public UnaryOperator
1757  {
1758  public:
1761 
1763  virtual ~Not (void);
1764 
1766  //virtual int precedence (void);
1767  virtual int add_precedence (int accumulated_precedence);
1768 
1770  virtual ComponentNode * build (void);
1771  };
1772 
1778  class Multiply : public TernaryOperator
1779  {
1780  public:
1783 
1785  virtual ~Multiply (void);
1786 
1788  //virtual int precedence (void);
1789  virtual int add_precedence (int accumulated_precedence);
1790 
1792  virtual ComponentNode * build (void);
1793  };
1794 
1800  class Modulus : public Operator
1801  {
1802  public:
1805 
1807  virtual ~Modulus (void);
1808 
1810  //virtual int precedence (void);
1811  virtual int add_precedence (int accumulated_precedence);
1812 
1814  virtual ComponentNode * build (void);
1815  };
1816 
1822  class Divide : public Operator
1823  {
1824  public:
1827 
1829  virtual ~Divide (void);
1830 
1832  //virtual int precedence (void);
1833  virtual int add_precedence (int accumulated_precedence);
1834 
1836  virtual ComponentNode * build (void);
1837  };
1838 
1839  }
1840 }
1841 
1842 // constructor
1847  : logger_ (&logger), left_ (left), right_ (right), precedence_ (precedence)
1848 {
1849 }
1850 
1851 // destructor
1853 {
1854  delete left_;
1855  delete right_;
1856 }
1857 
1858 // constructor
1860  Symbol * left, Symbol * right, int precedence)
1861  : Symbol (logger, left, right, precedence)
1862 {
1863 }
1864 
1865 // destructor
1867 {
1868 }
1869 
1870 // constructor
1872  Symbol * left, Symbol * right, int precedence)
1873  : Operator (logger, left, right, precedence)
1874 {
1875 }
1876 
1877 // destructor
1879 {
1880 }
1881 
1882 // constructor
1886  : madara::expression::Symbol (logger, 0, right, precedence)
1887 {
1888 }
1889 
1890 // destructor
1892 {
1893 }
1894 
1895 // constructor
1898  : Symbol (logger, 0, 0, NUMBER_PRECEDENCE)
1899 {
1900  item_.set_value (input);
1901 }
1902 
1903 // constructor
1905  double input)
1906  : Symbol (logger, 0, 0, NUMBER_PRECEDENCE)
1907 {
1908  item_.set_value (input);
1909 }
1910 
1911 // constructor
1913  std::string input)
1914  : Symbol (logger, 0, 0, NUMBER_PRECEDENCE)
1915 {
1916  item_.set_value (input);
1917 }
1918 
1919 // destructor
1921 {
1922 }
1923 
1924 // returns the precedence level
1925 int
1927 {
1928  return this->precedence_ = NUMBER_PRECEDENCE + precedence;
1929 }
1930 
1931 // builds an equivalent ExpressionTree node
1934 {
1935  return new LeafNode (*(this->logger_), item_);
1936 }
1937 
1938 // constructor
1940  : UnaryOperator (logger, 0, NEGATE_PRECEDENCE)
1941 {
1942 }
1943 
1944 // destructor
1946 {
1947 }
1948 
1949 // returns the precedence level
1950 int
1952 {
1953  return this->precedence_ = NEGATE_PRECEDENCE + precedence;
1954 }
1955 
1956 // builds an equivalent ExpressionTree node
1959 {
1960  // check for cascading nots
1961  Negate * next = dynamic_cast <Negate *> (right_);
1962  Symbol * right = right_;
1963  unsigned int i;
1964 
1965  for (i = 1; next;
1966  ++i, right = next->right_, next = dynamic_cast <Negate *> (next->right_)) {}
1967 
1968  if (i % 2 == 1)
1969  return new CompositeNegateNode (*(this->logger_), right->build ());
1970  else
1971  return new CompositeNegateNode (*(this->logger_),
1972  new CompositeNegateNode (*(this->logger_), right->build ()));
1973 }
1974 
1975 // constructor
1977  const std::string & name,
1979  : TernaryOperator (context.get_logger (), 0, 0, VARIABLE_PRECEDENCE), name_ (name), context_ (context)
1980 {
1981 }
1982 
1983 // destructor
1985 {
1986 }
1987 
1988 // returns the precedence level
1989 int
1991 {
1992  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
1993 }
1994 
1995 // builds an equivalent ExpressionTree node
1998 {
1999  return new CompositeFunctionNode (name_, context_, nodes_);
2000 }
2001 
2002 
2003 
2004 // constructor
2007 : TernaryOperator (context.get_logger (), 0, 0, VARIABLE_PRECEDENCE),
2008  context_ (context)
2009 {
2010 }
2011 
2012 // destructor
2014 {
2015 }
2016 
2017 // returns the precedence level
2018 int
2020 {
2021  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2022 }
2023 
2024 // builds an equivalent ExpressionTree node
2027 {
2028  return new CompositeConstArray (*(this->logger_), nodes_);
2029 }
2030 
2031 
2032 
2033 
2034 
2035 // constructor
2038 : TernaryOperator (context.get_logger (), 0, 0, VARIABLE_PRECEDENCE),
2039  context_ (context)
2040 {
2041 }
2042 
2043 // destructor
2045 {
2046 }
2047 
2048 
2049 // constructor
2052  : SystemCall (context)
2053 {
2054 }
2055 
2056 // destructor
2058 {
2059 }
2060 
2061 // returns the precedence level
2062 int
2064 {
2065  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2066 }
2067 
2068 // builds an equivalent ExpressionTree node
2071 {
2072  return new SystemCallClearVariable (context_, nodes_);
2073 }
2074 
2075 
2076 // constructor
2079  : SystemCall (context)
2080 {
2081 }
2082 
2083 // destructor
2085 {
2086 }
2087 
2088 // returns the precedence level
2089 int
2091 {
2092  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2093 }
2094 
2095 // builds an equivalent ExpressionTree node
2098 {
2100 }
2101 
2102 
2103 
2104 // constructor
2107  : SystemCall (context)
2108 {
2109 }
2110 
2111 // destructor
2113 {
2114 }
2115 
2116 // returns the precedence level
2117 int
2119 {
2120  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2121 }
2122 
2123 // builds an equivalent ExpressionTree node
2126 {
2127  return new SystemCallEval (context_, nodes_);
2128 }
2129 
2130 
2131 
2132 // constructor
2135  : SystemCall (context)
2136 {
2137 }
2138 
2139 // destructor
2141 {
2142 }
2143 
2144 // returns the precedence level
2145 int
2147 {
2148  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2149 }
2150 
2151 // builds an equivalent ExpressionTree node
2154 {
2155  return new SystemCallExpandEnv (context_, nodes_);
2156 }
2157 
2158 
2159 
2160 // constructor
2163  : SystemCall (context)
2164 {
2165 }
2166 
2167 // destructor
2169 {
2170 }
2171 
2172 // returns the precedence level
2173 int
2175 {
2176  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2177 }
2178 
2179 // builds an equivalent ExpressionTree node
2182 {
2184 }
2185 
2186 
2187 
2188 
2189 // constructor
2192  : SystemCall (context)
2193 {
2194 }
2195 
2196 // destructor
2198 {
2199 }
2200 
2201 // returns the precedence level
2202 int
2204 {
2205  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2206 }
2207 
2208 // builds an equivalent ExpressionTree node
2211 {
2212  return new SystemCallFragment (context_, nodes_);
2213 }
2214 
2215 
2216 
2217 // constructor
2220  : SystemCall (context)
2221 {
2222 }
2223 
2224 // destructor
2226 {
2227 }
2228 
2229 // returns the precedence level
2230 int
2232 {
2233  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2234 }
2235 
2236 // builds an equivalent ExpressionTree node
2239 {
2240  return new SystemCallLogLevel (context_, nodes_);
2241 }
2242 
2243 
2244 
2245 
2246 // constructor
2249  : SystemCall (context)
2250 {
2251 }
2252 
2253 // destructor
2255 {
2256 }
2257 
2258 // returns the precedence level
2259 int
2261 {
2262  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2263 }
2264 
2265 // builds an equivalent ExpressionTree node
2268 {
2269  return new SystemCallGetClock (context_, nodes_);
2270 }
2271 
2272 
2273 // constructor
2276  : SystemCall (context)
2277 {
2278 }
2279 
2280 // destructor
2282 {
2283 }
2284 
2285 // returns the precedence level
2286 int
2288 {
2289  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2290 }
2291 
2292 // builds an equivalent ExpressionTree node
2295 {
2296  return new SystemCallGetTime (context_, nodes_);
2297 }
2298 
2299 
2300 // constructor
2303  : SystemCall (context)
2304 {
2305 }
2306 
2307 // destructor
2309 {
2310 }
2311 
2312 // returns the precedence level
2313 int
2315 {
2316  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2317 }
2318 
2319 // builds an equivalent ExpressionTree node
2322 {
2324 }
2325 
2326 
2327 // constructor
2330  : SystemCall (context)
2331 {
2332 }
2333 
2334 // destructor
2336 {
2337 }
2338 
2339 // returns the precedence level
2340 int
2342 {
2343  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2344 }
2345 
2346 // builds an equivalent ExpressionTree node
2349 {
2350  return new SystemCallSetClock (context_, nodes_);
2351 }
2352 
2353 // constructor
2356  : SystemCall (context)
2357 {
2358 }
2359 
2360 // destructor
2362 {
2363 }
2364 
2365 // returns the precedence level
2366 int
2368 {
2369  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2370 }
2371 
2372 // builds an equivalent ExpressionTree node
2375 {
2376  return new SystemCallSetFixed (context_, nodes_);
2377 }
2378 
2379 
2380 // constructor
2383  : SystemCall (context)
2384 {
2385 }
2386 
2387 // destructor
2389 {
2390 }
2391 
2392 // returns the precedence level
2393 int
2395 {
2396  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2397 }
2398 
2399 // builds an equivalent ExpressionTree node
2402 {
2403  return new SystemCallSetPrecision (context_, nodes_);
2404 }
2405 
2406 
2407 // constructor
2410  : SystemCall (context)
2411 {
2412 }
2413 
2414 // destructor
2416 {
2417 }
2418 
2419 // returns the precedence level
2420 int
2422 {
2423  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2424 }
2425 
2426 // builds an equivalent ExpressionTree node
2429 {
2430  return new SystemCallSetScientific (context_, nodes_);
2431 }
2432 
2433 
2434 
2435 // constructor
2438  : SystemCall (context)
2439 {
2440 }
2441 
2442 // destructor
2444 {
2445 }
2446 
2447 // returns the precedence level
2448 int
2450 {
2451  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2452 }
2453 
2454 // builds an equivalent ExpressionTree node
2457 {
2458  return new SystemCallPrint (context_, nodes_);
2459 }
2460 
2461 // constructor
2464  : SystemCall (context)
2465 {
2466 }
2467 
2468 // destructor
2470 {
2471 }
2472 
2473 // returns the precedence level
2474 int
2476 {
2477  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2478 }
2479 
2480 // builds an equivalent ExpressionTree node
2483 {
2484  return new SystemCallCos (context_, nodes_);
2485 }
2486 
2487 
2488 // constructor
2491  : SystemCall (context)
2492 {
2493 }
2494 
2495 // destructor
2497 {
2498 }
2499 
2500 // returns the precedence level
2501 int
2503 {
2504  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2505 }
2506 
2507 // builds an equivalent ExpressionTree node
2510 {
2511  return new SystemCallSin (context_, nodes_);
2512 }
2513 
2514 // constructor
2517  : SystemCall (context)
2518 {
2519 }
2520 
2521 // destructor
2523 {
2524 }
2525 
2526 // returns the precedence level
2527 int
2529 {
2530  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2531 }
2532 
2533 // builds an equivalent ExpressionTree node
2536 {
2537  return new SystemCallTan (context_, nodes_);
2538 }
2539 
2540 // constructor
2543  : SystemCall (context)
2544 {
2545 }
2546 
2547 // destructor
2549 {
2550 }
2551 
2552 // returns the precedence level
2553 int
2555 {
2556  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2557 }
2558 
2559 // builds an equivalent ExpressionTree node
2562 {
2563  return new SystemCallPow (context_, nodes_);
2564 }
2565 
2566 // constructor
2569  : SystemCall (context)
2570 {
2571 }
2572 
2573 // destructor
2575 {
2576 }
2577 
2578 // returns the precedence level
2579 int
2581 {
2582  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2583 }
2584 
2585 // builds an equivalent ExpressionTree node
2588 {
2589  return new SystemCallSqrt (context_, nodes_);
2590 }
2591 
2592 
2593 
2594 // constructor
2597  : SystemCall (context)
2598 {
2599 }
2600 
2601 // destructor
2603 {
2604 }
2605 
2606 // returns the precedence level
2607 int
2609 {
2610  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2611 }
2612 
2613 // builds an equivalent ExpressionTree node
2616 {
2618 }
2619 
2620 
2621 // constructor
2624  : SystemCall (context)
2625 {
2626 }
2627 
2628 // destructor
2630 {
2631 }
2632 
2633 // returns the precedence level
2634 int
2636 {
2637  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2638 }
2639 
2640 // builds an equivalent ExpressionTree node
2643 {
2644  return new SystemCallRandDouble (context_, nodes_);
2645 }
2646 
2647 
2648 // constructor
2651  : SystemCall (context)
2652 {
2653 }
2654 
2655 // destructor
2657 {
2658 }
2659 
2660 // returns the precedence level
2661 int
2663 {
2664  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2665 }
2666 
2667 // builds an equivalent ExpressionTree node
2670 {
2671  return new SystemCallRandInt (context_, nodes_);
2672 }
2673 
2674 
2675 // constructor
2678  : SystemCall (context)
2679 {
2680 }
2681 
2682 // destructor
2684 {
2685 }
2686 
2687 // returns the precedence level
2688 int
2690 {
2691  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2692 }
2693 
2694 // builds an equivalent ExpressionTree node
2697 {
2698  return new SystemCallReadFile (context_, nodes_);
2699 }
2700 
2701 
2702 // constructor
2705  : SystemCall (context)
2706 {
2707 }
2708 
2709 // destructor
2711 {
2712 }
2713 
2714 // returns the precedence level
2715 int
2717 {
2718  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2719 }
2720 
2721 // builds an equivalent ExpressionTree node
2724 {
2725  return new SystemCallWriteFile (context_, nodes_);
2726 }
2727 
2728 
2729 
2730 // constructor
2733  : SystemCall (context)
2734 {
2735 }
2736 
2737 // destructor
2739 {
2740 }
2741 
2742 // returns the precedence level
2743 int
2745 {
2746  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2747 }
2748 
2749 // builds an equivalent ExpressionTree node
2752 {
2753  return new SystemCallSize (context_, nodes_);
2754 }
2755 
2756 
2757 // constructor
2760  : SystemCall (context)
2761 {
2762 }
2763 
2764 // destructor
2766 {
2767 }
2768 
2769 // returns the precedence level
2770 int
2772 {
2773  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2774 }
2775 
2776 // builds an equivalent ExpressionTree node
2779 {
2780  return new SystemCallSleep (context_, nodes_);
2781 }
2782 
2783 
2784 // constructor
2787  : SystemCall (context)
2788 {
2789 }
2790 
2791 // destructor
2793 {
2794 }
2795 
2796 // returns the precedence level
2797 int
2799 {
2800  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2801 }
2802 
2803 // builds an equivalent ExpressionTree node
2806 {
2807  return new SystemCallToBuffer (context_, nodes_);
2808 }
2809 
2810 
2811 // constructor
2814  : SystemCall (context)
2815 {
2816 }
2817 
2818 // destructor
2820 {
2821 }
2822 
2823 // returns the precedence level
2824 int
2826 {
2827  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2828 }
2829 
2830 // builds an equivalent ExpressionTree node
2833 {
2834  return new SystemCallToDouble (context_, nodes_);
2835 }
2836 
2837 
2838 // constructor
2841  : SystemCall (context)
2842 {
2843 }
2844 
2845 // destructor
2847 {
2848 }
2849 
2850 // returns the precedence level
2851 int
2853 {
2854  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2855 }
2856 
2857 // builds an equivalent ExpressionTree node
2860 {
2861  return new SystemCallToDoubles (context_, nodes_);
2862 }
2863 
2864 
2865 // constructor
2868  : SystemCall (context)
2869 {
2870 }
2871 
2872 // destructor
2874 {
2875 }
2876 
2877 // returns the precedence level
2878 int
2880 {
2881  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2882 }
2883 
2884 // builds an equivalent ExpressionTree node
2887 {
2888  return new SystemCallToHostDirs (context_, nodes_);
2889 }
2890 
2891 
2892 // constructor
2895  : SystemCall (context)
2896 {
2897 }
2898 
2899 // destructor
2901 {
2902 }
2903 
2904 // returns the precedence level
2905 int
2907 {
2908  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2909 }
2910 
2911 // builds an equivalent ExpressionTree node
2914 {
2915  return new SystemCallToInteger (context_, nodes_);
2916 }
2917 
2918 
2919 // constructor
2922  : SystemCall (context)
2923 {
2924 }
2925 
2926 // destructor
2928 {
2929 }
2930 
2931 // returns the precedence level
2932 int
2934 {
2935  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2936 }
2937 
2938 // builds an equivalent ExpressionTree node
2941 {
2942  return new SystemCallToIntegers (context_, nodes_);
2943 }
2944 
2945 
2946 // constructor
2949  : SystemCall (context)
2950 {
2951 }
2952 
2953 // destructor
2955 {
2956 }
2957 
2958 // returns the precedence level
2959 int
2961 {
2962  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2963 }
2964 
2965 // builds an equivalent ExpressionTree node
2968 {
2969  return new SystemCallToString (context_, nodes_);
2970 }
2971 
2972 
2973 // constructor
2976  : SystemCall (context)
2977 {
2978 }
2979 
2980 // destructor
2982 {
2983 }
2984 
2985 // returns the precedence level
2986 int
2988 {
2989  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
2990 }
2991 
2992 // builds an equivalent ExpressionTree node
2995 {
2996  return new SystemCallType (context_, nodes_);
2997 }
2998 
2999 
3000 
3001 // constructor
3003  Symbol * condition, Symbol * postcondition,
3004  Symbol * body,
3006 : UnaryOperator (context.get_logger (), 0, VARIABLE_PRECEDENCE),
3007  precondition_ (precondition), condition_ (condition),
3008  postcondition_ (postcondition), body_ (body), context_ (context)
3009 {
3010 }
3011 
3012 // destructor
3014 {
3015  delete precondition_;
3016  delete postcondition_;
3017  delete condition_;
3018  delete body_;
3019 }
3020 
3021 // returns the precedence level
3022 int
3024 {
3025  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
3026 }
3027 
3028 // builds an equivalent ExpressionTree node
3031 {
3032  if (body_)
3033  return new CompositeForLoop (
3036  else
3037  return new CompositeAssignmentNode (
3039  condition_->right_->build ());
3040 }
3041 
3042 // constructor
3045 : UnaryOperator (logger, 0, NEGATE_PRECEDENCE)
3046 {
3047 }
3048 
3049 // destructor
3051 {
3052 }
3053 
3054 // returns the precedence level
3055 int
3057 {
3058  return this->precedence_ = NEGATE_PRECEDENCE + precedence;
3059 }
3060 
3061 // builds an equivalent ExpressionTree node
3064 {
3065  return new CompositePostdecrementNode (
3066  *(this->logger_), right_->build ());
3067 }
3068 
3069 // constructor
3071 : UnaryOperator (logger, 0, NEGATE_PRECEDENCE)
3072 {
3073 }
3074 
3075 // destructor
3077 {
3078 }
3079 
3080 // returns the precedence level
3081 int
3083 {
3084  return this->precedence_ = NEGATE_PRECEDENCE + precedence;
3085 }
3086 
3087 // builds an equivalent ExpressionTree node
3090 {
3091  return new CompositePostincrementNode (
3092  *(this->logger_), right_->build ());
3093 }
3094 
3095 // constructor
3097 : UnaryOperator (logger, 0, NEGATE_PRECEDENCE)
3098 {
3099 }
3100 
3101 // destructor
3103 {
3104 }
3105 
3106 // returns the precedence level
3107 int
3109 {
3110  return this->precedence_ = NEGATE_PRECEDENCE + precedence;
3111 }
3112 
3113 // builds an equivalent ExpressionTree node
3116 {
3117  return new CompositePredecrementNode (*(this->logger_), right_->build ());
3118 }
3119 
3120 // constructor
3122  : UnaryOperator (logger, 0, NEGATE_PRECEDENCE)
3123 {
3124 }
3125 
3126 // destructor
3128 {
3129 }
3130 
3131 // returns the precedence level
3132 int
3134 {
3135  return this->precedence_ = NEGATE_PRECEDENCE + precedence;
3136 }
3137 
3138 // builds an equivalent ExpressionTree node
3141 {
3142  return new CompositePreincrementNode (*(this->logger_), right_->build ());
3143 }
3144 
3145 // constructor
3147  : UnaryOperator (logger, 0, NEGATE_PRECEDENCE)
3148 {
3149 }
3150 
3151 // destructor
3153 {
3154 }
3155 
3156 // returns the precedence level
3157 int
3159 {
3160  return this->precedence_ = NEGATE_PRECEDENCE + precedence;
3161 }
3162 
3163 // builds an equivalent ExpressionTree node
3166 {
3167  // check for cascading nots
3168  Not * next = dynamic_cast <Not *> (right_);
3169  Symbol * right = right_;
3170  unsigned int i;
3171 
3172  for (i = 1; next;
3173  ++i, right = next->right_, next = dynamic_cast <Not *> (next->right_)) {}
3174 
3175  if (i % 2 == 1)
3176  return new CompositeNotNode (*(this->logger_), right->build ());
3177  else
3178  return new CompositeNotNode (*(this->logger_),
3179  new CompositeNotNode (*(this->logger_), right->build ()));
3180 }
3181 
3182 // constructor
3184  : UnaryOperator (logger, 0, NEGATE_PRECEDENCE)
3185 {
3186 }
3187 
3188 // destructor
3190 {
3191 }
3192 
3193 // returns the precedence level
3194 int
3196 {
3197  return this->precedence_ = NEGATE_PRECEDENCE + precedence;
3198 }
3199 
3200 // builds an equivalent ExpressionTree node
3203 {
3204  return new CompositeSquareRootNode (*(this->logger_), right_->build ());
3205 }
3206 
3207 // constructor
3210  : Symbol (context.get_logger (), 0, 0, VARIABLE_PRECEDENCE),
3211  key_ (key), context_ (context)
3212 {
3213 }
3214 
3215 // destructor
3217 {
3218 }
3219 
3220 // returns the precedence level
3221 int
3223 {
3224  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
3225 }
3226 
3227 // builds an equivalent ExpressionTree node
3230 {
3231  return new VariableNode (key_, context_);
3232 }
3233 
3234 
3235 // constructor
3237  Symbol * index,
3239  : Symbol (context.get_logger (), 0, 0, VARIABLE_PRECEDENCE),
3240  key_ (key), context_ (context), index_ (index)
3241 {
3242 }
3243 
3244 // destructor
3246 {
3247 }
3248 
3249 // returns the precedence level
3250 int
3252 {
3253  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
3254 }
3255 
3256 // builds an equivalent ExpressionTree node
3259 {
3260  return new CompositeArrayReference (key_, index_->build (), context_);
3261 }
3262 
3263 
3264 // constructor
3266  Symbol * lhs,
3269  : Operator (context.get_logger (), 0, rhs, ASSIGNMENT_PRECEDENCE), left_ (lhs), value_ (value),
3270  context_ (context)
3271 {
3272 }
3273 
3274 // destructor
3276 {
3277 }
3278 
3279 // returns the precedence level
3280 int
3282 {
3283  return this->precedence_ = ASSIGNMENT_PRECEDENCE + precedence;
3284 }
3285 
3286 // builds an equivalent ExpressionTree node
3289 {
3290  if (this->right_)
3291  return new VariableDecrementNode (left_->build (), value_, this->right_->build (), context_);
3292  else
3293  return new VariableDecrementNode (left_->build (), value_, 0, context_);
3294 }
3295 
3296 
3297 // constructor
3299  knowledge::KnowledgeRecord value, Symbol * rhs,
3301  : Operator (context.get_logger (), 0, rhs, ASSIGNMENT_PRECEDENCE), left_ (lhs), value_ (value),
3302  context_ (context)
3303 {
3304 }
3305 
3306 // destructor
3308 {
3309 }
3310 
3311 // returns the precedence level
3312 int
3314 {
3315  return this->precedence_ = ASSIGNMENT_PRECEDENCE + precedence;
3316 }
3317 
3318 // builds an equivalent ExpressionTree node
3321 {
3322  if (this->right_)
3323  return new VariableDivideNode (left_->build (), value_, this->right_->build (), context_);
3324  else
3325  return new VariableDivideNode (left_->build (), value_, 0, context_);
3326 }
3327 
3328 // constructor
3332  : Operator (context.get_logger (), 0, rhs, ASSIGNMENT_PRECEDENCE),
3333  left_ (lhs), value_ (value),
3334  context_ (context)
3335 {
3336 }
3337 
3338 // destructor
3340 {
3341 }
3342 
3343 // returns the precedence level
3344 int
3346 {
3347  return this->precedence_ = ASSIGNMENT_PRECEDENCE + precedence;
3348 }
3349 
3350 // builds an equivalent ExpressionTree node
3353 {
3354  if (this->right_)
3355  return new VariableIncrementNode (left_->build (),
3356  value_, this->right_->build (), context_);
3357  else
3358  return new VariableIncrementNode (left_->build (), value_, 0, context_);
3359 }
3360 
3361 // constructor
3365  : Operator (context.get_logger (), 0, rhs, ASSIGNMENT_PRECEDENCE),
3366  left_ (lhs), value_ (value),
3367  context_ (context)
3368 {
3369 }
3370 
3371 // destructor
3373 {
3374 }
3375 
3376 // returns the precedence level
3377 int
3379 {
3380  return this->precedence_ = ASSIGNMENT_PRECEDENCE + precedence;
3381 }
3382 
3383 // builds an equivalent ExpressionTree node
3386 {
3387  if (this->right_)
3388  return new VariableMultiplyNode (left_->build (), value_, this->right_->build (), context_);
3389  else
3390  return new VariableMultiplyNode (left_->build (), value_, 0, context_);
3391 }
3392 
3393 
3394 // constructor
3396  madara::knowledge::KnowledgeRecord value, Symbol * rhs, int compare_type,
3398  : Symbol (context.get_logger (), 0, 0, VARIABLE_PRECEDENCE),
3399  left_ (lhs), value_ (value), rhs_ (rhs),
3400  compare_type_ (compare_type), context_ (context)
3401 {
3402 }
3403 
3404 // destructor
3406 {
3407 }
3408 
3409 // returns the precedence level
3410 int
3412 {
3413  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
3414 }
3415 
3416 // builds an equivalent ExpressionTree node
3419 {
3420  if (rhs_)
3422  rhs_->build (), context_);
3423  else
3425  0, context_);
3426 }
3427 
3428 
3429 
3430 // constructor
3433  : Symbol (context.get_logger (), 0, 0, VARIABLE_PRECEDENCE),
3434  context_ (context)
3435 {
3436 }
3437 
3438 // destructor
3440 {
3441 }
3442 
3443 // returns the precedence level
3444 int
3446 {
3447  return this->precedence_ = VARIABLE_PRECEDENCE + precedence;
3448 }
3449 
3450 // builds an equivalent ExpressionTree node
3453 {
3454  return new ListNode (context_);
3455 }
3456 
3457 // constructor
3459  : TernaryOperator (logger, 0, 0, ADD_PRECEDENCE)
3460 {
3461 }
3462 
3463 // destructor
3465 {
3466 }
3467 
3468 // returns the precedence level
3469 int
3471 {
3472  return this->precedence_ = ADD_PRECEDENCE + precedence;
3473 }
3474 
3475 // builds an equivalent ExpressionTree node
3478 {
3479  if (left_ && right_)
3480  {
3481  // check for cascading max
3482  Add * next = dynamic_cast <Add *> (left_);
3483  Symbol * left = left_;
3484 
3485  // push the right onto the deque
3486  nodes_.push_back (right_->build ());
3487  delete right_;
3488  right_ = 0;
3489 
3490  for (; next; next = dynamic_cast <Add *> (left))
3491  {
3492  // we have a chained max node. Move the left into our nodes list
3493  if (next->right_)
3494  {
3495  nodes_.push_front (next->right_->build ());
3496  delete next->right_;
3497  next->right_ = 0;
3498  }
3499 
3500  // set right to next->right_ and then clear next->right_ before deletion
3501  left = next->left_;
3502  next->left_ = 0;
3503  delete next;
3504  }
3505 
3506  // push the rightmost build from the compressed node and delete it.
3507  // then reset our right_, since we've already taken care of deletion
3508  if (left)
3509  {
3510  nodes_.push_front (left->build ());
3511  delete left;
3512  }
3513  left_ = 0;
3514 
3515  return new CompositeAddNode (*(this->logger_), nodes_);
3516  }
3517  else if (left_)
3518  // all we have is a valid left child, so there is no reason to build
3519  // a Both operator
3520  return left_->build ();
3521  else if (right_)
3522  // all we have is a valid right child, so there is no reason to build
3523  // a Both operator
3524  return right_->build ();
3525  else
3526  // we've got nothing. This node should eventually be pruned out of the
3527  // picture if at all possible.
3528  return new LeafNode (*(this->logger_),
3530 }
3531 
3532 
3533 // constructor
3535  : TernaryOperator (logger, 0, 0, LOGICAL_PRECEDENCE)
3536 {
3537 }
3538 
3539 // destructor
3541 {
3542 }
3543 
3544 // returns the precedence level
3545 int
3547 {
3548  return this->precedence_ = LOGICAL_PRECEDENCE + precedence;
3549 }
3550 
3551 // builds an equivalent ExpressionTree node
3554 {
3555  if (left_ && right_)
3556  {
3557  // check for cascading max
3558  And * next = dynamic_cast <And *> (left_);
3559  Symbol * left = left_;
3560 
3561  // push the right onto the deque
3562  nodes_.push_back (right_->build ());
3563  delete right_;
3564  right_ = 0;
3565 
3566  for (; next; next = dynamic_cast <And *> (left))
3567  {
3568  // we have a chained max node. Move the left into our nodes list
3569  if (next->right_)
3570  {
3571  nodes_.push_front (next->right_->build ());
3572  delete next->right_;
3573  next->right_ = 0;
3574  }
3575 
3576  // set right to next->right_ and then clear next->right_ before deletion
3577  left = next->left_;
3578  next->left_ = 0;
3579  delete next;
3580  }
3581 
3582  // push the rightmost build from the compressed node and delete it.
3583  // then reset our right_, since we've already taken care of deletion
3584  if (left)
3585  {
3586  nodes_.push_front (left->build ());
3587  delete left;
3588  }
3589  left_ = 0;
3590 
3591  return new CompositeAndNode (*(this->logger_), nodes_);
3592  }
3593  else if (left_)
3594  // all we have is a valid left child, so there is no reason to build
3595  // a Both operator
3596  return left_->build ();
3597  else if (right_)
3598  // all we have is a valid right child, so there is no reason to build
3599  // a Both operator
3600  return right_->build ();
3601  else
3602  // we've got nothing. This node should eventually be pruned out of the
3603  // picture if at all possible.
3605 }
3606 
3607 // constructor
3609  : TernaryOperator (logger, 0, 0, LOGICAL_PRECEDENCE)
3610 {
3611 }
3612 
3613 // destructor
3615 {
3616 }
3617 
3618 // returns the precedence level
3619 int
3621 {
3622  return this->precedence_ = LOGICAL_PRECEDENCE + precedence;
3623 }
3624 
3625 
3626 
3627 // builds an equivalent ExpressionTree node
3630 {
3631  if (left_ && right_)
3632  {
3633  // check for cascading max
3634  Or * next = dynamic_cast <Or *> (left_);
3635  Symbol * left = left_;
3636 
3637  // push the right onto the deque
3638  nodes_.push_back (right_->build ());
3639  delete right_;
3640  right_ = 0;
3641 
3642  for (; next; next = dynamic_cast <Or *> (left))
3643  {
3644  // we have a chained max node. Move the left into our nodes list
3645  if (next->right_)
3646  {
3647  nodes_.push_front (next->right_->build ());
3648  delete next->right_;
3649  next->right_ = 0;
3650  }
3651 
3652  // set right to next->right_ and then clear next->right_ before deletion
3653  left = next->left_;
3654  next->left_ = 0;
3655  delete next;
3656  }
3657 
3658  // push the rightmost build from the compressed node and delete it.
3659  // then reset our right_, since we've already taken care of deletion
3660  if (left)
3661  {
3662  nodes_.push_front (left->build ());
3663  delete left;
3664  }
3665  left_ = 0;
3666 
3667  return new CompositeOrNode (*(this->logger_), nodes_);
3668  }
3669  else if (left_)
3670  // all we have is a valid left child, so there is no reason to build
3671  // a Both operator
3672  return left_->build ();
3673  else if (right_)
3674  // all we have is a valid right child, so there is no reason to build
3675  // a Both operator
3676  return right_->build ();
3677  else
3678  // we've got nothing. This node should eventually be pruned out of the
3679  // picture if at all possible.
3680  return new LeafNode (*(this->logger_),
3682 }
3683 
3684 
3685 // constructor
3687  : TernaryOperator (logger, 0, 0, BOTH_PRECEDENCE)
3688 {
3689 }
3690 
3691 // destructor
3693 {
3694 }
3695 
3696 // returns the precedence level
3697 int
3699 {
3700  return this->precedence_ = BOTH_PRECEDENCE + precedence;
3701 }
3702 
3703 // builds an equivalent ExpressionTree node
3706 {
3707  // Since users can say something like ";;;;;;;;", it is very possible
3708  // that a both operation contains no valid children. So, we need
3709  // to check whether or not we have a valid child.
3710  if (left_ && right_)
3711  {
3712  // check for cascading max
3713  Both * next = dynamic_cast <Both *> (left_);
3714  Symbol * left = left_;
3715 
3716  // push the right onto the deque
3717  //nodes_.push_back (right_->build ());
3718  //delete right_;
3719  //right_ = 0;
3720 
3721  for (; next; next = dynamic_cast <Both *> (left))
3722  {
3723  // we have a chained max node. Move the left into our nodes list
3724  if (next->right_)
3725  {
3726  nodes_.push_front (next->right_->build ());
3727  delete next->right_;
3728  next->right_ = 0;
3729  }
3730 
3731  // set right to next->right_ and then clear next->right_ before deletion
3732  left = next->left_;
3733  next->left_ = 0;
3734  delete next;
3735  }
3736 
3737  // push the rightmost build from the compressed node and delete it.
3738  // then reset our right_, since we've already taken care of deletion
3739  if (left)
3740  {
3741  nodes_.push_front (left->build ());
3742  delete left;
3743  }
3744  left_ = 0;
3745 
3746 
3747  next = dynamic_cast <Both *> (right_);
3748  Symbol * right = right_;
3749 
3750  for (; next; next = dynamic_cast <Both *> (right))
3751  {
3752  // we have a chained max node. Move the left into our nodes list
3753  if (next->left_)
3754  {
3755  nodes_.push_back (next->left_->build ());
3756  delete next->left_;
3757  next->left_ = 0;
3758  }
3759 
3760  // set right to next->right_ and then clear next->right_ before deletion
3761  right = next->right_;
3762  next->right_ = 0;
3763  delete next;
3764  }
3765 
3766  // push the rightmost build from the compressed node and delete it.
3767  // then reset our right_, since we've already taken care of deletion
3768  if (right)
3769  {
3770  nodes_.push_back (right->build ());
3771  delete right;
3772  }
3773  right_ = 0;
3774 
3775  return new CompositeBothNode (*(this->logger_), nodes_);
3776  }
3777  else if (left_)
3778  // all we have is a valid left child, so there is no reason to build
3779  // a Both operator
3780  return left_->build ();
3781  else if (right_)
3782  // all we have is a valid right child, so there is no reason to build
3783  // a Both operator
3784  return right_->build ();
3785  else
3786  // we've got nothing. This node should eventually be pruned out of the
3787  // picture if at all possible.
3788  return new LeafNode (*(this->logger_),
3790 }
3791 
3792 
3793 // constructor
3795  : TernaryOperator (logger, 0, 0, BOTH_PRECEDENCE)
3796 {
3797 }
3798 
3799 // destructor
3801 {
3802 }
3803 
3804 // returns the precedence level
3805 int
3807 {
3808  return this->precedence_ = BOTH_PRECEDENCE + precedence;
3809 }
3810 
3811 // builds an equivalent ExpressionTree node
3814 {
3815  // Since users can say something like ";;;;;;;;", it is very possible
3816  // that a both operation contains no valid children. So, we need
3817  // to check whether or not we have a valid child.
3818  if (left_ && right_)
3819  {
3820  // check for cascading max
3821  ReturnRight * next = dynamic_cast <ReturnRight *> (left_);
3822  Symbol * left = left_;
3823 
3824  // push the right onto the deque
3825  //nodes_.push_back (right_->build ());
3826  //delete right_;
3827  //right_ = 0;
3828 
3829  for (; next; next = dynamic_cast <ReturnRight *> (left))
3830  {
3831  // we have a chained max node. Move the left into our nodes list
3832  if (next->right_)
3833  {
3834  nodes_.push_front (next->right_->build ());
3835  delete next->right_;
3836  next->right_ = 0;
3837  }
3838 
3839  // set right to next->right_ and then clear next->right_ before deletion
3840  left = next->left_;
3841  next->left_ = 0;
3842  delete next;
3843  }
3844 
3845  // push the rightmost build from the compressed node and delete it.
3846  // then reset our right_, since we've already taken care of deletion
3847  if (left)
3848  {
3849  nodes_.push_front (left->build ());
3850  delete left;
3851  }
3852  left_ = 0;
3853 
3854 
3855  next = dynamic_cast <ReturnRight *> (right_);
3856  Symbol * right = right_;
3857 
3858  for (; next; next = dynamic_cast <ReturnRight *> (right))
3859  {
3860  // we have a chained max node. Move the left into our nodes list
3861  if (next->left_)
3862  {
3863  nodes_.push_back (next->left_->build ());
3864  delete next->left_;
3865  next->left_ = 0;
3866  }
3867 
3868  // set right to next->right_ and then clear next->right_ before deletion
3869  right = next->right_;
3870  next->right_ = 0;
3871  delete next;
3872  }
3873 
3874  // push the rightmost build from the compressed node and delete it.
3875  // then reset our right_, since we've already taken care of deletion
3876  if (right)
3877  {
3878  nodes_.push_back (right->build ());
3879  delete right;
3880  }
3881  right_ = 0;
3882 
3883  return new CompositeReturnRightNode (*(this->logger_), nodes_);
3884  }
3885  else if (left_)
3886  // all we have is a valid left child, so there is no reason to build
3887  // a Both operator
3888  return left_->build ();
3889  else if (right_)
3890  // all we have is a valid right child, so there is no reason to build
3891  // a Both operator
3892  return right_->build ();
3893  else
3894  // we've got nothing. This node should eventually be pruned out of the
3895  // picture if at all possible.
3896  return new LeafNode (*(this->logger_),
3898 }
3899 
3900 // constructor
3902  : TernaryOperator (logger, 0, 0, BOTH_PRECEDENCE)
3903 {
3904 }
3905 
3906 // destructor
3908 {
3909 }
3910 
3911 // returns the precedence level
3912 int
3914 {
3915  return this->precedence_ = BOTH_PRECEDENCE + precedence;
3916 }
3917 
3918 // builds an equivalent ExpressionTree node
3921 {
3922  // Since users can say something like ";;;;;;;;", it is very possible
3923  // that a both operation contains no valid children. So, we need
3924  // to check whether or not we have a valid child.
3925  if (left_ && right_)
3926  {
3927  // check for cascading max
3928  Sequence * next = dynamic_cast <Sequence *> (left_);
3929  Symbol * left = left_;
3930 
3931  // push the right onto the deque
3932  //nodes_.push_back (right_->build ());
3933  //delete right_;
3934  //right_ = 0;
3935 
3936  for (; next; next = dynamic_cast <Sequence *> (left))
3937  {
3938  // we have a chained max node. Move the left into our nodes list
3939  if (next->right_)
3940  {
3941  nodes_.push_front (next->right_->build ());
3942  delete next->right_;
3943  next->right_ = 0;
3944  }
3945 
3946  // set right to next->right_ and then clear next->right_ before deletion
3947  left = next->left_;
3948  next->left_ = 0;
3949  delete next;
3950  }
3951 
3952  // push the rightmost build from the compressed node and delete it.
3953  // then reset our right_, since we've already taken care of deletion
3954  if (left)
3955  {
3956  nodes_.push_front (left->build ());
3957  delete left;
3958  }
3959  left_ = 0;
3960 
3961 
3962  next = dynamic_cast <Sequence *> (right_);
3963  Symbol * right = right_;
3964 
3965  for (; next; next = dynamic_cast <Sequence *> (right))
3966  {
3967  // we have a chained max node. Move the left into our nodes list
3968  if (next->left_)
3969  {
3970  nodes_.push_back (next->left_->build ());
3971  delete next->left_;
3972  next->left_ = 0;
3973  }
3974 
3975  // set right to next->right_ and then clear next->right_ before deletion
3976  right = next->right_;
3977  next->right_ = 0;
3978  delete next;
3979  }
3980 
3981  // push the rightmost build from the compressed node and delete it.
3982  // then reset our right_, since we've already taken care of deletion
3983  if (right)
3984  {
3985  nodes_.push_back (right->build ());
3986  delete right;
3987  }
3988  right_ = 0;
3989 
3990  return new CompositeSequentialNode (*(this->logger_), nodes_);
3991  }
3992  else if (left_)
3993  // all we have is a valid left child, so there is no reason to build
3994  // a Both operator
3995  return left_->build ();
3996  else if (right_)
3997  // all we have is a valid right child, so there is no reason to build
3998  // a Both operator
3999  return right_->build ();
4000  else
4001  // we've got nothing. This node should eventually be pruned out of the
4002  // picture if at all possible.
4003  return new LeafNode (*(this->logger_),
4005 }
4006 
4007 // constructor
4009  : Operator (logger, 0, 0, IMPLIES_PRECEDENCE)
4010 {
4011 }
4012 
4013 // destructor
4015 {
4016 }
4017 
4018 // returns the precedence level
4019 int
4021 {
4022  return this->precedence_ = IMPLIES_PRECEDENCE + precedence;
4023 }
4024 
4025 // builds an equivalent ExpressionTree node
4028 {
4029  return new CompositeImpliesNode (
4030  *(this->logger_), left_->build (), right_->build ());
4031 }
4032 
4033 
4034 // constructor
4036  : Operator (logger, 0, 0, ASSIGNMENT_PRECEDENCE)
4037 {
4038 }
4039 
4040 // destructor
4042 {
4043 }
4044 
4045 // returns the precedence level
4046 int
4048 {
4049  return this->precedence_ = ASSIGNMENT_PRECEDENCE + precedence;
4050 }
4051 
4052 // builds an equivalent ExpressionTree node
4055 {
4056  // because of the way post order is evaluated and the fact that we want
4057  // to support statements like a = b = c, we reverse the order of the arguments
4058  // so the left side is built first. This looks very, very odd when printing
4059  // but it is the only way I know of to make this work with the order that
4060  // the Evaluation Visitor will visit the tree.
4061  return new CompositeAssignmentNode (*(this->logger_),
4062  left_->build (), right_->build ());
4063 }
4064 
4065 
4066 // constructor
4068  : Operator (logger, 0, 0, CONDITIONAL_PRECEDENCE)
4069 {
4070 }
4071 
4072 // destructor
4074 {
4075 }
4076 
4077 // returns the precedence level
4078 int
4080 {
4082 }
4083 
4084 // builds an equivalent ExpressionTree node
4087 {
4088  return new CompositeEqualityNode (*(this->logger_),
4089  left_->build (), right_->build ());
4090 }
4091 
4092 // constructor
4094  : Operator (logger, 0, 0, CONDITIONAL_PRECEDENCE)
4095 {
4096 }
4097 
4098 // destructor
4100 {
4101 }
4102 
4103 // returns the precedence level
4104 int
4106 {
4108 }
4109 
4110 // builds an equivalent ExpressionTree node
4113 {
4114  return new CompositeInequalityNode (*(this->logger_),
4115  left_->build (), right_->build ());
4116 }
4117 
4118 // constructor
4121  : Operator (logger, 0, 0, CONDITIONAL_PRECEDENCE)
4122 {
4123 }
4124 
4125 // destructor
4127 {
4128 }
4129 
4130 // returns the precedence level
4131 int
4133 {
4135 }
4136 
4137 // builds an equivalent ExpressionTree node
4140 {
4141  return new CompositeGreaterThanEqualNode (
4142  *(this->logger_), left_->build (), right_->build ());
4143 }
4144 
4145 // constructor
4147  : Operator (logger, 0, 0, CONDITIONAL_PRECEDENCE)
4148 {
4149 }
4150 
4151 // destructor
4153 {
4154 }
4155 
4156 // returns the precedence level
4157 int
4159 {
4161 }
4162 
4163 // builds an equivalent ExpressionTree node
4166 {
4167  return new CompositeGreaterThanNode (*(this->logger_),
4168  left_->build (), right_->build ());
4169 }
4170 
4171 // constructor
4174  : Operator (logger, 0, 0, CONDITIONAL_PRECEDENCE)
4175 {
4176 }
4177 
4178 // destructor
4180 {
4181 }
4182 
4183 // returns the precedence level
4184 int
4186 {
4188 }
4189 
4190 // builds an equivalent ExpressionTree node
4193 {
4194  return new CompositeLessThanEqualNode (*(this->logger_),
4195  left_->build (), right_->build ());
4196 }
4197 
4198 // constructor
4200  : Operator (logger, 0, 0, CONDITIONAL_PRECEDENCE)
4201 {
4202 }
4203 
4204 // destructor
4206 {
4207 }
4208 
4209 // returns the precedence level
4210 int
4212 {
4214 }
4215 
4216 // builds an equivalent ExpressionTree node
4219 {
4220  return new CompositeLessThanNode (*(this->logger_),
4221  left_->build (), right_->build ());
4222 }
4223 
4224 
4225 // constructor
4227  : Operator (logger, 0, 0, SUBTRACT_PRECEDENCE)
4228 {
4229 }
4230 
4231 // destructor
4233 {
4234 }
4235 
4236 // returns the precedence level
4237 int
4239 {
4240  return this->precedence_ = ADD_PRECEDENCE + precedence;
4241 }
4242 
4243 // builds an equivalent ExpressionTree node
4246 {
4247  return new CompositeSubtractNode (*(this->logger_),
4248  left_->build (), right_->build ());
4249 }
4250 
4251 // constructor
4253  : TernaryOperator (logger, 0, 0, MULTIPLY_PRECEDENCE)
4254 {
4255 }
4256 
4257 // destructor
4259 {
4260 }
4261 
4262 // returns the precedence level
4263 int
4265 {
4266  return this->precedence_ = MULTIPLY_PRECEDENCE + precedence;
4267 }
4268 
4269 // builds an equivalent ExpressionTree node
4272 {
4273  if (left_ && right_)
4274  {
4275  Multiply * rhs = dynamic_cast <Multiply *> (right_);
4276 
4277  nodes_.push_back (left_->build ());
4278 
4279  if (rhs)
4280  {
4281  nodes_.insert (nodes_.end (), rhs->nodes_.begin (), rhs->nodes_.end ());
4282  rhs->nodes_.clear ();
4283  }
4284  else
4285  {
4286  nodes_.push_back (right_->build ());
4287  }
4288  return new CompositeMultiplyNode (*(this->logger_), nodes_);
4289  }
4290  else if (left_)
4291  // all we have is a valid left child, so there is no reason to build
4292  // a Both operator
4293  return left_->build ();
4294  else if (right_)
4295  // all we have is a valid right child, so there is no reason to build
4296  // a Both operator
4297  return right_->build ();
4298  else
4299  // we've got nothing. This node should eventually be pruned out of the
4300  // picture if at all possible.
4301  return new LeafNode (*(this->logger_),
4303 }
4304 
4305 // constructor
4307  : Operator (logger, 0, 0, MODULUS_PRECEDENCE)
4308 {
4309 }
4310 
4311 // destructor
4313 {
4314 }
4315 
4316 // returns the precedence level
4317 int
4319 {
4320  return this->precedence_ = MODULUS_PRECEDENCE + precedence;
4321 }
4322 
4323 // builds an equivalent ExpressionTree node
4326 {
4327  return new CompositeModulusNode (*(this->logger_),
4328  left_->build (), right_->build ());
4329 }
4330 
4331 // constructor
4333  : Operator (logger, 0, 0, DIVIDE_PRECEDENCE)
4334 {
4335 }
4336 
4337 // destructor
4339 {
4340 }
4341 
4342 // returns the precedence level
4343 int
4345 {
4346  return this->precedence_ = DIVIDE_PRECEDENCE + precedence;
4347 }
4348 
4349 // builds an equivalent ExpressionTree node
4352 {
4353  return new CompositeDivideNode (*(this->logger_),
4354  left_->build (), right_->build ());
4355 }
4356 
4357 // constructor
4359 {
4360 }
4361 
4362 // destructor
4364 {
4365 }
4366 
4367 // extracts precondition, condition, postcondition, and body from input
4368 void
4371 std::string &variable,
4372 const std::string &input,
4373 std::string::size_type &i,
4374 int & accumulated_precedence,
4375 ::std::list<Symbol *>& list,
4376 Symbol *& returnableInput)
4377 {
4378  ::std::list <Symbol *> substr_list;
4379  Symbol * lastValidInput (0);
4380  std::string::size_type begin = i;
4381  Operator * precondition (0); //, * condition (0), * postcondition (0);
4382  Symbol * body (0), *user_pre (0), *user_cond (0), *user_post (0);
4383 
4384  // for extracting and using substrings of input
4385  std::string::size_type count (0);
4386  std::string substr;
4387 
4388  if (variable == "")
4389  variable = ".MADARA_I";
4390 
4391  bool delimiter_found = false, handled = false, equal_to = false;
4392  std::string::size_type delimiter_begin = 0;
4393  std::string::size_type delimiter_end = 0;
4394  int paren_depth = 0;
4395  int index_depth = 0;
4396 
4397  // search for end of for_loop conditions. Be on lookout for delimiter.
4398  for (; i < input.length (); ++i)
4399  {
4400  if (index_depth == 0 && paren_depth == 0 &&
4401  input[i] == '-' && !delimiter_found)
4402  {
4403  delimiter_found = true;
4404  delimiter_begin = i;
4405  }
4406  else if (index_depth == 0 && paren_depth == 0 &&
4407  delimiter_found && input[i] == '>')
4408  {
4409  delimiter_end = i;
4410  }
4411  else if (input[i] == ']')
4412  {
4413  if (index_depth == 0 && paren_depth == 0)
4414  {
4415  break;
4416  }
4417  else
4418  {
4419  --index_depth;
4420  }
4421  }
4422  else if (input[i] == '(')
4423  {
4424  ++paren_depth;
4425  }
4426  else if (input[i] == '[')
4427  {
4428  ++index_depth;
4429  }
4430  else if (input[i] == ')')
4431  {
4432  if (paren_depth == 0)
4433  {
4434  break;
4435  }
4436  else
4437  {
4438  --paren_depth;
4439  }
4440  }
4441  }
4442 
4447  if (delimiter_found && delimiter_end == 0)
4448  {
4449  delimiter_found = false;
4450  }
4451 
4452  // this is actually an array index
4453  if (!delimiter_found)
4454  {
4455  // variable
4456  // begin to end--the index
4457  substr = input.substr (begin, i - begin);
4458 
4459  Symbol * index = nullptr;
4460 
4461  for (count = 0;
4462  count < substr.length ();)
4463  {
4464  main_loop (context, substr, count, lastValidInput,
4465  handled, accumulated_precedence, substr_list);
4466  }
4467 
4469  "KaRL: For loop: Array reference created at %s\n",
4470  substr.c_str ());
4471 
4472  // we have a precondition
4473  if (!substr_list.empty ())
4474  {
4475  index = substr_list.back ();
4476  substr_list.clear ();
4477  }
4478 
4479  Symbol * op = new ArrayRef (variable, index, context);
4480  op->add_precedence (accumulated_precedence);
4481 
4482  // check for post increments and decrements
4483  if (i + 2 < input.size ())
4484  {
4485  if (input[i + 1] == '+' && input[i + 2] == '+')
4486  {
4487  Symbol * array_ref = op;
4488  op = new Postincrement (context.get_logger ());
4489  op->add_precedence (accumulated_precedence);
4490  op->right_ = array_ref;
4491  i += 2;
4492  }
4493  else if (input[i + 1] == '-' && input[i + 2] == '-')
4494  {
4495  Symbol * array_ref = op;
4496  op = new Postdecrement (context.get_logger ());
4497  op->add_precedence (accumulated_precedence);
4498  op->right_ = array_ref;
4499  i += 2;
4500  }
4501  }
4502 
4503  lastValidInput = op;
4504 
4505  precedence_insert (context, op, list);
4506 
4507  returnableInput = op;
4508  ++i;
4509  return;
4510  }
4511 
4513  "KaRL: For loop: Within input string, the for loop delimiter begins at %d"
4514  " and ends at %d (should be at least 1). Loop construct begins at "
4515  "%d and ends at %d\n",
4516  (int)delimiter_begin, (int)delimiter_end, (int)begin, (int)i);
4517 
4518 
4519  // What did we end with? Less than? Greater than?
4520  if (input[i] == ']')
4521  equal_to = true;
4522  else if (input[i] != ')')
4523  {
4524  // this is an error. Essentially, it means the user did not close the
4525  // for loop.
4527  "KARL COMPILE ERROR:: No closing delimiter (']' or ')')"
4528  " has been specified on the for loop.\n");
4529  }
4530 
4531  // if at all possible, don't touch i
4532  std::string::size_type end = i;
4533 
4534  // get the precondition, postcondition and condition ready
4535  precondition = new Assignment (context.get_logger ());
4536  precondition->left_ = new Variable (variable, context);
4537 
4538 
4539  // this is the non-short-hand way of specifying, e.g., var[0,30] {}
4540  if (delimiter_found)
4541  {
4542  // setup precondition
4543  if (delimiter_begin - begin > 0)
4544  {
4545  // run main_loop on the precondition substring
4546  substr = input.substr (begin, delimiter_begin - begin);
4547 
4548  for (count = 0;
4549  count < substr.length ();)
4550  {
4551  main_loop (context, substr, count, lastValidInput,
4552  handled, accumulated_precedence, substr_list);
4553  }
4554 
4556  "KaRL: For loop: Precondition is set to %s\n", substr.c_str ());
4557 
4558  // we have a precondition
4559  if (!substr_list.empty ())
4560  {
4561  user_pre = substr_list.back ();
4562  substr_list.clear ();
4563  }
4564  }
4565  else
4566  {
4568  "KaRL: For loop: No loop precondition was specified\n");
4569  }
4570 
4571  // check for special increment
4572  if (delimiter_end - delimiter_begin > 1)
4573  {
4574  count = 0;
4575  lastValidInput = 0;
4576  substr = input.substr (delimiter_begin + 1, delimiter_end - (delimiter_begin + 1));
4577 
4578  for (count = 0;
4579  count < substr.length ();)
4580  {
4581  main_loop (context, substr, count, lastValidInput,
4582  handled, accumulated_precedence, substr_list);
4583  }
4584 
4586  "KaRL: For loop: Postcondition is set to %s\n", substr.c_str ());
4587 
4588  // we have a postcondition
4589  if (!substr_list.empty ())
4590  {
4591  user_post = substr_list.back ();
4592 
4593  substr_list.clear ();
4594  }
4595  }
4596  else
4597  {
4599  "KaRL: For loop: No loop special increment was specified\n");
4600  }
4601 
4602  // set condition
4603  if (i - delimiter_end >= 2)
4604  {
4605  lastValidInput = 0;
4606  substr = input.substr (delimiter_end + 1, i - (delimiter_end + 1));
4607 
4608  for (count = 0;
4609  count < substr.length ();)
4610  {
4611  main_loop (context, substr, count, lastValidInput,
4612  handled, accumulated_precedence, substr_list);
4613  }
4614 
4615  // we have a condition
4616  if (!substr_list.empty ())
4617  {
4619  "KaRL: For loop: Condition is set to %s\n", substr.c_str ());
4620 
4621  user_cond = substr_list.back ();
4622  substr_list.clear ();
4623  }
4624  else
4625  {
4627  "KaRL: For loop: Condition was not set to %s\n", substr.c_str ());
4628  }
4629  }
4630  else
4631  {
4633  "KaRL: For loop: No loop condition was specified\n");
4634  }
4635  }
4636  // if no delimiter found, this is the shorthand
4637  else
4638  {
4639  lastValidInput = 0;
4640  substr = input.substr (begin, i - begin);
4641 
4642  for (count = 0;
4643  count < substr.length ();)
4644  {
4645  main_loop (context, substr, count, lastValidInput,
4646  handled, accumulated_precedence, substr_list);
4647  }
4648 
4650  "KaRL: For loop: Condition only is set to %s\n", substr.c_str ());
4651 
4652  // we have a condition
4653  if (!substr_list.empty ())
4654  {
4655  user_cond = substr_list.back ();
4656  substr_list.clear ();
4657  }
4658  }
4659 
4660  // if precondition not set, set to default
4661  if (!user_pre)
4662  {
4663  user_pre = new Number (context.get_logger (),
4665  }
4666 
4667  // set condition to default if not yet set
4668  if (!user_cond)
4669  {
4670  user_cond = new Number (context.get_logger (),
4672  }
4673 
4674  // set postcondition to default if not yet set
4675  if (!user_post)
4676  {
4677  user_post = new Number (context.get_logger (),
4680  "KaRL: For loop: Postcondition is set to 1 (def)\n");
4681  }
4682 
4683  // eat up whitespace so we can check for a parenthesis (function)
4684  for (++i; i < input.length () && is_whitespace (input[i]); ++i);
4685 
4686  // can't have a body without a parenthesis or brace
4687  if (i < input.length () && input[i] == '(')
4688  {
4689  ++i;
4690  lastValidInput = 0;
4691 
4693  "KaRL: For loop: Body is reading from %s\n",
4694  input.substr (i, input.size () - i).c_str ());
4695 
4696 
4697  // we have a function instead of a variable
4698  handle_parenthesis (context, input, i, lastValidInput, handled,
4699  accumulated_precedence, substr_list);
4700 
4701  if (!substr_list.empty ())
4702  {
4703  body = substr_list.back ();
4704  substr_list.clear ();
4705  }
4706  }
4707 
4708  // now, see if we can locate a body for the for loop
4709  if (body)
4710  {
4711  Assignment * assignment = dynamic_cast <Assignment *> (body);
4712  if (assignment)
4713  {
4714  Variable * variable_node = dynamic_cast <Variable *> (assignment->left_);
4715  Number * number = dynamic_cast <Number *> (assignment->right_);
4716 
4717  if (variable_node && number)
4718  {
4720  "KaRL: For loop: Body is a simple assignment of variable %s to %s\n",
4721  variable_node->key_.c_str (), number->item_.to_string ().c_str ());
4722  }
4723  else
4724  {
4726  "KaRL: For loop: For loop has a complex body\n");
4727  }
4728  }
4729 
4730  precondition->right_ = user_pre;
4733 
4734  // optimize postcondition
4735  Number * number = dynamic_cast <Number *> (user_post);
4736  if (number)
4737  {
4738  post_val = number->item_;
4739  delete number;
4740  user_post = 0;
4741  }
4742 
4743  // optimize condition
4744  number = dynamic_cast <Number *> (user_cond);
4745  if (number)
4746  {
4747  cond_val = number->item_;
4748  delete number;
4749  user_cond = 0;
4750  }
4751 
4752  int compare_type (0);
4753 
4754  if (equal_to)
4755  compare_type = 1;
4756 
4757  Variable * var_node = new Variable (variable, context);
4758 
4759  VariableIncrement * postcondition = new VariableIncrement (var_node, post_val,
4760  user_post, context);
4761  postcondition->add_precedence (accumulated_precedence + FOR_LOOP_PRECEDENCE);
4762 
4763  VariableCompare * condition = new VariableCompare (var_node, cond_val,
4764  user_cond, compare_type, context);
4765  condition->add_precedence (accumulated_precedence + FOR_LOOP_PRECEDENCE);
4766 
4767  Symbol * op = new ForLoop (precondition, condition, postcondition, body, context);
4768  op->add_precedence (accumulated_precedence);
4769 
4770  precedence_insert (context, op, list);
4771 
4772  lastValidInput = 0;
4773  }
4774  else
4775  {
4776  // user forgot to specify a for loop body, so they apparently just want us to loop
4777  // the variable from the precondition to the condition. Since we assume the user
4778  // doesn't want a busy loop, which this is, we instead create an assignment for
4779  // the variable to equal the condition and clean up the pointers
4780 
4781  // if they specified a ']', they actually want something 1 greater than the condition
4782  if (equal_to)
4783  {
4784  Number * number = dynamic_cast <Number *> (user_cond);
4785 
4786  if (number)
4787  ++number->item_;
4788  else
4789  {
4790  // if it wasn't already a number, then it must be something more complex. We'll
4791  // just add one to it and see if the prune () method can optimize it a bit.
4792  Add * add = new Add (context.get_logger ());
4793  add->left_ = new Number (context.get_logger (),
4795  add->right_ = user_cond;
4796  user_cond = add;
4797  }
4798  }
4799 
4800  delete precondition->right_;
4801  precondition->right_ = user_cond;
4802  precondition->add_precedence (accumulated_precedence);
4803 
4804  precedence_insert (context, precondition, list);
4805 
4806  lastValidInput = 0;
4807  }
4808 }
4809 
4810 // inserts a variable (leaf node / number) into the parse tree
4811 void
4814 const std::string &input,
4815 std::string::size_type &i,
4816 int & accumulated_precedence,
4817 ::std::list<Symbol *>& list,
4818 Symbol *& lastValidInput)
4819 {
4820  // build a potential variable name (this could also be a function)
4821  std::string::size_type j = 1;
4822 
4823  for (; i + j < input.length () && is_alphanumeric (input[i + j]); ++j)
4824  continue;
4825 
4826  // the variable or function name is stored in input.substr (i,j)
4827  // is the next char a parenthesis?
4828 
4829  std::string name = input.substr (i, j);
4830 
4831  i += j;
4832 
4833  // eat up whitespace so we can check for a parenthesis (function)
4834  for (; i < input.length () && is_whitespace (input[i]); ++i);
4835 
4836  if (i < input.length () && input[i] == '(')
4837  {
4838  // save the function name and update i
4839  Function * function = new Function (name, context);
4840  function->add_precedence (accumulated_precedence);
4841 
4842  bool handled = false;
4843 
4844  ::std::list<Symbol *> param_list;
4845 
4846  int local_precedence = 0;
4847  Symbol * local_last_valid = 0;
4848 
4849  ++i;
4850 
4851  // we have a function instead of a variable
4852  handle_parenthesis (context, input, i, local_last_valid, handled,
4853  local_precedence, param_list, true);
4854 
4855  //if (param_list.size () > 0)
4856  // function->right_ = param_list.back ();
4857 
4858  function->nodes_.resize (param_list.size ());
4859  int cur = 0;
4860 
4861  for (::std::list<Symbol *>::iterator arg = param_list.begin ();
4862  arg != param_list.end (); ++arg, ++cur)
4863  {
4864  function->nodes_[cur] = (*arg)->build ();
4865  }
4866 
4867  //function->right_ = new List (context);
4868 
4869  precedence_insert (context, function, list);
4870  lastValidInput = 0;
4871  }
4872  else if (i < input.length () && input[i] == '[')
4873  {
4874  ++i;
4875  handle_for_loop (context, name, input, i, accumulated_precedence,
4876  list, lastValidInput);
4877  }
4878  else
4879  {
4880  Symbol * op = new Variable (name, context);
4881  op->add_precedence (accumulated_precedence);
4882 
4883  // check for post increments and decrements
4884  if (i + 1 < input.size ())
4885  {
4886  if (input[i] == '+' && input[i + 1] == '+')
4887  {
4888  Symbol * variable = op;
4889  op = new Postincrement (context.get_logger ());
4890  op->add_precedence (accumulated_precedence);
4891  op->right_ = variable;
4892  i += 2;
4893  }
4894  else if (input[i] == '-' && input[i + 1] == '-')
4895  {
4896  Symbol * variable = op;
4897  op = new Postdecrement (context.get_logger ());
4898  op->add_precedence (accumulated_precedence);
4899  op->right_ = variable;
4900  i += 2;
4901  }
4902  }
4903 
4904  lastValidInput = op;
4905 
4906  precedence_insert (context, op, list);
4907  }
4908 }
4909 
4910 // inserts a leaf node / number into the parse tree
4911 void
4913  char opener,
4914  knowledge::ThreadSafeContext & context,
4915  const std::string &input,
4916  std::string::size_type &i, int & accumulated_precedence,
4917  ::std::list<madara::expression::Symbol *>& list,
4918  madara::expression::Symbol *& lastValidInput)
4919 {
4920  std::string::size_type j = 0;
4921  Number * number = 0;
4922 
4923  for (; i + j < input.length (); ++j)
4924  {
4925  if (input[i + j] == opener && input[i + j - 1] != '\\')
4926  break;
4927  }
4928 
4929  number = new Number (context.get_logger (), input.substr (i, j));
4930 
4931  number->add_precedence (accumulated_precedence);
4932 
4933  lastValidInput = number;
4934 
4935  // update i to next char for main loop or handle parenthesis.
4936 
4937  i += j + 1;
4938 
4939  precedence_insert (context, number, list);
4940 }
4941 
4942 // inserts a variable (leaf node / number) into the parse tree
4943 void
4946  const std::string &input,
4947  std::string::size_type &i,
4948  int & accumulated_precedence,
4949  ::std::list<Symbol *>& list,
4950  Symbol *& lastValidInput)
4951 {
4952  // build a potential variable name (this could also be a function)
4953  std::string::size_type j = 1;
4954 
4955  for (; i + j < input.length () && is_alphanumeric (input[i + j]); ++j)
4956  continue;
4957 
4958  // the variable or function name is stored in input.substr (i,j)
4959  // is the next char a parenthesis?
4960 
4961  std::string name = input.substr (i, j);
4962 
4963  i += j;
4964 
4965  //MADARA_DEBUG (MADARA_LOG_EMERGENCY, (LM_ERROR, DLINFO
4966  // "Checking %s, before is_whitespace. i=%d, j=%" PRIu64 "\n",
4967  // name.c_str (), i, j));
4968 
4969  // eat up whitespace so we can check for a parenthesis (function)
4970  for (; i < input.length () && is_whitespace (input[i]); ++i);
4971 
4972  //MADARA_DEBUG (MADARA_LOG_EMERGENCY, (LM_ERROR, DLINFO
4973  // "Checking %s, after is_whitespace. i=%d, j=%" PRIu64 "\n",
4974  // name.c_str (), i, j));
4975 
4976  if (i < input.length () && input[i] == '(')
4977  {
4978  // save the function name and update i
4979  SystemCall * call = 0;
4980  char first_char = 0;
4981 
4982  if (name.size () > 1)
4983  {
4984  first_char = name[1];
4985  }
4986 
4987  switch (first_char)
4988  {
4989  case 'b':
4990  if (name == "#buffer")
4991  {
4992  call = new ToBuffer (context);
4993  }
4994  break;
4995  case 'c':
4996  if (name == "#clear_var" || name == "#clear_variable")
4997  {
4998  call = new ClearVariable (context);
4999  }
5000  else if (name == "#cos")
5001  {
5002  call = new Cos (context);
5003  }
5004  break;
5005  case 'd':
5006  if (name == "#delete_var" || name == "#delete_variable")
5007  {
5008  call = new DeleteVariable (context);
5009  }
5010  else if (name == "#double")
5011  {
5012  call = new ToDouble (context);
5013  }
5014  else if (name == "#doubles")
5015  {
5016  call = new ToDoubles (context);
5017  }
5018  break;
5019  case 'e':
5020  if (name == "#eval" || name == "#evaluate")
5021  {
5022  call = new Eval (context);
5023  }
5024  else if (name == "#expand" || name == "#expand_statement")
5025  {
5026  call = new ExpandStatement (context);
5027  }
5028  else if (name == "#expand_env" || name == "#expand_envs")
5029  {
5030  call = new ExpandEnv (context);
5031  }
5032  break;
5033  case 'f':
5034  if (name == "#fragment")
5035  {
5036  call = new Fragment (context);
5037  }
5038  else if (name == "#fixed")
5039  {
5040  call = new SetFixed (context);
5041  }
5042  break;
5043  case 'g':
5044  if (name == "#get_clock")
5045  {
5046  call = new GetClock (context);
5047  }
5048  else if (name == "#get_time" || name == "#get_time_ns" || name == "#get_time_nano")
5049  {
5050  call = new GetTime (context);
5051  }
5052  else if (name == "#get_time_seconds" || name == "#get_time_s")
5053  {
5054  call = new GetTimeSeconds (context);
5055  }
5056  break;
5057  case 'i':
5058  if (name == "#integer")
5059  {
5060  call = new ToInteger (context);
5061  }
5062  else if (name == "#integers")
5063  {
5064  call = new ToIntegers (context);
5065  }
5066  break;
5067  case 'l':
5068  if (name == "#log_level")
5069  {
5070  call = new LogLevel (context);
5071  }
5072  break;
5073  case 'p':
5074  if (name == "#pow")
5075  {
5076  call = new Power (context);
5077  }
5078  else if (name == "#print")
5079  {
5080  call = new Print (context);
5081  }
5082  else if (name == "#print_system_calls" || name == "#print_system_call")
5083  {
5084  call = new PrintSystemCalls (context);
5085  }
5086  else if (name == "#precision")
5087  {
5088  call = new SetPrecision (context);
5089  }
5090  break;
5091  case 'r':
5092  if (name == "#rand_double")
5093  {
5094  call = new RandDouble (context);
5095  }
5096  else if (name == "#rand_int" || name == "#rand_integer")
5097  {
5098  call = new RandInt (context);
5099  }
5100  else if (name == "#read_file")
5101  {
5102  call = new ReadFile (context);
5103  }
5104  break;
5105  case 's':
5106  if (name == "#scientific")
5107  {
5108  call = new SetScientific (context);
5109  }
5110  else if (name == "#set_clock")
5111  {
5112  call = new SetClock (context);
5113  }
5114  else if (name == "#set_fixed")
5115  {
5116  call = new SetFixed (context);
5117  }
5118  else if (name == "#set_precision")
5119  {
5120  call = new SetPrecision (context);
5121  }
5122  else if (name == "#set_scientific")
5123  {
5124  call = new SetScientific (context);
5125  }
5126  else if (name == "#sin")
5127  {
5128  call = new Sin (context);
5129  }
5130  else if (name == "#size")
5131  {
5132  call = new Size (context);
5133  }
5134  else if (name == "#sleep")
5135  {
5136  call = new Sleep (context);
5137  }
5138  else if (name == "#sqrt")
5139  {
5140  call = new SquareRoot (context);
5141  }
5142  else if (name == "#string")
5143  {
5144  call = new ToString (context);
5145  }
5146  break;
5147  case 't':
5148  if (name == "#tan")
5149  {
5150  call = new Tan (context);
5151  }
5152  else if (name == "#to_buffer")
5153  {
5154  call = new ToBuffer (context);
5155  }
5156  else if (name == "#to_double")
5157  {
5158  call = new ToDouble (context);
5159  }
5160  else if (name == "#to_doubles")
5161  {
5162  call = new ToDoubles (context);
5163  }
5164  else if (name == "#to_host_dirs")
5165  {
5166  call = new ToHostDirs (context);
5167  }
5168  else if (name == "#to_integer")
5169  {
5170  call = new ToInteger (context);
5171  }
5172  else if (name == "#to_integers")
5173  {
5174  call = new ToIntegers (context);
5175  }
5176  else if (name == "#to_string")
5177  {
5178  call = new ToString (context);
5179  }
5180  else if (name == "#type")
5181  {
5182  call = new Type (context);
5183  }
5184  break;
5185  case 'w':
5186  if (name == "#write_file")
5187  {
5188  call = new WriteFile (context);
5189  }
5190  break;
5191  default:
5193  "System call %s is unsupported in this version of MADARA, "
5194  "defaulting to print_system_calls help menu.\n", name.c_str ());
5195 
5196  call = new PrintSystemCalls (context);
5197  }
5198 
5199  call->add_precedence (accumulated_precedence);
5200 
5201  bool handled = false;
5202 
5203  ::std::list<Symbol *> param_list;
5204 
5205  ++i;
5206 
5207  // we have a function instead of a variable
5208  handle_parenthesis (context, input, i, lastValidInput, handled,
5209  accumulated_precedence, param_list, true);
5210 
5211  call->nodes_.resize (param_list.size ());
5212  int cur = 0;
5213 
5214  for (::std::list<Symbol *>::iterator arg = param_list.begin ();
5215  arg != param_list.end (); ++arg, ++cur)
5216  {
5217  call->nodes_[cur] = (*arg)->build ();
5218  }
5219 
5220  precedence_insert (context, call, list);
5221  lastValidInput = 0;
5222  }
5223  else
5224  {
5226  "System call %s does not have appropriate parentheses\n", name.c_str ());
5227  }
5228 }
5229 
5230 // inserts a leaf node / number into the parse tree
5231 void
5233  knowledge::ThreadSafeContext & context,
5234  const std::string &input,
5235  std::string::size_type &i,
5236  int & accumulated_precedence,
5237  ::std::list<madara::expression::Symbol *>& list,
5238  madara::expression::Symbol *& lastValidInput)
5239 {
5240  // merge all consecutive number chars into a single Number symbol,
5241  // eg '123' = int (123). Scope of j needs to be outside of the for
5242  // loop.
5243 
5244  std::string::size_type j = 1;
5245  Number * number = 0;
5246 
5247  for (; i + j <= input.length () && is_number (input[i + j]); ++j)
5248  continue;
5249 
5250  // do we have a float?
5251  if (i + j <= input.length () && input[i + j] == '.')
5252  {
5253  ++j;
5254  for (; i + j <= input.length () && is_number (input[i + j]); ++j)
5255  continue;
5256 
5257  // scientific notation
5258  if (i + j <= input.length () &&
5259  (input[i + j] == 'e' || input[i + j] == 'E'))
5260  {
5261  ++j;
5262  if (i + j <= input.length () &&
5263  (input[i + j] == '+' || input[i + j] == '-'))
5264  {
5265  ++j;
5266  }
5267 
5268  for (; i + j <= input.length () && is_number (input[i + j]); ++j)
5269  continue;
5270  }
5271 
5272  double new_number;
5273 
5274  std::stringstream buffer;
5275  buffer << input.substr (i, j);
5276  buffer >> new_number;
5277 
5278  number = new Number (context.get_logger (), new_number);
5279  }
5280  else
5281  {
5282  // we have an integer
5283 
5285 
5286  std::stringstream buffer;
5287  buffer << input.substr (i, j);
5288  buffer >> new_number;
5289 
5290  number = new Number (context.get_logger (), new_number);
5291  }
5292 
5293  number->add_precedence (accumulated_precedence);
5294 
5295  lastValidInput = number;
5296 
5297  // update i to next char for main loop or handle parenthesis.
5298 
5299  i += j;
5300 
5301  precedence_insert (context, number, list);
5302 }
5303 
5304 
5305 // inserts a multiplication or division into the parse tree
5306 void
5310 ::std::list<madara::expression::Symbol *>& list)
5311 {
5312  if (!list.empty ())
5313  {
5314  // if last element was a number, then make that our left_
5315 
5316  Symbol *parent = list.back ();
5317  Symbol *child = 0;
5318  Symbol *grandparent = 0;
5319 
5320  // check to see if op is an assignment or implication, which are treated
5321  // uniquely
5322  Assignment * op_assignment = dynamic_cast <Assignment *> (op);
5323  Implies * op_implies = dynamic_cast <Implies *> (op);
5324  UnaryOperator * op_unary = dynamic_cast <UnaryOperator *> (op);
5325 
5326  // move down the right side of the tree until we find either a null or
5327  // a precedence that is >= this operation's precedence. This puts us
5328  // in the situation that we know our op should be performed after child
5329  // or child should be null (assignment or implication not withstanding)
5330  for (child = parent->right_;
5331  child && child->precedence () < op->precedence ();
5332  child = child->right_)
5333  {
5334  grandparent = parent;
5335  parent = child;
5336  }
5337 
5338  // parent->precedence is < op->precedence at this point
5339 
5340  if (op_assignment || op_implies || op_unary)
5341  {
5342  // if we are an assignment, implies, or unary op, we actually
5343  // need this op to have slightly higher precedence (it needs to be
5344  // evaluated first). This situation is signified by something like this
5345  // var1 = var2 = var3 = 1. In the list, will be var1 = var2 = var3, so parent will be
5346  // and assignment, and parent left will be var1, right and child will be assignment
5347  // and it will have a left of var2
5348 
5349 
5350  for (child = parent->right_;
5351  child && child->precedence () <= op->precedence ();
5352  child = child->right_)
5353  {
5354  grandparent = parent;
5355  parent = child;
5356  }
5357  }
5358 
5359  // Now that we have our parent and child setup appropriately according
5360  // to precedence relationships, we should be able to modify or replace
5361  // the tree in the list
5362 
5363  if (parent->precedence () < op->precedence () ||
5364  (parent->precedence () == op->precedence () &&
5365  (op_assignment || op_implies || op_unary)))
5366  {
5367  // this op needs to be evaluated before the parent
5368 
5369  // first let's do some error checking, so we can give helpful compile errors
5370  Operator * parent_binary = dynamic_cast <Operator *> (parent);
5371  UnaryOperator * parent_unary = dynamic_cast <UnaryOperator *> (parent);
5372 
5373  // if the parent is a binary (like addition or &&), then it needs a left hand side
5374  // if it doesn't have this, let's report a warning and insert a Leaf Node with a value
5375  // of zero
5376  if (parent_binary && !parent->left_)
5377  {
5378  // try to give as specific message as possible
5379  Both * parent_both = dynamic_cast <Both *> (parent);
5380  if (parent_both)
5381  {
5383  "KARL COMPILE WARNING: Empty statements between ';' may"
5384  " cause slower execution, attempting to prune away the extra "
5385  "statement\n");
5386  }
5387  else
5388  {
5390  "KARL COMPILE WARNING: Binary operation has no left child. "
5391  "Inserting a zero\n");
5392 
5393  parent->left_ = new Number (context.get_logger (),
5395  }
5396  }
5397 
5398  // if the parent is a unary operator (like negate or not), then it should
5399  // NOT have a left child. This would only happen if someone input
5400  // something like 5 ! 3, which has no meaning. This is a compile error.
5401  if (parent_unary && parent->left_)
5402  {
5404  "KARL COMPILE ERROR: Unary operation shouldn't have a left child\n");
5405 
5406  exit (-1);
5407  }
5408 
5409  // if we've gotten to this point, then we need to
5410  // replace the child with ourself in the tree
5411  if (child)
5412  {
5413  if (op_unary)
5414  {
5415  // This is a compile error. Unary cannot have a left
5416  // child, and that is the only way that being at this
5417  // point would make sense.
5419  "KARL COMPILE ERROR: unary operation shouldn't have a left child\n");
5420 
5421  exit (-1);
5422  }
5423  else
5424  op->left_ = child;
5425  }
5426 
5427  parent->right_ = op;
5428  }
5429  else
5430  {
5431  // we are a lower precedence than our parent, so we need to replace
5432  // the tree in the list. This typically happens with assignment, implies,
5433  // logical operations (&&, ||) and equality checks
5434 
5435  op->left_ = parent;
5436 
5437  if (grandparent)
5438  grandparent->right_ = op;
5439  else
5440  {
5441  list.pop_back ();
5442  list.push_back (op);
5443  }
5444  }
5445  }
5446  else
5447  {
5448  list.push_back (op);
5449  }
5450 }
5451 
5452 void
5455 const std::string &input, std::string::size_type &i,
5456 madara::expression::Symbol *& lastValidInput,
5457 bool & handled, int & accumulated_precedence,
5458 ::std::list<madara::expression::Symbol *>& list,
5459 bool build_argument_list)
5460 {
5461  handled = false;
5462  if (is_number (input[i]))
5463  {
5464  handled = true;
5465  // leaf node
5466  number_insert (context, input, i, accumulated_precedence,
5467  list, lastValidInput);
5468  }
5469  else if (is_alphanumeric (input[i]))
5470  {
5471  handled = true;
5472  // variable leaf node
5473  variable_insert (context, input, i, accumulated_precedence,
5474  list, lastValidInput);
5475  }
5476  else if (is_string_literal (input[i]))
5477  {
5478  char opener = input[i];
5479  ++i;
5480  handled = true;
5481  // string
5482  string_insert (opener, context, input, i, accumulated_precedence,
5483  list, lastValidInput);
5484  }
5485  else if (i < input.length () && input[i] == '[')
5486  {
5487  // save the function name and update i
5488  ConstArray * object = new ConstArray (context);
5489  object->add_precedence (accumulated_precedence);
5490 
5491  bool handled = false;
5492 
5493  ::std::list<Symbol *> param_list;
5494 
5495  int local_precedence = 0;
5496  Symbol * local_last_valid = 0;
5497 
5498  ++i;
5499 
5500  // we have an array
5501  handle_array (context, input, i, local_last_valid, handled,
5502  local_precedence, param_list);
5503 
5504  object->nodes_.resize (param_list.size ());
5505  int cur = 0;
5506 
5507  for (::std::list<Symbol *>::iterator arg = param_list.begin ();
5508  arg != param_list.end (); ++arg, ++cur)
5509  {
5510  object->nodes_[cur] = (*arg)->build ();
5511  }
5512 
5513  precedence_insert (context, object, list);
5514  lastValidInput = 0;
5515  }
5516  else if (input[i] == '#')
5517  {
5518  handled = true;
5519  // variable leaf node
5520  system_call_insert (context, input, i, accumulated_precedence,
5521  list, lastValidInput);
5522  }
5523  else if (input[i] == '+')
5524  {
5525  handled = true;
5526  Symbol * op = 0;
5527 
5528  // is this a predecrement?
5529  if (i + 1 < input.size () && input[i + 1] == '+')
5530  {
5531  op = new Preincrement (context.get_logger ());
5532  ++i;
5533  }
5534  // is this an atomic increment?
5535  else if (i + 1 < input.size () && input[i + 1] == '=')
5536  {
5537  Variable * var = dynamic_cast <Variable *> (lastValidInput);
5538  ArrayRef * array_ref = dynamic_cast <ArrayRef *> (lastValidInput);
5539  if (var || array_ref)
5540  op = new VariableIncrement (lastValidInput,
5541  madara::knowledge::KnowledgeRecord (), 0, context);
5542  else
5543  {
5544  // major error here. The left hand side must be a variable
5545  op = new VariableIncrement (new Variable (".MADARA_I", context),
5546  madara::knowledge::KnowledgeRecord (), 0, context);
5547 
5549  "KARL COMPILE WARNING (+=): "
5550  "Assignments must have a variable left hand side. Using .MADARA_I by "
5551  "default, but this is likely a major error in the expression.\n");
5552  }
5553  ++i;
5554  }
5555  else
5556  op = new Add (context.get_logger ());
5557 
5558  // insert the op according to left-to-right relationships
5559  op->add_precedence (accumulated_precedence);
5560  lastValidInput = 0;
5561  precedence_insert (context, op, list);
5562  ++i;
5563  }
5564  else if (input[i] == '-')
5565  {
5566  handled = true;
5567  Symbol * op = 0;
5568 
5569  // is this a predecrement?
5570  if (i + 1 < input.size () && input[i + 1] == '-')
5571  {
5572  op = new Predecrement (context.get_logger ());
5573  ++i;
5574  }
5575  // is this an atomic decrement?
5576  else if (i + 1 < input.size () && input[i + 1] == '=')
5577  {
5578  Variable * var = dynamic_cast <Variable *> (lastValidInput);
5579  ArrayRef * array_ref = dynamic_cast <ArrayRef *> (lastValidInput);
5580  if (var || array_ref)
5581  {
5582  op = new VariableDecrement (lastValidInput, madara::knowledge::KnowledgeRecord (),
5583  0, context);
5584  }
5585  else
5586  {
5587  // major error here. The left hand side must be a variable
5588  op = new VariableDecrement (new Variable (".MADARA_I", context),
5589  madara::knowledge::KnowledgeRecord (), 0, context);
5590 
5592  "KARL COMPILE WARNING (-=): "
5593  "Assignments must have a variable left hand side. Using .MADARA_I by "
5594  "default, but this is likely a major error in the expression.\n");
5595  }
5596  ++i;
5597  }
5598  // Negate
5599  else if (!lastValidInput)
5600  op = new Negate (context.get_logger ());
5601  // Subtract
5602  else
5603  op = new Subtract (context.get_logger ());
5604 
5605  // insert the op according to left-to-right relationships
5606  lastValidInput = 0;
5607  op->add_precedence (accumulated_precedence);
5608  precedence_insert (context, op, list);
5609  ++i;
5610  }
5611  else if (input[i] == '*')
5612  {
5613  handled = true;
5614  Symbol * op = 0;
5615 
5616  // is this an atomic multiply?
5617  if (i + 1 < input.size () && input[i + 1] == '=')
5618  {
5619  Variable * var = dynamic_cast <Variable *> (lastValidInput);
5620  ArrayRef * array_ref = dynamic_cast <ArrayRef *> (lastValidInput);
5621  if (var || array_ref)
5622  op = new VariableMultiply (lastValidInput, madara::knowledge::KnowledgeRecord (),
5623  0, context);
5624  else
5625  {
5626  // major error here. The left hand side must be a variable
5627  op = new VariableMultiply (new Variable (".MADARA_I", context),
5628  madara::knowledge::KnowledgeRecord (), 0, context);
5629 
5631  "KARL COMPILE WARNING (*=): "
5632  "Assignments must have a variable left hand side. Using .MADARA_I by "
5633  "default, but this is likely a major error in the expression.\n");
5634  }
5635  ++i;
5636  }
5637  // multiplication operation
5638  else
5639  op = new Multiply (context.get_logger ());
5640 
5641  // insert the op according to precedence relationships
5642  op->add_precedence (accumulated_precedence);
5643  lastValidInput = 0;
5644  precedence_insert (context, op, list);
5645  ++i;
5646  }
5647  else if (input[i] == '%')
5648  {
5649  // multiplication operation
5650  handled = true;
5651  Modulus *op = new Modulus (context.get_logger ());
5652 
5653  // insert the op according to precedence relationships
5654  op->add_precedence (accumulated_precedence);
5655  lastValidInput = 0;
5656  precedence_insert (context, op, list);
5657  ++i;
5658  }
5659  else if (input[i] == '/')
5660  {
5661  // is this a one line comment?
5662  if (i + 1 < input.size () && input[i + 1] == '/')
5663  {
5664  // we have a one line comment
5665  for (; i < input.size () && input[i] != '\n'; ++i);
5666  }
5667  // is this a multi-line comment?
5668  else if (i + 1 < input.size () && input[i + 1] == '*')
5669  {
5670  // find the matching close
5671  std::string::size_type found = input.find ("*/", i + 1);
5672 
5673  // if we were able to find the matching close,
5674  // then set i to the '/' in '*/'
5675  if (found != std::string::npos)
5676  i = found + 1;
5677 
5678  // otherwise, the user apparently wanted to
5679  // comment out the rest of the file
5680  else
5681  i = input.size ();
5682  }
5683  // is this an atomic decrement?
5684  else
5685  {
5686  handled = true;
5687  // division operation
5688  Symbol * op = 0;
5689 
5690  // atomic division?
5691  if (i + 1 < input.size () && input[i + 1] == '=')
5692  {
5693  Variable * var = dynamic_cast <Variable *> (lastValidInput);
5694  ArrayRef * array_ref = dynamic_cast <ArrayRef *> (lastValidInput);
5695  if (var || array_ref)
5696  op = new VariableDivide (lastValidInput, madara::knowledge::KnowledgeRecord (), 0, context);
5697  else
5698  {
5699  // major error here. The left hand side must be a variable
5700  op = new VariableDivide (new Variable (".MADARA_I", context),
5701  madara::knowledge::KnowledgeRecord (), 0, context);
5702 
5704  "KARL COMPILE WARNING (/=): "
5705  "Assignments must have a variable left hand side. Using .MADARA_I by "
5706  "default, but this is likely a major error in the expression.\n");
5707  }
5708  ++i;
5709  }
5710  else
5711  op = new Divide (context.get_logger ());
5712 
5713  op->add_precedence (accumulated_precedence);
5714  lastValidInput = 0;
5715  precedence_insert (context, op, list);
5716  }
5717  ++i;
5718  }
5719  else if (input[i] == '=')
5720  {
5721  handled = true;
5722  Symbol * op = 0;
5723 
5724  // is this an equality?
5725  if (i + 1 < input.size () && input[i + 1] == '=')
5726  {
5727  op = new Equality (context.get_logger ());
5728  op->add_precedence (accumulated_precedence);
5729 
5730  lastValidInput = 0;
5731  ++i;
5732 
5733  // insert the op according to precedence relationships
5734  precedence_insert (context, op, list);
5735  }
5736  // is this an implication?
5737  else if (i + 1 < input.size () && input[i + 1] == '>')
5738  {
5739  op = new Implies (context.get_logger ());
5740  op->add_precedence (accumulated_precedence);
5741 
5742  lastValidInput = 0;
5743  ++i;
5744 
5745  // insert the op according to precedence relationships
5746  precedence_insert (context, op, list);
5747  }
5748  // must be an assignment then
5749  else
5750  {
5751  op = new Assignment (context.get_logger ());
5752  op->add_precedence (accumulated_precedence);
5753 
5754  lastValidInput = 0;
5755 
5756  // insert the op according to precedence relationships
5757  // assignment_insert (op, list);
5758  precedence_insert (context, op, list);
5759  }
5760  ++i;
5761  }
5762  else if (input[i] == '!')
5763  {
5764  handled = true;
5765  Symbol * op = 0;
5766 
5767  // is this an inequality?
5768  if (i + 1 < input.size () && input[i + 1] == '=')
5769  {
5770  op = new Inequality (context.get_logger ());
5771  ++i;
5772  }
5773  // must be a logical not then
5774  else
5775  {
5776  op = new Not (context.get_logger ());
5777  }
5778 
5779  // insert the op according to precedence relationships
5780  op->add_precedence (accumulated_precedence);
5781  lastValidInput = 0;
5782  precedence_insert (context, op, list);
5783  ++i;
5784  }
5785  // square root is ASCII 251 (UTF 8 format)
5786  else if ((uint8_t)input[i] == 251)
5787  {
5788  handled = true;
5789  Symbol * op = 0;
5790 
5791  op = new SquareRootUnary (context.get_logger ());
5792 
5793  // insert the op according to precedence relationships
5794  op->add_precedence (accumulated_precedence);
5795  lastValidInput = 0;
5796  precedence_insert (context, op, list);
5797  ++i;
5798  }
5799  else if (input[i] == '&')
5800  {
5801  // is this a logical and?
5802  if (i + 1 < input.size () && input[i + 1] == '&')
5803  {
5804  handled = true;
5805  Symbol * op = new And (context.get_logger ());
5806  ++i;
5807 
5808  // insert the op according to precedence relationships
5809  op->add_precedence (accumulated_precedence);
5810  lastValidInput = 0;
5811  precedence_insert (context, op, list);
5812  }
5813  else
5814  {
5815  // error. We currently don't allow logical and (A & B)
5817  "KARL COMPILE ERROR: "
5818  "Logical And (&) not available. " \
5819  "You may want to use && instead in %s.\n", input.c_str ());
5820  }
5821  ++i;
5822  }
5823  else if (input[i] == '|')
5824  {
5825  // is this a logical and?
5826  if (i + 1 < input.size () && input[i + 1] == '|')
5827  {
5828  handled = true;
5829  Symbol * op = new Or (context.get_logger ());
5830  ++i;
5831 
5832  // insert the op according to precedence relationships
5833  op->add_precedence (accumulated_precedence);
5834  lastValidInput = 0;
5835  precedence_insert (context, op, list);
5836  }
5837  else
5838  {
5839  // error. We don't currently support logical or
5841  "KARL COMPILE ERROR: "
5842  "Logical And (|) not available. " \
5843  "You may want to use || instead in %s.\n", input.c_str ());
5844  }
5845  ++i;
5846  }
5847  else if (input[i] == ';')
5848  {
5849  handled = true;
5850  Symbol * op = 0;
5851 
5852  // is this a logical and?
5853  if (i + 1 < input.size () && input[i + 1] == '>')
5854  {
5855  op = new ReturnRight (context.get_logger ());
5856  ++i;
5857  }
5858  else
5859  {
5860  op = new Both (context.get_logger ());
5861  }
5862 
5863  // insert the op according to precedence relationships
5864  op->add_precedence (accumulated_precedence);
5865  lastValidInput = 0;
5866  precedence_insert (context, op, list);
5867  ++i;
5868  }
5869  else if (input[i] == ',')
5870  {
5871  if (build_argument_list)
5872  return;
5873 
5874  handled = true;
5875  Symbol * op = new Sequence (context.get_logger ());
5876 
5877  // insert the op according to precedence relationships
5878  op->add_precedence (accumulated_precedence);
5879  lastValidInput = 0;
5880  precedence_insert (context, op, list);
5881  ++i;
5882  }
5883  else if (input[i] == '<')
5884  {
5885  handled = true;
5886  Symbol * op = 0;
5887 
5888  // is this a less than or equal to operator?
5889  if (i + 1 < input.size () && input[i + 1] == '=')
5890  {
5891  op = new LessThanEqual (context.get_logger ());
5892  ++i;
5893  }
5894  // must be a less than operator
5895  else
5896  op = new LessThan (context.get_logger ());
5897 
5898  // insert the op according to precedence relationships
5899  op->add_precedence (accumulated_precedence);
5900  lastValidInput = 0;
5901  precedence_insert (context, op, list);
5902  ++i;
5903  }
5904  else if (input[i] == '>')
5905  {
5906  handled = true;
5907  Symbol * op = 0;
5908 
5909  // is this a less than or equal to operator?
5910  if (i + 1 < input.size () && input[i + 1] == '=')
5911  {
5912  op = new GreaterThanEqual (context.get_logger ());
5913  ++i;
5914  }
5915  // must be a less than operator
5916  else
5917  op = new GreaterThan (context.get_logger ());
5918 
5919  // insert the op according to precedence relationships
5920  op->add_precedence (accumulated_precedence);
5921  lastValidInput = 0;
5922  precedence_insert (context, op, list);
5923  ++i;
5924  }
5925  else if (input[i] == '(')
5926  {
5927  handled = true;
5928  ++i;
5929  handle_parenthesis (context, input, i, lastValidInput,
5930  handled, accumulated_precedence, list);
5931  }
5932  else if (input[i] == '\t' || input[i] == ' '
5933  || input[i] == '\r' || input[i] == '\n')
5934  {
5935  handled = true;
5936  ++i;
5937  // skip whitespace
5938  }
5939 }
5940 
5941 
5942 void
5945 const std::string &input, std::string::size_type &i,
5946 madara::expression::Symbol *& lastValidInput,
5947 bool & handled, int & accumulated_precedence,
5948 ::std::list<madara::expression::Symbol *>& master_list)
5949 {
5950  /* handle parenthesis is a lot like handling a new interpret.
5951  the difference is that we have to worry about how the calling
5952  function has its list setup */
5953 
5954  accumulated_precedence += PARENTHESIS_PRECEDENCE;
5955  int initial_precedence = accumulated_precedence;
5956 
5957  ::std::list<Symbol *> list;
5958 
5959  handled = false;
5960  bool closed = false;
5961  while (i < input.length ())
5962  {
5963  main_loop (context, input, i, lastValidInput,
5964  handled, accumulated_precedence, list, true);
5965 
5966  if (input[i] == ']')
5967  {
5968  handled = true;
5969  closed = true;
5970  ++i;
5971  accumulated_precedence -= PARENTHESIS_PRECEDENCE;
5972  break;
5973  }
5974  else if (input[i] == ',')
5975  {
5976  ++i;
5977  while (list.size ())
5978  {
5979  master_list.push_back (list.back ());
5980  list.pop_back ();
5981  }
5982  accumulated_precedence = initial_precedence;
5983  }
5984  else if (i == input.length () - 1)
5985  {
5986  break;
5987  }
5988  }
5989 
5990  if (!closed)
5991  {
5993  "KARL COMPILE ERROR: "
5994  "Forgot to close parenthesis in %s.\n", input.c_str ());
5995  }
5996 
5997  if (list.size () > 0)
5998  {
5999  if (list.size () > 1)
6000  {
6002  "KARL COMPILE ERROR: "
6003  "A parenthesis was closed, leaving multiple list items (there should "
6004  "be a max of 1) in %s.\n", input.c_str ());
6005  }
6006 
6007  while (list.size ())
6008  {
6009  master_list.push_back (list.back ());
6010  list.pop_back ();
6011  }
6012  }
6013 
6014  list.clear ();
6015 }
6016 
6017 
6018 
6019 void
6022  const std::string &input, std::string::size_type &i,
6023  madara::expression::Symbol *& lastValidInput,
6024  bool & handled, int & accumulated_precedence,
6025  ::std::list<madara::expression::Symbol *>& master_list,
6026  bool build_argument_list)
6027 {
6028  /* handle parenthesis is a lot like handling a new interpret.
6029  the difference is that we have to worry about how the calling
6030  function has its list setup */
6031 
6032  accumulated_precedence += PARENTHESIS_PRECEDENCE;
6033  int initial_precedence = accumulated_precedence;
6034 
6035  ::std::list<Symbol *> list;
6036 
6037  handled = false;
6038  bool closed = false;
6039  while (i < input.length ())
6040  {
6041  main_loop (context, input, i, lastValidInput,
6042  handled, accumulated_precedence, list, build_argument_list);
6043 
6044  if (input[i] == ')')
6045  {
6046  handled = true;
6047  closed = true;
6048  ++i;
6049  accumulated_precedence -= PARENTHESIS_PRECEDENCE;
6050  break;
6051  }
6052  else if (build_argument_list && input[i] == ',')
6053  {
6054  ++i;
6055  while (list.size ())
6056  {
6057  master_list.push_back (list.back ());
6058  list.pop_back ();
6059  }
6060  accumulated_precedence = initial_precedence;
6061  }
6062  else if (i == input.length () - 1)
6063  {
6064  break;
6065  }
6066  }
6067 
6068  if (!build_argument_list && !closed)
6069  {
6071  "KARL COMPILE ERROR: "
6072  "Forgot to close parenthesis in %s.\n", input.c_str ());
6073  }
6074 
6075  if (!build_argument_list && master_list.size () > 0 && list.size () > 0)
6076  {
6077  Symbol * lastSymbol = master_list.back ();
6078  Operator * op = dynamic_cast <Operator *> (lastSymbol);
6079  UnaryOperator * unary = dynamic_cast < UnaryOperator * >
6080  (lastSymbol);
6081 
6082 
6083  // is it a node with 2 children?
6084  if (op || unary)
6085  {
6086  precedence_insert (context, list.back (), master_list);
6087  }
6088  else
6089  {
6090  // is it a terminal node (Number)
6091  // error
6092  }
6093  }
6094  else if (list.size () > 0)
6095  {
6096  if (list.size () > 1)
6097  {
6099  "KARL COMPILE ERROR: "
6100  "A parenthesis was closed, leaving multiple list items (there should "
6101  "be a max of 1) in %s.\n", input.c_str ());
6102  }
6103 
6104  while (list.size ())
6105  {
6106  master_list.push_back (list.back ());
6107  list.pop_back ();
6108  }
6109  }
6110 
6111  list.clear ();
6112 }
6113 
6114 // converts a string and context into a parse tree, and builds an
6115 // expression tree out of the parse tree
6119  const std::string &input)
6120 {
6121  // return the cached expression tree if it exists
6122  ExpressionTreeMap::const_iterator found = cache_.find (input);
6123  if (found != cache_.end ())
6124  return found->second;
6125 
6126  ::std::list<Symbol *> list;
6127  //list.clear ();
6128  Symbol * lastValidInput = 0;
6129  bool handled = false;
6130  int accumulated_precedence = 0;
6131  std::string::size_type last_i = 0;
6132 
6133  for (std::string::size_type i = 0;
6134  i < input.length ();)
6135  {
6136  // we took out the loop update from the for loop
6137  // and the main_loop or handle_parenthesis call
6138  // should now take care of this.
6139  main_loop (context, input, i, lastValidInput,
6140  handled, accumulated_precedence, list);
6141 
6142  if (i == last_i)
6143  {
6144  if (input[i] == ')')
6145  {
6147  "KARL COMPILE ERROR: "
6148  "You have included too many closing parentheses in %s \n",
6149  input.c_str ());
6150  }
6151  else
6152  {
6154  "KARL COMPILE ERROR: "
6155  "Compilation is spinning at %d in %s. Char is %c\n",
6156  i, input.c_str (), input[i]);
6157  }
6158  break;
6159  }
6160  else
6161  last_i = i;
6162 
6163  // store last valid input symbol. this is useful to the '-' operator
6164  // and will help us determine if '-' is a subtraction or a negation
6165  //if (input[i] != ' ' && input[i] != '\n')
6166  // lastValidInput = input[i];
6167  }
6168 
6169  // if the list has an element in it, then return the back of the list.
6170  if (!list.empty ())
6171  {
6172  // Invoke a recursive ExpressionTree build starting with the root
6173  // symbol. This is an example of the builder pattern. See pg 97
6174  // in GoF book.
6175 
6176  ExpressionTree tree (context.get_logger (),
6177  list.back ()->build (), false);
6178 
6179  // optimize the tree
6180  tree.prune ();
6181  delete list.back ();
6182 
6183  // store this optimized tree into cached memory
6184  cache_[input] = tree;
6185 
6186  return tree;
6187  }
6188 
6189  // If we reach this, we didn't have any symbols.
6190  return ExpressionTree (context.get_logger ());
6191 }
6192 
6193 #endif // _MADARA_NO_KARL_
6194 
6195 #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 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
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
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
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
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
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
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
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::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:35
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
static constexpr struct madara::knowledge::tags::string_t string
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
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
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.