1 #include "MathParser.hpp" 2 3 namespace pdal 4 { 5 namespace expr 6 { 7 expression(Expression & expr)8bool MathParser::expression(Expression& expr) 9 { 10 return addexpr(expr); 11 } 12 addexpr(Expression & expr)13bool MathParser::addexpr(Expression& expr) 14 { 15 if (!multexpr(expr)) 16 return false; 17 18 while (true) 19 { 20 NodeType type; 21 22 if (match(TokenType::Plus)) 23 type = NodeType::Add; 24 else if (match(TokenType::Dash)) 25 type = NodeType::Subtract; 26 else 27 return true; 28 29 if (!multexpr(expr)) 30 { 31 setError("Expected expression following '" + 32 curToken().sval() + "'."); 33 return false; 34 } 35 36 NodePtr right = expr.popNode(); 37 NodePtr left = expr.popNode(); 38 39 ConstValueNode *leftVal = dynamic_cast<ConstValueNode *>(left.get()); 40 ConstValueNode *rightVal = dynamic_cast<ConstValueNode *>(right.get()); 41 if (leftVal && rightVal) 42 { 43 double v = (type == NodeType::Add) ? 44 leftVal->value() + rightVal->value() : 45 leftVal->value() - rightVal->value(); 46 expr.pushNode(NodePtr(new ConstValueNode(v))); 47 } 48 else 49 { 50 if (left->isBool() || right->isBool()) 51 { 52 setError("Can't apply '" + curToken().sval() + "' to " 53 "logical expression."); 54 return false; 55 } 56 expr.pushNode(NodePtr(new BinMathNode(type, std::move(left), std::move(right)))); 57 } 58 } 59 return true; 60 } 61 multexpr(Expression & expr)62bool MathParser::multexpr(Expression& expr) 63 { 64 if (!uminus(expr)) 65 return false; 66 67 while (true) 68 { 69 NodeType type; 70 if (match(TokenType::Asterisk)) 71 type = NodeType::Multiply; 72 else if (match(TokenType::Slash)) 73 type = NodeType::Divide; 74 else 75 return true; 76 77 if (!uminus(expr)) 78 { 79 setError("Expected expression following '" + 80 curToken().sval() + "'."); 81 return false; 82 } 83 84 NodePtr right = expr.popNode(); 85 NodePtr left = expr.popNode(); 86 87 ConstValueNode *leftVal = dynamic_cast<ConstValueNode *>(left.get()); 88 ConstValueNode *rightVal = dynamic_cast<ConstValueNode *>(right.get()); 89 90 if (leftVal && rightVal) 91 { 92 double v; 93 if (type == NodeType::Multiply) 94 v = leftVal->value() * rightVal->value(); 95 else 96 { 97 if (rightVal->value() == 0.0) 98 { 99 setError("Divide by 0."); 100 return false; 101 } 102 v = leftVal->value() / rightVal->value(); 103 } 104 expr.pushNode(NodePtr(new ConstValueNode(v))); 105 } 106 else 107 { 108 if (left->isBool() || right->isBool()) 109 { 110 setError("Can't apply '" + curToken().sval() + "' to " 111 "logical expression."); 112 return false; 113 } 114 expr.pushNode(NodePtr(new BinMathNode(type, std::move(left), std::move(right)))); 115 } 116 } 117 return true; 118 } 119 uminus(Expression & expr)120bool MathParser::uminus(Expression& expr) 121 { 122 if (!match(TokenType::Dash)) 123 return primary(expr); 124 125 if (!primary(expr)) 126 { 127 setError("Expecting expression following '-'."); 128 return false; 129 } 130 131 NodePtr sub = expr.popNode(); 132 ConstValueNode *node = dynamic_cast<ConstValueNode *>(sub.get()); 133 if (node) 134 { 135 double v = -(node->value()); 136 expr.pushNode(NodePtr(new ConstValueNode(v))); 137 } 138 else 139 { 140 if (node->isBool()) 141 { 142 setError("Can't apply '-' to logical expression '" + 143 sub->print() + "'."); 144 return false; 145 } 146 expr.pushNode(NodePtr(new UnMathNode(NodeType::Negative, std::move(sub)))); 147 } 148 return true; 149 } 150 primary(Expression & expr)151bool MathParser::primary(Expression& expr) 152 { 153 if (match(TokenType::Number)) 154 { 155 expr.pushNode(NodePtr(new ConstValueNode(curToken().dval()))); 156 return true; 157 } 158 else if (match(TokenType::Identifier)) 159 { 160 expr.pushNode(NodePtr(new VarNode(curToken().sval()))); 161 return true; 162 } 163 164 return parexpr(expr); 165 } 166 parexpr(Expression & expr)167bool MathParser::parexpr(Expression& expr) 168 { 169 if (!match(TokenType::Lparen)) 170 return false; 171 172 if (!expression(expr)) 173 { 174 setError("Expected expression following '('."); 175 return false; 176 } 177 178 if (!match(TokenType::Rparen)) 179 { 180 setError("Expected ')' following expression at '" + 181 curToken().sval() + "'."); 182 return false; 183 } 184 return true; 185 } 186 187 } // namespace expr 188 } // namespace pdal 189