Nicolas Winkler hace 5 años
padre
commit
40fe3dc39f
Se han modificado 3 ficheros con 115 adiciones y 26 borrados
  1. 1 1
      Almond.cpp
  2. 16 0
      libmandel/include/IterationFormula.h
  3. 98 25
      libmandel/src/IterationFormula.cpp

+ 1 - 1
Almond.cpp

@@ -26,7 +26,7 @@ Almond::Almond(QWidget* parent) :
 {
     ui.setupUi(this);
 
-    auto form = mnd::parse("123");
+    auto form = mnd::parse("92 + 2");
     ::exit(0);
 
     mw = std::make_unique<MandelWidget>(mandelContext,

+ 16 - 0
libmandel/include/IterationFormula.h

@@ -29,6 +29,8 @@ namespace mnd
     >;
 
     std::unique_ptr<Expression> parse(const std::string& formula);
+
+    std::string toString(const mnd::Expression&);
 }
 
 
@@ -44,6 +46,9 @@ struct mnd::Constant
     inline Constant(double value) :
         value{ value }
     {}
+    inline Constant() :
+        value{ 1010 }
+    {}
 };
 
 
@@ -56,6 +61,9 @@ struct mnd::Variable
 struct mnd::UnaryOperation
 {
     std::unique_ptr<Expression> operand;
+    /*inline UnaryOperation(const UnaryOperation& other) :
+        operand{ std::make_unique<Expression>(*other.operand) }
+    {}*/
 };
 
 
@@ -63,6 +71,10 @@ struct mnd::BinaryOperation
 {
     std::unique_ptr<Expression> left;
     std::unique_ptr<Expression> right;
+    /*inline BinaryOperation(const BinaryOperation& other) :
+        left{ std::make_unique<Expression>(*other.left) },
+        right{ std::make_unique<Expression>(*other.right) }
+    {}*/
 };
 
 
@@ -87,6 +99,10 @@ struct mnd::Pow : mnd::BinaryOperation
 };
 
 
+namespace mnd
+{
+}
+
 
 #endif // MANDEL_ITERATIONFORMULA_H
 

+ 98 - 25
libmandel/src/IterationFormula.cpp

@@ -1,7 +1,14 @@
 #include "IterationFormula.h"
 #include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/qi_action.hpp>
 #include <boost/phoenix/object/construct.hpp>
+#include <boost/phoenix/bind.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_fusion.hpp>
+#include <boost/spirit/include/phoenix_stl.hpp>
 #include <iostream>
+#include <sstream>
 #include <iomanip>
 
 using namespace mnd;
@@ -23,28 +30,32 @@ void PhraseParseOrDie(
     }
 }
 
