-
Notifications
You must be signed in to change notification settings - Fork 3
/
operators.d
181 lines (162 loc) · 4.66 KB
/
operators.d
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// Written in the D programming language
// Author: Timon Gehr
// License: http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0
import std.conv, std.traits;
import lexer;
import std.algorithm : canFind;
enum unaryOps = ["&", "*", "-", "++", "--", "+", "!", "~"];
enum postfixOps=[/*".",*/"++", "--","(","["];
//alias canFind!("a==b",TokenType[],TokenType) _canFind;
enum binaryOps=mixin({string r="[";
foreach(x;EnumMembers!TokenType)if(getLbp(x)!=-1&&!canFind([Tok!"++",Tok!"--",Tok!"(",Tok!"["],x)) r~=`"`~TokenTypeToString(x)~`",`;
return r~"]";
}());
enum overloadableUnary = ["-","+","~","*","++","--"];
enum overloadableBinary = ["+","-","*","/","%","^^","&","|","^","<<",">>",">>>","~","in"];
// expression parser:
// left binding power
template lbp(TokenType type){enum lbp=getLbp(type);}
// right binding power: ^^, (op)=, ? bind weaker to the right than to the left, '.' binds only primaryExpressions
template rbp(TokenType type){enum rbp=type==Tok!"."?180:lbp!type-(type==Tok!"^^"||lbp!type==30||type==Tok!"?");}
int getLbp(TokenType type) pure{ // operator precedence
switch(type){
//case Tok!"..": return 10; // range operator
case Tok!",": return 20; // comma operator
// assignment operators
case Tok!"/=",Tok!"&=",Tok!"|=",Tok!"-=":
case Tok!"+=",Tok!"<<=",Tok!">>=", Tok!">>>=":
case Tok!"=",Tok!"*=",Tok!"%=",Tok!"^=":
case Tok!"^^=",Tok!"~=":
return 30;
// logical operators
case Tok!"?": return 40; // conditional operator
case Tok!"||": return 50; // logical OR
case Tok!"&&": return 60; // logical AND
// bitwise operators
case Tok!"|": return 70; // bitwise OR
case Tok!"^": return 80; // bitwise XOR
case Tok!"&": return 90; // bitwise AND
// relational operators
case Tok!"==",Tok!"!=",Tok!">",Tok!"<":
case Tok!">=",Tok!"<=",Tok!"!>",Tok!"!<":
case Tok!"!>=",Tok!"!<=",Tok!"<>",Tok!"!<>":
case Tok!"<>=", Tok!"!<>=":
case Tok!"in", Tok!"!in" ,Tok!"is",Tok!"!is":
return 100;
// shift operators
case Tok!">>", Tok!"<<":
case Tok!">>>": return 110;
// additive operators
case Tok!"+",Tok!"-",Tok!"~":
return 120;
// multiplicative operators
case Tok!"*",Tok!"/",Tok!"%":
return 130;
/*/ prefix operators
case Tok!"&",Tok!"++",Tok!"--",Tok!"*":
case Tok!"-",Tok!"+",Tok!"!",Tok!"~":
return 140; */
case Tok!"^^": return 150; // power
// postfix operators
case Tok!".",Tok!"++",Tok!"--":
case Tok!"(", Tok!"[": // function call and indexing
return 160;
// template instantiation
case Tok!"=>": return 165; // goesto
case Tok!"!": return 170;
//case Tok!"i": return 45; //infix
default: return -1;
}
}
// unary exp binding power
enum nbp=140;
bool isAssignOp(TokenType op){
switch(op){
// assignment operators
case Tok!"/=",Tok!"&=",Tok!"|=",Tok!"-=":
case Tok!"+=",Tok!"<<=",Tok!">>=", Tok!">>>=":
case Tok!"=",Tok!"*=",Tok!"%=",Tok!"^=":
case Tok!"^^=",Tok!"~=":
return true;
default:
return false;
}
}
bool isIntRelationalOp(TokenType op){
switch(op){
// relational operators
case Tok!"==",Tok!"!=",Tok!"is",Tok!"!is":
case Tok!">",Tok!"<", Tok!">=",Tok!"<=":
return true;
default: return false;
}
}
bool isRelationalOp(TokenType op){
switch(op){
// relational operators
case Tok!"==",Tok!"!=",Tok!">",Tok!"<":
case Tok!">=",Tok!"<=",Tok!"!>",Tok!"!<":
case Tok!"!>=",Tok!"!<=",Tok!"<>",Tok!"!<>":
case Tok!"<>=", Tok!"!<>=":
case Tok!"in", Tok!"!in" ,Tok!"is",Tok!"!is":
return true;
default: return false;
}
}
TokenType toIntegerRelationalOp(TokenType op){
switch(op){
// convert relational float operators to integer operators
case Tok!"!>": return Tok!"<=";
case Tok!"!<": return Tok!">=";
case Tok!"!>=": return Tok!"<";
case Tok!"!<=": return Tok!">";
case Tok!"<>": return Tok!"!=";
case Tok!"!<>": return Tok!"==";
case Tok!"<>=": return Tok!"<>="; // cannot translate, always true
case Tok!"!<>=": return Tok!"!<>="; // cannot translate, always false
default: return op;
}
}
bool isLogicalOp(TokenType op){
switch(op){
case Tok!"||": // logical OR
case Tok!"&&": // logical AND
return true;
default:
return false;
}
}
bool isBitwiseOp(TokenType op){
switch(op){
case Tok!"|": // bitwise OR
case Tok!"^": // bitwise XOR
case Tok!"&": // bitwise AND
return true;
default:
return false;
}
}
bool isShiftOp(TokenType op){
switch(op){
// shift operators
case Tok!">>": return true;
case Tok!"<<": return true;
case Tok!">>>":return true;
return true;
default:
return false;
}
}
bool isArithmeticOp(TokenType op){
switch(op){
// additive operators
case Tok!"+",Tok!"-":
return true;
// multiplicative operators
case Tok!"*",Tok!"/",Tok!"%":
case Tok!"^^": // power
return true;
default:
return false;
}
}