| 1 |
module minid; |
|---|
| 2 |
|
|---|
| 3 |
import std.c.stdlib; |
|---|
| 4 |
import std.conv; |
|---|
| 5 |
import std.perf; |
|---|
| 6 |
import std.stdio; |
|---|
| 7 |
import std.stream; |
|---|
| 8 |
import std.string; |
|---|
| 9 |
import std.utf; |
|---|
| 10 |
|
|---|
| 11 |
/* |
|---|
| 12 |
Calling a closure (of any type): |
|---|
| 13 |
ocall ox, 0 |
|---|
| 14 |
|
|---|
| 15 |
Calling methods with "this": |
|---|
| 16 |
ocall ox, index |
|---|
| 17 |
|
|---|
| 18 |
Downcalling dynamic closures: |
|---|
| 19 |
ecall index |
|---|
| 20 |
|
|---|
| 21 |
Calling static functions / Sidecalling dynamic closures: |
|---|
| 22 |
rcall index |
|---|
| 23 |
|
|---|
| 24 |
Referencing static functions / Sidereferencing dynamic closures: |
|---|
| 25 |
rfuncref index |
|---|
| 26 |
|
|---|
| 27 |
Downreferencing dynamic closures: |
|---|
| 28 |
efuncref index |
|---|
| 29 |
|
|---|
| 30 |
Downclosing a function: |
|---|
| 31 |
eclose index |
|---|
| 32 |
|
|---|
| 33 |
Sideclosing a function |
|---|
| 34 |
rclose index |
|---|
| 35 |
|
|---|
| 36 |
Closing/referencing methods with "this" (delegation): |
|---|
| 37 |
oclose ox, index |
|---|
| 38 |
|
|---|
| 39 |
Create closures at a static function level. |
|---|
| 40 |
*/ |
|---|
| 41 |
|
|---|
| 42 |
/* |
|---|
| 43 |
the minid module: |
|---|
| 44 |
|
|---|
| 45 |
class Object |
|---|
| 46 |
{ |
|---|
| 47 |
int opCmp(Object other); |
|---|
| 48 |
bool opEquals(Object other); |
|---|
| 49 |
int getHash(); |
|---|
| 50 |
char[] toString(); |
|---|
| 51 |
} |
|---|
| 52 |
|
|---|
| 53 |
// Cut down on duplication of effort with RTTI! |
|---|
| 54 |
// But that involves either subverting the typesafe compiler or adding in a new "feature" to allow an "any" type. |
|---|
| 55 |
// How about instead of converting arrays to __Arrays right away, save that for the codegen, or somewhere between |
|---|
| 56 |
// semantic and codegen? That would work. |
|---|
| 57 |
|
|---|
| 58 |
class __Array : Object |
|---|
| 59 |
{ |
|---|
| 60 |
this(TypeInfo ti, int length); |
|---|
| 61 |
|
|---|
| 62 |
int opCmp(__Array other); |
|---|
| 63 |
bool opEquals(__Array other); |
|---|
| 64 |
int getHash(); |
|---|
| 65 |
char[] toString(); |
|---|
| 66 |
|
|---|
| 67 |
// These return an "int", but the return type is really dictated by the compiler. |
|---|
| 68 |
int opIndex(int index); |
|---|
| 69 |
|
|---|
| 70 |
// These all take "ints", but again, it's type-dependent. |
|---|
| 71 |
int opIndexAssign(int value, int index); |
|---|
| 72 |
|
|---|
| 73 |
__Array opSlice(); |
|---|
| 74 |
__Array opSlice(int lo, int hi); |
|---|
| 75 |
__Array opSliceAssign(int value); |
|---|
| 76 |
__Array opSliceAssign(int value, int lo, int hi); |
|---|
| 77 |
__IntArray dup(); |
|---|
| 78 |
void sort(); |
|---|
| 79 |
void reverse(); |
|---|
| 80 |
|
|---|
| 81 |
namespace length |
|---|
| 82 |
{ |
|---|
| 83 |
int opGet(); |
|---|
| 84 |
int opSet(int l); |
|---|
| 85 |
} |
|---|
| 86 |
|
|---|
| 87 |
__IntArray opCat(__IntArray other); |
|---|
| 88 |
__IntArray opCatEq(__IntArray other); |
|---|
| 89 |
} |
|---|
| 90 |
*/ |
|---|
| 91 |
|
|---|
| 92 |
void main() |
|---|
| 93 |
{ |
|---|
| 94 |
BufferedFile f = new BufferedFile(`testscript.txt`, FileMode.In); |
|---|
| 95 |
|
|---|
| 96 |
auto Compiler c = new Compiler(); |
|---|
| 97 |
|
|---|
| 98 |
c.compile(`testscript.txt`, f); |
|---|
| 99 |
|
|---|
| 100 |
f.close(); |
|---|
| 101 |
delete f; |
|---|
| 102 |
} |
|---|
| 103 |
|
|---|
| 104 |
class Compiler |
|---|
| 105 |
{ |
|---|
| 106 |
public this() |
|---|
| 107 |
{ |
|---|
| 108 |
|
|---|
| 109 |
} |
|---|
| 110 |
|
|---|
| 111 |
public void compile(char[] name, Stream source) |
|---|
| 112 |
{ |
|---|
| 113 |
auto Lexer l = new Lexer(); |
|---|
| 114 |
auto HighPerformanceCounter hpc = new HighPerformanceCounter(); |
|---|
| 115 |
hpc.start(); |
|---|
| 116 |
Token* tokens = l.lex(name, source); |
|---|
| 117 |
Module m = Module.parse(tokens); |
|---|
| 118 |
m.semantic(); |
|---|
| 119 |
hpc.stop(); |
|---|
| 120 |
writefln("Took ", hpc.microseconds() / 1000.0, "ms\n"); |
|---|
| 121 |
m.showChildren(); |
|---|
| 122 |
//writefln(m); |
|---|
| 123 |
} |
|---|
| 124 |
} |
|---|
| 125 |
|
|---|
| 126 |
int toInt(char[] s, int base) |
|---|
| 127 |
{ |
|---|
| 128 |
assert(base >= 2 && base <= 36); |
|---|
| 129 |
|
|---|
| 130 |
static char[] transTable = |
|---|
| 131 |
[ |
|---|
| 132 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|---|
| 133 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|---|
| 134 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|---|
| 135 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|---|
| 136 |
0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, |
|---|
| 137 |
73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 0, 0, 0, 0, 0, |
|---|
| 138 |
0, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, |
|---|
| 139 |
73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 0, 0, 0, 0, 0, |
|---|
| 140 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|---|
| 141 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|---|
| 142 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|---|
| 143 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|---|
| 144 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|---|
| 145 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|---|
| 146 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|---|
| 147 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
|---|
| 148 |
]; |
|---|
| 149 |
|
|---|
| 150 |
int length = s.length; |
|---|
| 151 |
|
|---|
| 152 |
if(!length) |
|---|
| 153 |
throw new ConvError(s); |
|---|
| 154 |
|
|---|
| 155 |
int sign = 0; |
|---|
| 156 |
int v = 0; |
|---|
| 157 |
|
|---|
| 158 |
char maxDigit = '0' + base - 1; |
|---|
| 159 |
|
|---|
| 160 |
for(int i = 0; i < length; i++) |
|---|
| 161 |
{ |
|---|
| 162 |
char c = transTable[s[i]]; |
|---|
| 163 |
|
|---|
| 164 |
if(c >= '0' && c <= maxDigit) |
|---|
| 165 |
{ |
|---|
| 166 |
uint v1 = v; |
|---|
| 167 |
v = v * base + (c - '0'); |
|---|
| 168 |
|
|---|
| 169 |
if(cast(uint)v < v1) |
|---|
| 170 |
throw new ConvOverflowError(s); |
|---|
| 171 |
} |
|---|
| 172 |
else if(c == '-' && i == 0) |
|---|
| 173 |
{ |
|---|
| 174 |
sign = -1; |
|---|
| 175 |
|
|---|
| 176 |
if(length == 1) |
|---|
| 177 |
throw new ConvError(s); |
|---|
| 178 |
} |
|---|
| 179 |
else if(c == '+' && i == 0) |
|---|
| 180 |
{ |
|---|
| 181 |
if(length == 1) |
|---|
| 182 |
throw new ConvError(s); |
|---|
| 183 |
} |
|---|
| 184 |
else |
|---|
| 185 |
throw new ConvError(s); |
|---|
| 186 |
} |
|---|
| 187 |
|
|---|
| 188 |
if(sign == -1) |
|---|
| 189 |
{ |
|---|
| 190 |
if(cast(uint)v > 0x80000000) |
|---|
| 191 |
throw new ConvOverflowError(s); |
|---|
| 192 |
|
|---|
| 193 |
v = -v; |
|---|
| 194 |
} |
|---|
| 195 |
else |
|---|
| 196 |
{ |
|---|
| 197 |
if(cast(uint)v > 0x7FFFFFFF) |
|---|
| 198 |
throw new ConvOverflowError(s); |
|---|
| 199 |
} |
|---|
| 200 |
|
|---|
| 201 |
return v; |
|---|
| 202 |
} |
|---|
| 203 |
|
|---|
| 204 |
struct Token |
|---|
| 205 |
{ |
|---|
| 206 |
public static enum Type |
|---|
| 207 |
{ |
|---|
| 208 |
Assert, |
|---|
| 209 |
Bool, |
|---|
| 210 |
Break, |
|---|
| 211 |
Case, |
|---|
| 212 |
Cast, |
|---|
| 213 |
Char, |
|---|
| 214 |
Class, |
|---|
| 215 |
Closure, |
|---|
| 216 |
Continue, |
|---|
| 217 |
Def, |
|---|
| 218 |
Default, |
|---|
| 219 |
Delete, |
|---|
| 220 |
Do, |
|---|
| 221 |
Else, |
|---|
| 222 |
False, |
|---|
| 223 |
Float, |
|---|
| 224 |
For, |
|---|
| 225 |
Foreach, |
|---|
| 226 |
Function, |
|---|
| 227 |
If, |
|---|
| 228 |
Import, |
|---|
| 229 |
Int, |
|---|
| 230 |
Main, |
|---|
| 231 |
Module, |
|---|
| 232 |
Namespace, |
|---|
| 233 |
New, |
|---|
| 234 |
Null, |
|---|
| 235 |
Return, |
|---|
| 236 |
Super, |
|---|
| 237 |
Switch, |
|---|
| 238 |
This, |
|---|
| 239 |
True, |
|---|
| 240 |
Vararg, |
|---|
| 241 |
Void, |
|---|
| 242 |
While, |
|---|
| 243 |
|
|---|
| 244 |
Add, |
|---|
| 245 |
AddEq, |
|---|
| 246 |
Sub, |
|---|
| 247 |
SubEq, |
|---|
| 248 |
Mul, |
|---|
| 249 |
MulEq, |
|---|
| 250 |
Div, |
|---|
| 251 |
DivEq, |
|---|
| 252 |
Mod, |
|---|
| 253 |
ModEq, |
|---|
| 254 |
Pow, |
|---|
| 255 |
PowEq, |
|---|
| 256 |
Cat, |
|---|
| 257 |
CatEq, |
|---|
| 258 |
Assign, |
|---|
| 259 |
|
|---|
| 260 |
AndAnd, |
|---|
| 261 |
OrOr, |
|---|
| 262 |
|
|---|
| 263 |
Inc, |
|---|
| 264 |
Dec, |
|---|
| 265 |
|
|---|
| 266 |
LT, |
|---|
| 267 |
LE, |
|---|
| 268 |
GT, |
|---|
| 269 |
GE, |
|---|
| 270 |
EQ, |
|---|
| 271 |
NE, |
|---|
| 272 |
Is, |
|---|
| 273 |
|
|---|
| 274 |
Not, |
|---|
| 275 |
|
|---|
| 276 |
LParen, |
|---|
| 277 |
RParen, |
|---|
| 278 |
LBracket, |
|---|
| 279 |
RBracket, |
|---|
| 280 |
LBrace, |
|---|
| 281 |
RBrace, |
|---|
| 282 |
|
|---|
| 283 |
Colon, |
|---|
| 284 |
Comma, |
|---|
| 285 |
Semicolon, |
|---|
| 286 |
|
|---|
| 287 |
Dot, |
|---|
| 288 |
DotDot, |
|---|
| 289 |
|
|---|
| 290 |
Ident, |
|---|
| 291 |
BoolLiteral, |
|---|
| 292 |
StringLiteral, |
|---|
| 293 |
CharLiteral, |
|---|
| 294 |
IntLiteral, |
|---|
| 295 |
FloatLiteral, |
|---|
| 296 |
EOF |
|---|
| 297 |
} |
|---|
| 298 |
|
|---|
| 299 |
public static const char[][] tokenStrings = |
|---|
| 300 |
[ |
|---|
| 301 |
"assert", |
|---|
| 302 |
"bool", |
|---|
| 303 |
"break", |
|---|
| 304 |
"case", |
|---|
| 305 |
"cast", |
|---|
| 306 |
"char", |
|---|
| 307 |
"class", |
|---|
| 308 |
"closure", |
|---|
| 309 |
"continue", |
|---|
| 310 |
"def", |
|---|
| 311 |
"default", |
|---|
| 312 |
"delete", |
|---|
| 313 |
"do", |
|---|
| 314 |
"else", |
|---|
| 315 |
"false", |
|---|
| 316 |
"float", |
|---|
| 317 |
"for", |
|---|
| 318 |
"foreach", |
|---|
| 319 |
"function", |
|---|
| 320 |
"if", |
|---|
| 321 |
"import", |
|---|
| 322 |
"int", |
|---|
| 323 |
"main", |
|---|
| 324 |
"module", |
|---|
| 325 |
"namespace" |
|---|
| 326 |
"new", |
|---|
| 327 |
"null", |
|---|
| 328 |
"return", |
|---|
| 329 |
"super", |
|---|
| 330 |
"switch", |
|---|
| 331 |
"this", |
|---|
| 332 |
"true", |
|---|
| 333 |
"vararg", |
|---|
| 334 |
"void", |
|---|
| 335 |
"while", |
|---|
| 336 |
|
|---|
| 337 |
"+", |
|---|
| 338 |
"+=", |
|---|
| 339 |
"-", |
|---|
| 340 |
"-=", |
|---|
| 341 |
"*", |
|---|
| 342 |
"*=", |
|---|
| 343 |
"/", |
|---|
| 344 |
"/=", |
|---|
| 345 |
"%", |
|---|
| 346 |
"%=", |
|---|
| 347 |
"^", |
|---|
| 348 |
"^=", |
|---|
| 349 |
"~", |
|---|
| 350 |
"~=", |
|---|
| 351 |
"=", |
|---|
| 352 |
|
|---|
| 353 |
"&&", |
|---|
| 354 |
"||", |
|---|
| 355 |
|
|---|
| 356 |
"++", |
|---|
| 357 |
"--", |
|---|
| 358 |
|
|---|
| 359 |
"<", |
|---|
| 360 |
"<=", |
|---|
| 361 |
">", |
|---|
| 362 |
">=", |
|---|
| 363 |
"==", |
|---|
| 364 |
"!=", |
|---|
| 365 |
"is", |
|---|
| 366 |
|
|---|
| 367 |
"!", |
|---|
| 368 |
|
|---|
| 369 |
"(", |
|---|
| 370 |
")", |
|---|
| 371 |
"[", |
|---|
| 372 |
"]", |
|---|
| 373 |
"{", |
|---|
| 374 |
"}", |
|---|
| 375 |
|
|---|
| 376 |
":", |
|---|
| 377 |
",", |
|---|
| 378 |
";", |
|---|
| 379 |
|
|---|
| 380 |
".", |
|---|
| 381 |
"..", |
|---|
| 382 |
|
|---|
| 383 |
"Identifier", |
|---|
| 384 |
"Bool Literal", |
|---|
| 385 |
"String Literal", |
|---|
| 386 |
"Char Literal", |
|---|
| 387 |
"Int Literal", |
|---|
| 388 |
"Float Literal", |
|---|
| 389 |
"<EOF>" |
|---|
| 390 |
]; |
|---|
| 391 |
|
|---|
| 392 |
public static Type[char[]] stringToType; |
|---|
| 393 |
|
|---|
| 394 |
static this() |
|---|
| 395 |
{ |
|---|
| 396 |
stringToType["assert"] = Type.Assert; |
|---|
| 397 |
stringToType["bool"] = Type.Bool; |
|---|
| 398 |
stringToType["break"] = Type.Break; |
|---|
| 399 |
stringToType["case"] = Type.Case; |
|---|
| 400 |
stringToType["cast"] = Type.Cast; |
|---|
| 401 |
stringToType["char"] = Type.Char; |
|---|
| 402 |
stringToType["class"] = Type.Class; |
|---|
| 403 |
stringToType["closure"] = Type.Closure; |
|---|
| 404 |
stringToType["continue"] = Type.Continue; |
|---|
| 405 |
stringToType["def"] = Type.Def; |
|---|
| 406 |
stringToType["default"] = Type.Default; |
|---|
| 407 |
stringToType["delete"] = Type.Delete; |
|---|
| 408 |
stringToType["do"] = Type.Do; |
|---|
| 409 |
stringToType["else"] = Type.Else; |
|---|
| 410 |
stringToType["false"] = Type.False; |
|---|
| 411 |
stringToType["float"] = Type.Float; |
|---|
| 412 |
stringToType["for"] = Type.For; |
|---|
| 413 |
stringToType["foreach"] = Type.Foreach; |
|---|
| 414 |
stringToType["function"] = Type.Function; |
|---|
| 415 |
stringToType["if"] = Type.If; |
|---|
| 416 |
stringToType["is"] = Type.Is; |
|---|
| 417 |
stringToType["import"] = Type.Import; |
|---|
| 418 |
stringToType["int"] = Type.Int; |
|---|
| 419 |
stringToType["main"] = Type.Main; |
|---|
| 420 |
stringToType["module"] = Type.Module; |
|---|
| 421 |
stringToType["namespace"] = Type.Namespace; |
|---|
| 422 |
stringToType["new"] = Type.New; |
|---|
| 423 |
stringToType["null"] = Type.Null; |
|---|
| 424 |
stringToType["return"] = Type.Return; |
|---|
| 425 |
stringToType["super"] = Type.Super; |
|---|
| 426 |
stringToType["switch"] = Type.Switch; |
|---|
| 427 |
stringToType["this"] = Type.This; |
|---|
| 428 |
stringToType["true"] = Type.True; |
|---|
| 429 |
stringToType["vararg"] = Type.Vararg; |
|---|
| 430 |
stringToType["void"] = Type.Void; |
|---|
| 431 |
stringToType["while"] = Type.While; |
|---|
| 432 |
stringToType["("] = Type.LParen; |
|---|
| 433 |
stringToType[")"] = Type.RParen; |
|---|
| 434 |
stringToType["["] = Type.LBracket; |
|---|
| 435 |
stringToType["]"] = Type.RBracket; |
|---|
| 436 |
stringToType["{"] = Type.LBrace; |
|---|
| 437 |
stringToType["}"] = Type.RBrace; |
|---|
| 438 |
stringToType[":"] = Type.Colon; |
|---|
| 439 |
stringToType[","] = Type.Comma; |
|---|
| 440 |
stringToType[";"] = Type.Semicolon; |
|---|
| 441 |
|
|---|
| 442 |
stringToType.rehash; |
|---|
| 443 |
} |
|---|
| 444 |
|
|---|
| 445 |
public char[] toString() |
|---|
| 446 |
{ |
|---|
| 447 |
char[] ret; |
|---|
| 448 |
|
|---|
| 449 |
switch(type) |
|---|
| 450 |
{ |
|---|
| 451 |
case Type.Ident: |
|---|
| 452 |
ret ~= "Ident: " ~ stringValue; |
|---|
| 453 |
break; |
|---|
| 454 |
|
|---|
| 455 |
case Type.BoolLiteral: |
|---|
| 456 |
ret ~= (boolValue ? "true" : "false"); |
|---|
| 457 |
|
|---|
| 458 |
case Type.StringLiteral: |
|---|
| 459 |
ret ~= '"' ~ stringValue ~ '"'; |
|---|
| 460 |
break; |
|---|
| 461 |
|
|---|
| 462 |
case Type.CharLiteral: |
|---|
| 463 |
ret ~= "'" ~ stringValue ~ "'"; |
|---|
| 464 |
|
|---|
| 465 |
case Type.IntLiteral: |
|---|
| 466 |
ret ~= "Int: " ~ std.string.toString(intValue); |
|---|
| 467 |
break; |
|---|
| 468 |
|
|---|
| 469 |
case Type.FloatLiteral: |
|---|
| 470 |
ret ~= "Float: " ~ std.string.toString(floatValue); |
|---|
| 471 |
break; |
|---|
| 472 |
|
|---|
| 473 |
default: |
|---|
| 474 |
ret ~= tokenStrings[cast(uint)type]; |
|---|
| 475 |
break; |
|---|
| 476 |
} |
|---|
| 477 |
|
|---|
| 478 |
return ret; |
|---|
| 479 |
} |
|---|
| 480 |
|
|---|
| 481 |
public static char[] toString(Type type) |
|---|
| 482 |
{ |
|---|
| 483 |
return tokenStrings[type]; |
|---|
| 484 |
} |
|---|
| 485 |
|
|---|
| 486 |
public void check(Type t) |
|---|
| 487 |
{ |
|---|
| 488 |
if(type != t) |
|---|
| 489 |
throw new MDCompileException("'" ~ tokenStrings[t] ~ "' expected; found '" ~ tokenStrings[type] ~ "' instead", location); |
|---|
| 490 |
} |
|---|
| 491 |
|
|---|
| 492 |
public Type type; |
|---|
| 493 |
|
|---|
| 494 |
union |
|---|
| 495 |
{ |
|---|
| 496 |
public bool boolValue; |
|---|
| 497 |
public char[] stringValue; |
|---|
| 498 |
public int intValue; |
|---|
| 499 |
public float floatValue; |
|---|
| 500 |
} |
|---|
| 501 |
|
|---|
| 502 |
public Location location; |
|---|
| 503 |
|
|---|
| 504 |
public Token* nextToken; |
|---|
| 505 |
} |
|---|
| 506 |
|
|---|
| 507 |
struct Location |
|---|
| 508 |
{ |
|---|
| 509 |
public uint line = 1; |
|---|
| 510 |
public uint column = 1; |
|---|
| 511 |
public char[] fileName; |
|---|
| 512 |
|
|---|
| 513 |
public static Location opCall(char[] fileName, uint line = 1, uint column = 1) |
|---|
| 514 |
{ |
|---|
| 515 |
Location l; |
|---|
| 516 |
l.fileName = fileName; |
|---|
| 517 |
l.line = line; |
|---|
| 518 |
l.column = column; |
|---|
| 519 |
return l; |
|---|
| 520 |
} |
|---|
| 521 |
|
|---|
| 522 |
public char[] toString() |
|---|
| 523 |
{ |
|---|
| 524 |
return fileName ~ "(" ~ .toString(line) ~ ":" ~ .toString(column) ~ ")"; |
|---|
| 525 |
} |
|---|
| 526 |
} |
|---|
| 527 |
|
|---|
| 528 |
class MDException : Exception |
|---|
| 529 |
{ |
|---|
| 530 |
public this(char[] msg) |
|---|
| 531 |
{ |
|---|
| 532 |
super(msg); |
|---|
| 533 |
} |
|---|
| 534 |
} |
|---|
| 535 |
|
|---|
| 536 |
class MDCompileException : MDException |
|---|
| 537 |
{ |
|---|
| 538 |
public this(char[] msg, Location loc) |
|---|
| 539 |
{ |
|---|
| 540 |
super(loc.toString() ~ ": " ~ msg); |
|---|
| 541 |
} |
|---|
| 542 |
} |
|---|
| 543 |
|
|---|
| 544 |
class MDSymbolConflictException : MDCompileException |
|---|
| 545 |
{ |
|---|
| 546 |
public this(Symbol sym1, Symbol sym2) |
|---|
| 547 |
{ |
|---|
| 548 |
super("'" ~ sym1.toPrettyString() ~ "' conflicts with '" ~ sym2.toPrettyString() ~ "'(" ~ sym2.mLocation.toString() ~ ")", sym1.mLocation); |
|---|
| 549 |
} |
|---|
| 550 |
} |
|---|
| 551 |
|
|---|
| 552 |
class MDShadowingException : MDCompileException |
|---|
| 553 |
{ |
|---|
| 554 |
public this(Symbol sym1, Symbol sym2) |
|---|
| 555 |
{ |
|---|
| 556 |
super("'" ~ sym1.toPrettyString() ~ "' shadows '" ~ sym2.toPrettyString() ~ "'(" ~ sym2.mLocation.toString() ~ ")", sym1.mLocation); |
|---|
| 557 |
} |
|---|
| 558 |
} |
|---|
| 559 |
|
|---|
| 560 |
class MDTypeConvException : MDCompileException |
|---|
| 561 |
{ |
|---|
| 562 |
public this(Expression from, Expression to) |
|---|
| 563 |
{ |
|---|
| 564 |
super("Cannot implicitly convert expression '" ~ from.toString() ~ "' of type '" ~ from.mSemType.toString() ~ "' to type '" ~ to.mSemType.toString() ~ "'", from.mLocation); |
|---|
| 565 |
} |
|---|
| 566 |
} |
|---|
| 567 |
|
|---|
| 568 |
class Lexer |
|---|
| 569 |
{ |
|---|
| 570 |
protected Stream mSource; |
|---|
| 571 |
protected Location mLoc; |
|---|
| 572 |
protected char mCharacter; |
|---|
| 573 |
|
|---|
| 574 |
public this() |
|---|
| 575 |
{ |
|---|
| 576 |
|
|---|
| 577 |
} |
|---|
| 578 |
|
|---|
| 579 |
public Token* lex(char[] name, Stream source) |
|---|
| 580 |
{ |
|---|
| 581 |
if(!source.readable) |
|---|
| 582 |
throw new MDException(name ~ ": Source code stream is not readable"); |
|---|
| 583 |
|
|---|
| 584 |
mLoc = Location(name); |
|---|
| 585 |
|
|---|
| 586 |
mSource = source; |
|---|
| 587 |
|
|---|
| 588 |
nextChar(); |
|---|
| 589 |
|
|---|
| 590 |
Token* firstToken = nextToken(); |
|---|
| 591 |
Token* t = firstToken; |
|---|
| 592 |
|
|---|
| 593 |
while(t.type != Token.Type.EOF) |
|---|
| 594 |
{ |
|---|
| 595 |
Token* next = nextToken(); |
|---|
| 596 |
|
|---|
| 597 |
t.nextToken = next; |
|---|
| 598 |
t = t.nextToken; |
|---|
| 599 |
} |
|---|
| 600 |
|
|---|
| 601 |
return firstToken; |
|---|
| 602 |
} |
|---|
| 603 |
|
|---|
| 604 |
protected static bool isEOF(char c) |
|---|
| 605 |
{ |
|---|
| 606 |
return (c == '\0') || (c == char.init); |
|---|
| 607 |
} |
|---|
| 608 |
|
|---|
| 609 |
protected static bool isEOL(char c) |
|---|
| 610 |
{ |
|---|
| 611 |
return isNewline(c) || isEOF(c); |
|---|
| 612 |
} |
|---|
| 613 |
|
|---|
| 614 |
protected static bool isWhitespace(char c) |
|---|
| 615 |
{ |
|---|
| 616 |
return (c == ' ') || (c == '\t') || (c == '\v') || (c == '\u000C') || isEOL(c); |
|---|
| 617 |
} |
|---|
| 618 |
|
|---|
| 619 |
protected static bool isNewline(char c) |
|---|
| 620 |
{ |
|---|
| 621 |
return (c == '\r') || (c == '\n'); |
|---|
| 622 |
} |
|---|
| 623 |
|
|---|
| 624 |
protected static bool isBinaryDigit(char c) |
|---|
| 625 |
{ |
|---|
| 626 |
return (c == '0') || (c == '1'); |
|---|
| 627 |
} |
|---|
| 628 |
|
|---|
| 629 |
protected static bool isOctalDigit(char c) |
|---|
| 630 |
{ |
|---|
| 631 |
return (c >= '0') && (c <= '7'); |
|---|
| 632 |
} |
|---|
| 633 |
|
|---|
| 634 |
protected static bool isHexDigit(char c) |
|---|
| 635 |
{ |
|---|
| 636 |
return ((c >= '0') && (c <= '9')) || ((c >= 'a') && (c <= 'f')) || ((c >= 'A') && (c <= 'F')); |
|---|
| 637 |
} |
|---|
| 638 |
|
|---|
| 639 |
protected static bool isDecimalDigit(char c) |
|---|
| 640 |
{ |
|---|
| 641 |
return (c >= '0') && (c <= '9'); |
|---|
| 642 |
} |
|---|
| 643 |
|
|---|
| 644 |
protected static bool isAlpha(char c) |
|---|
| 645 |
{ |
|---|
| 646 |
return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')); |
|---|
| 647 |
} |
|---|
| 648 |
|
|---|
| 649 |
protected void nextChar() |
|---|
| 650 |
{ |
|---|
| 651 |
mCharacter = mSource.getc(); |
|---|
| 652 |
mLoc.column++; |
|---|
| 653 |
&nb |
|---|