-int simple(int a) {
+
+/*
+void simple(int& a) {
     printf("simple: %d\n", a);
-    return a;
+    a = a;
 }
 
-int dopp(boost::fusion::vector<int, int> x) {
-    int a = boost::fusion::at_c<0>(x);
-    int b = boost::fusion::at_c<1>(x);
+void dopp(boost::fusion::vector<int, int>& x) {
+    int& a = boost::fusion::at_c<0>(x);
+    int& b = boost::fusion::at_c<1>(x);
     printf("dopp: %d + %d\n", a, b);
-    return a + b;
-}
+    a = a + b;
+}*/
 
 class ArithmeticGrammar4 : public qi::grammar<
     // the string iterator to parse: can also be const char* or templated.
     std::string::const_iterator,
     // return value of the grammar, written in function syntax!
-    int(),
+    mnd::Expression(),
     // the _type_ of the skip parser
     ascii::space_type>
 {
-public:
     using Iterator = std::string::const_iterator;
+    qi::rule<Iterator, mnd::Expression(), ascii::space_type> start, group, product, factor;
+    qi::rule<Iterator, mnd::Constant(), ascii::space_type> constant;
+public:
 
     ArithmeticGrammar4() : ArithmeticGrammar4::base_type(start)
     {
@@ -52,23 +63,48 @@ public:
         using qi::_1;
         using qi::_2;
 
-        start = qi::int_[_val = _1];
+        auto add = [] (auto&& left, auto&& right) {
+            return mnd::Addition{
+                std::make_unique<Expression>(std::move(left)),
+                std::make_unique<Expression>(std::move(right)),
+                false
+            };
+        };
+        auto mul = [] (auto& left, auto& right) {
+            return mnd::Multiplication {
+                std::make_unique<Expression>(std::move(left)),
+                std::make_unique<Expression>(std::move(right))
+            };
+        };
+        auto pow = [] (auto& left, auto& right) {
+            return mnd::Pow {
+                std::make_unique<Expression>(std::move(left)),
+                std::make_unique<Expression>(std::move(right))
+            };
+        };
+        auto id = [] (auto& x) {
+            //x = Constant{4};//std::move(*x);
+        };
+
+        constant %= qi::int_;
+        //start = (constant >> '+' >> constant)[_val = phx::bind(add, _1, _2)];
 
-        /*start = (product >> '+' >> start)[&dopp]
+        start = (constant >> '+' >> constant)[_val = _2]//[_val = phx::bind(add, _1, _2)]
+            |
+            product;
+            //constant[_val = _1];
+            //qi::int_[_val = _1];
+        product = (constant >> '*' >> constant)[_val = phx::bind(mul, _1, _2)];
+        /*product = (factor >> '*' >> product) [_val = phx::bind(mul, _1, _2)]
             |
-            //product[&simple];
-            qi::int_[_val = _1];
-        product = (factor >> '*' >> product) [&dopp]
+            factor[_val = phx::bind(std::move, _1)];
+        factor %= constant
             |
-            factor[&simple];
-        factor = //qi::int_[&simple]
-            //|
-            group[&simple];
-        group = ('(' >> start >> ')')[&simple];*/
+            group[_val = phx::bind(std::move, _1)];
+        group %= ('(' >> start >> ')');*/
     }
 
     // as before, mirrors the template arguments of qi::grammar.
-    qi::rule<Iterator, int(), ascii::space_type> start, group, product, factor;
 };
 
 /*
@@ -89,24 +125,61 @@ namespace mnd
 {
     std::unique_ptr<Expression> parse(const std::string& formula)
     {
-        //mnd::Expression ret = mnd::Constant{ 1.0 };
-        int ret = 0;
+        mnd::Expression ret = mnd::Constant{ 2.3 };
+        //int ret = 7;
+        int ret2 = 3;
         //FormulaParser<std::string::const_iterator> grammar;
         ArithmeticGrammar4 c;
         auto begin = formula.begin();
         auto end = formula.end();
-        bool r = true;
         /*PhraseParseOrDie (
             formula,
             c,
             ascii::space,
             ret
         );*/
-        boost::spirit::qi::phrase_parse(
+        bool r = boost::spirit::qi::phrase_parse(
             begin, end, c, ascii::space, ret);
 
-        printf("%d\n\n", (int) ret);
+        if (begin != end)
+            printf("error parsing");
+
+        //printf("%d, %d\n\n", (int) ret, ret2);
+        printf("%s\n\n", toString(ret).c_str());
         return std::make_unique<Expression>(mnd::Constant{ 0.0 });
     }
+
+    std::string toString(const mnd::Expression& expr)
+    {
+        return std::visit([] (auto&& ex) -> std::string {
+            std::stringstream ss;
+            using T = std::decay_t<decltype(ex)>;
+            if constexpr (std::is_same<T, mnd::Constant>::value) {
+                ss << "const[" << ex.value << "]";
+                return ss.str();
+            }
+            else if constexpr (std::is_same<T, mnd::Variable>::value) {
+                return std::string("var[") + ex.name + "]";
+            }
+            else if constexpr (std::is_same<T, mnd::UnaryOperation>::value) {
+                return std::string("-") + toString(*ex.operand);
+            }
+            else if constexpr (std::is_same<T, mnd::Addition>::value) {
+                return toString(*ex.left) + std::string("+") + toString(*ex.right);
+            }
+            else if constexpr (std::is_same<T, mnd::Multiplication>::value) {
+                return toString(*ex.left) + std::string("*") + toString(*ex.right);
+            }
+            else if constexpr (std::is_same<T, mnd::Division>::value) {
+                return toString(*ex.left) + std::string("/") + toString(*ex.right);
+            }
+            else if constexpr (std::is_same<T, mnd::Pow>::value) {
+                return toString(*ex.left) + std::string("^") + toString(*ex.right);
+            }
+            return "";
+        }, expr);
+    }
 }
 
+
+