1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
|
#pragma once
namespace nall { namespace Eval {
inline auto evaluateExpression(Node* node) -> string {
#define p(n) evaluateExpression(node->link[n])
switch(node->type) {
case Node::Type::Null: return "Null";
case Node::Type::Literal: return {"Literal:", node->literal};
case Node::Type::Function: return {"Function(0:", p(0), ", 1:", p(1), ")"};
case Node::Type::Subscript: return {"Subscript(0:", p(0), ", 1:", p(1), ")"};
case Node::Type::Member: return {"Member(0:", p(0), ", 1:", p(1), ")"};
case Node::Type::SuffixIncrement: return {"SuffixIncrement(0:", p(0), ")"};
case Node::Type::SuffixDecrement: return {"SuffixDecrement(0:", p(0), ")"};
case Node::Type::Reference: return {"Reference(0:", p(0), ")"};
case Node::Type::Dereference: return {"Dereference(0:", p(0), ")"};
case Node::Type::BitwiseNot: return {"Complement(0:", p(0), ")"};
case Node::Type::PrefixIncrement: return {"PrefixIncrement(0:", p(0), ")"};
case Node::Type::PrefixDecrement: return {"PrefixDecrement(0:", p(0), ")"};
case Node::Type::Add: return {"Add(0:", p(0), ", 1:", p(1), ")"};
case Node::Type::Multiply: return {"Multiply(0:", p(0), ", 1:", p(1), ")"};
case Node::Type::Concatenate: return {"Concatenate(0:", p(0), ", ", p(1), ")"};
case Node::Type::Coalesce: return {"Coalesce(0:", p(0), ", ", p(1), ")"};
case Node::Type::Condition: return {"Condition(0:", p(0), ", ", p(1), ", ", p(2), ")"};
case Node::Type::Assign: return {"Assign(0:", p(0), ", ", p(1), ")"};
case Node::Type::Separator: {
string result = "Separator(";
for(auto& link : node->link) {
result.append(evaluateExpression(link), ", ");
}
return result.rtrim(", ", 1L).append(")");
}
}
#undef p
throw "invalid operator";
}
inline auto evaluateInteger(Node* node) -> int64_t {
if(node->type == Node::Type::Literal) return nall::integer(node->literal);
#define p(n) evaluateInteger(node->link[n])
switch(node->type) {
case Node::Type::SuffixIncrement: return p(0);
case Node::Type::SuffixDecrement: return p(0);
case Node::Type::LogicalNot: return !p(0);
case Node::Type::BitwiseNot: return ~p(0);
case Node::Type::Positive: return +p(0);
case Node::Type::Negative: return -p(0);
case Node::Type::PrefixIncrement: return p(0) + 1;
case Node::Type::PrefixDecrement: return p(0) - 1;
case Node::Type::Multiply: return p(0) * p(1);
case Node::Type::Divide: return p(0) / p(1);
case Node::Type::Modulo: return p(0) % p(1);
case Node::Type::Add: return p(0) + p(1);
case Node::Type::Subtract: return p(0) - p(1);
case Node::Type::ShiftLeft: return p(0) << p(1);
case Node::Type::ShiftRight: return p(0) >> p(1);
case Node::Type::BitwiseAnd: return p(0) & p(1);
case Node::Type::BitwiseOr: return p(0) | p(1);
case Node::Type::BitwiseXor: return p(0) ^ p(1);
case Node::Type::Equal: return p(0) == p(1);
case Node::Type::NotEqual: return p(0) != p(1);
case Node::Type::LessThanEqual: return p(0) <= p(1);
case Node::Type::GreaterThanEqual: return p(0) >= p(1);
case Node::Type::LessThan: return p(0) < p(1);
case Node::Type::GreaterThan: return p(0) > p(1);
case Node::Type::LogicalAnd: return p(0) && p(1);
case Node::Type::LogicalOr: return p(0) || p(1);
case Node::Type::Condition: return p(0) ? p(1) : p(2);
case Node::Type::Assign: return p(1);
case Node::Type::AssignMultiply: return p(0) * p(1);
case Node::Type::AssignDivide: return p(0) / p(1);
case Node::Type::AssignModulo: return p(0) % p(1);
case Node::Type::AssignAdd: return p(0) + p(1);
case Node::Type::AssignSubtract: return p(0) - p(1);
case Node::Type::AssignShiftLeft: return p(0) << p(1);
case Node::Type::AssignShiftRight: return p(0) >> p(1);
case Node::Type::AssignBitwiseAnd: return p(0) & p(1);
case Node::Type::AssignBitwiseOr: return p(0) | p(1);
case Node::Type::AssignBitwiseXor: return p(0) ^ p(1);
}
#undef p
throw "invalid operator";
}
inline auto integer(const string& expression) -> maybe<int64_t> {
try {
auto tree = new Node;
const char* p = expression;
parse(tree, p, 0);
auto result = evaluateInteger(tree);
delete tree;
return result;
} catch(const char*) {
return nothing;
}
}
inline auto evaluateReal(Node* node) -> long double {
if(node->type == Node::Type::Literal) return nall::real(node->literal);
#define p(n) evaluateReal(node->link[n])
switch(node->type) {
case Node::Type::LogicalNot: return !p(0);
case Node::Type::Positive: return +p(0);
case Node::Type::Negative: return -p(0);
case Node::Type::Multiply: return p(0) * p(1);
case Node::Type::Divide: return p(0) / p(1);
case Node::Type::Add: return p(0) + p(1);
case Node::Type::Subtract: return p(0) - p(1);
case Node::Type::Equal: return p(0) == p(1);
case Node::Type::NotEqual: return p(0) != p(1);
case Node::Type::LessThanEqual: return p(0) <= p(1);
case Node::Type::GreaterThanEqual: return p(0) >= p(1);
case Node::Type::LessThan: return p(0) < p(1);
case Node::Type::GreaterThan: return p(0) > p(1);
case Node::Type::LogicalAnd: return p(0) && p(1);
case Node::Type::LogicalOr: return p(0) || p(1);
case Node::Type::Condition: return p(0) ? p(1) : p(2);
case Node::Type::Assign: return p(1);
case Node::Type::AssignMultiply: return p(0) * p(1);
case Node::Type::AssignDivide: return p(0) / p(1);
case Node::Type::AssignAdd: return p(0) + p(1);
case Node::Type::AssignSubtract: return p(0) - p(1);
}
#undef p
throw "invalid operator";
}
inline auto real(const string& expression) -> maybe<long double> {
try {
auto tree = new Node;
const char* p = expression;
parse(tree, p, 0);
auto result = evaluateReal(tree);
delete tree;
return result;
} catch(const char*) {
return nothing;
}
}
}}
|