-
Notifications
You must be signed in to change notification settings - Fork 0
/
Symbol.h
134 lines (121 loc) · 2.91 KB
/
Symbol.h
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
#pragma once
#ifndef SYMBOL_H_
#define SYMBOL_H_
#include <wx/wx.h>
#include <string>
#include <functional>
#include <cmath>
#include <utility>
#include <vector>
#include "Domain.h"
template<class T>
class Symbol
{
public:
Symbol(int rank,std::string label):_rank(rank),_label(label){}
virtual ~Symbol(){}
std::string const& GetLabel(){return _label;}
void SetLabel(std::string str){_label = wxString(str);}
virtual T Fire(T a, T b) = 0;
int GetRank(){return _rank;}
friend bool operator<(Symbol const& rhs, Symbol const& lhs);
protected:
std::string _label;
int _rank;
};
template<class T>
class OperandSymbol:public Symbol<T>
{
public:
OperandSymbol(std::string label, T data):Symbol<T>(-1,label),_data(data){}
OperandSymbol(int rank,double data):Symbol<T>(rank,""),_data(data){}
virtual ~OperandSymbol(){}
virtual T Fire(T a, T b)
{
return _data;
}
void SetData(T const& data){_data = data;}
private:
T _data;
};
template<class T>
class CompositeOperandSymbol:public Symbol<T>
{
public:
CompositeOperandSymbol(std::string label):Symbol<T>(-1,label){}
CompositeOperandSymbol(int rank):Symbol<T>(rank,""){}
virtual ~CompositeOperandSymbol(){}
virtual T Fire(T a, T b)
{
T result = 0;
if(!_symbols.empty())
{
int exponent = -1;
bool leftOfDecimal = true;
std::vector<Symbol<T>* >::iterator it = _symbols.begin();
for(;it!=_symbols.end();it++)
{
if((*it)->GetRank()==0)
{
if(leftOfDecimal==true)
{
leftOfDecimal = false;
}
else
throw std::invalid_argument("invalid syntax");
continue;
}
if(leftOfDecimal)
{
result = result*10.0 + (*it)->Fire(a,b);
}
else
{
result += pow(10.0,exponent)*((*it)->Fire(a,b));
exponent--;
}
}
}
return result;
}
void AddSymbol(Symbol<T>* sym){_symbols.push_back(sym);}
void RemoveSymbol()
{
if(!_symbols.empty())
_symbols.pop_back();
}
private:
std::vector<Symbol<T>* > _symbols;
};
template<class T>
class BinaryOperatorSymbol:public Symbol<T>
{
public:
BinaryOperatorSymbol(std::string label,int rank,std::function<T(T,T)> func):Symbol<T>(rank,label),_function(func){}
BinaryOperatorSymbol(int rank,std::function<T(T,T)> func):Symbol<T>(rank,""),_function(func){}
virtual ~BinaryOperatorSymbol(){}
void SetLeftDomain(T up, T low){_leftDomain.Set(up,low);}
void SetRightDomain(T up, T low){_rightDomain.Set(up,low);}
void SetRightDiscontinuity(T undefined){_rightDomain.SetUndefined(undefined);}
virtual T Fire(T a, T b)
{
if(IsValid(a,b))
return _function(a,b);
else
throw std::logic_error("logic error!");
}
bool IsValid(T const& leftArg, T const& rightArg)
{
bool valid = true;
if(_leftDomain.HasConstraint())
valid = _leftDomain.IsWithin(leftArg);
if(_rightDomain.HasConstraint())
valid = _rightDomain.IsWithin(rightArg);
return valid;
}
private:
std::function<T(T,T)> _function;
Domain<T> _rightDomain;
Domain<T> _leftDomain;
};
#endif