| 1 |
// dlexer - D language lexer |
|---|
| 2 |
// (C) Copyright 2004-2005 James Dunne |
|---|
| 3 |
|
|---|
| 4 |
// Please feel free to distribute this module in any form you like. I only ask that you |
|---|
| 5 |
// give credit where credit is due. You may make modifications to this module. If you do |
|---|
| 6 |
// so, you may provide your modifications publicly, but you are not required to. |
|---|
| 7 |
|
|---|
| 8 |
module dlexer; |
|---|
| 9 |
|
|---|
| 10 |
import std.stream; |
|---|
| 11 |
import std.string; |
|---|
| 12 |
import std.ctype; |
|---|
| 13 |
|
|---|
| 14 |
private import std.c.stdlib; // for strtod and strtold |
|---|
| 15 |
|
|---|
| 16 |
alias std.ctype.isdigit isdigit; |
|---|
| 17 |
|
|---|
| 18 |
// Set this version identifier to enable interpretation of escaped characters within parsed strings |
|---|
| 19 |
// If this is disabled, the strings are copied directly, escape sequences and all. |
|---|
| 20 |
|
|---|
| 21 |
// version = interpret_slashes; |
|---|
| 22 |
|
|---|
| 23 |
// Enumeration of D language tokens taken from DMD's lexer.h |
|---|
| 24 |
enum : uint { |
|---|
| 25 |
TOKreserved, |
|---|
| 26 |
|
|---|
| 27 |
// Other |
|---|
| 28 |
TOKlparen, TOKrparen, |
|---|
| 29 |
TOKlbracket, TOKrbracket, |
|---|
| 30 |
TOKlcurly, TOKrcurly, |
|---|
| 31 |
TOKcolon, TOKneg, |
|---|
| 32 |
TOKsemicolon, TOKdotdotdot, |
|---|
| 33 |
TOKeof, TOKcast, |
|---|
| 34 |
TOKnull, TOKassert, |
|---|
| 35 |
TOKtrue, TOKfalse, |
|---|
| 36 |
TOKarray, TOKcall, |
|---|
| 37 |
TOKaddress, TOKtypedot, |
|---|
| 38 |
TOKtype, TOKthrow, |
|---|
| 39 |
TOKnew, TOKdelete, |
|---|
| 40 |
TOKstar, TOKsymoff, |
|---|
| 41 |
TOKvar, TOKdotvar, |
|---|
| 42 |
TOKdotti, TOKdotexp, |
|---|
| 43 |
TOKdottype, TOKslice, |
|---|
| 44 |
TOKarraylength, TOKversion, |
|---|
| 45 |
TOKmodule, TOKdollar, |
|---|
| 46 |
TOKtemplate, TOKinstance, |
|---|
| 47 |
TOKdeclaration, TOKtypeof, |
|---|
| 48 |
TOKpragma, TOKdsymbol, |
|---|
| 49 |
TOKtypeid, TOKuadd, |
|---|
| 50 |
|
|---|
| 51 |
// Operators |
|---|
| 52 |
TOKlt, TOKgt, |
|---|
| 53 |
TOKle, TOKge, |
|---|
| 54 |
TOKequal, TOKnotequal, |
|---|
| 55 |
TOKidentity, TOKnotidentity, |
|---|
| 56 |
TOKindex, |
|---|
| 57 |
|
|---|
| 58 |
// NCEG floating point compares |
|---|
| 59 |
// !<>= <> <>= !> !>= !< !<= !<> |
|---|
| 60 |
TOKunord,TOKlg,TOKleg,TOKule,TOKul,TOKuge,TOKug,TOKue, |
|---|
| 61 |
|
|---|
| 62 |
TOKshl, TOKshr, |
|---|
| 63 |
TOKshlass, TOKshrass, |
|---|
| 64 |
TOKushr, TOKushrass, |
|---|
| 65 |
TOKcat, TOKcatass, // ~ ~= |
|---|
| 66 |
TOKadd, TOKmin, TOKaddass, TOKminass, |
|---|
| 67 |
TOKmul, TOKdiv, TOKmod, |
|---|
| 68 |
TOKmulass, TOKdivass, TOKmodass, |
|---|
| 69 |
TOKand, TOKor, TOKxor, |
|---|
| 70 |
TOKandass, TOKorass, TOKxorass, |
|---|
| 71 |
TOKassign, TOKnot, TOKtilde, |
|---|
| 72 |
TOKplusplus, TOKminusminus, |
|---|
| 73 |
TOKdot, TOKarrow, TOKcomma, |
|---|
| 74 |
TOKquestion, TOKandand, TOKoror, |
|---|
| 75 |
|
|---|
| 76 |
// Numeric literals |
|---|
| 77 |
TOKint32v, TOKuns32v, |
|---|
| 78 |
TOKint64v, TOKuns64v, |
|---|
| 79 |
TOKfloat32v, TOKfloat64v, TOKfloat80v, |
|---|
| 80 |
TOKimaginary32v, TOKimaginary64v, TOKimaginary80v, |
|---|
| 81 |
|
|---|
| 82 |
// Char constants |
|---|
| 83 |
TOKcharv, TOKwcharv, TOKdcharv, |
|---|
| 84 |
|
|---|
| 85 |
// Leaf operators |
|---|
| 86 |
TOKidentifier, TOKstring, |
|---|
| 87 |
TOKthis, TOKsuper, |
|---|
| 88 |
|
|---|
| 89 |
// Basic types |
|---|
| 90 |
TOKvoid, |
|---|
| 91 |
TOKint8, TOKuns8, |
|---|
| 92 |
TOKint16, TOKuns16, |
|---|
| 93 |
TOKint32, TOKuns32, |
|---|
| 94 |
TOKint64, TOKuns64, |
|---|
| 95 |
TOKfloat32, TOKfloat64, TOKfloat80, |
|---|
| 96 |
TOKimaginary32, TOKimaginary64, TOKimaginary80, |
|---|
| 97 |
TOKcomplex32, TOKcomplex64, TOKcomplex80, |
|---|
| 98 |
TOKchar, TOKwchar, TOKdchar, TOKbit, |
|---|
| 99 |
|
|---|
| 100 |
// Aggregates |
|---|
| 101 |
TOKstruct, TOKclass, TOKinterface, TOKunion, TOKenum, TOKimport, |
|---|
| 102 |
TOKtypedef, TOKalias, TOKoverride, TOKdelegate, TOKfunction, |
|---|
| 103 |
TOKmixin, |
|---|
| 104 |
|
|---|
| 105 |
TOKalign, TOKextern, TOKprivate, TOKprotected, TOKpublic, TOKexport, |
|---|
| 106 |
TOKstatic, /*TOKvirtual,*/ TOKfinal, TOKconst, TOKabstract, TOKvolatile, |
|---|
| 107 |
TOKdebug, TOKdeprecated, TOKin, TOKout, TOKinout, |
|---|
| 108 |
TOKauto, TOKpackage, |
|---|
| 109 |
|
|---|
| 110 |
// Statements |
|---|
| 111 |
TOKif, TOKelse, TOKwhile, TOKfor, TOKdo, TOKswitch, |
|---|
| 112 |
TOKcase, TOKdefault, TOKbreak, TOKcontinue, TOKwith, |
|---|
| 113 |
TOKsynchronized, TOKreturn, TOKgoto, TOKtry, TOKcatch, TOKfinally, |
|---|
| 114 |
TOKasm, TOKforeach, |
|---|
| 115 |
|
|---|
| 116 |
// Contracts |
|---|
| 117 |
TOKbody, TOKinvariant, |
|---|
| 118 |
|
|---|
| 119 |
// Testing |
|---|
| 120 |
TOKunittest, |
|---|
| 121 |
|
|---|
| 122 |
TOKmax |
|---|
| 123 |
} |
|---|
| 124 |
|
|---|
| 125 |
// A table converting token values into string representations: |
|---|
| 126 |
char[] toktostr[TOKmax] = [ |
|---|
| 127 |
TOKreserved : "reserved", |
|---|
| 128 |
|
|---|
| 129 |
// Other |
|---|
| 130 |
TOKlparen : "(", |
|---|
| 131 |
TOKrparen : ")", |
|---|
| 132 |
TOKlbracket : "[", |
|---|
| 133 |
TOKrbracket : "]", |
|---|
| 134 |
TOKlcurly : "{", |
|---|
| 135 |
TOKrcurly : "}", |
|---|
| 136 |
TOKcolon : ":", |
|---|
| 137 |
TOKneg : "-", |
|---|
| 138 |
TOKsemicolon : ";", |
|---|
| 139 |
TOKdotdotdot : "...", |
|---|
| 140 |
TOKeof : "EOF", |
|---|
| 141 |
TOKcast : "cast", |
|---|
| 142 |
TOKnull : "null", |
|---|
| 143 |
TOKassert : "assert", |
|---|
| 144 |
TOKtrue : "true", |
|---|
| 145 |
TOKfalse : "false", |
|---|
| 146 |
TOKarray : "[]", |
|---|
| 147 |
TOKcall : "call", |
|---|
| 148 |
TOKaddress : "#", |
|---|
| 149 |
TOKtypedot : "typedot", |
|---|
| 150 |
TOKtype : "type", |
|---|
| 151 |
TOKthrow : "throw", |
|---|
| 152 |
TOKnew : "new", |
|---|
| 153 |
TOKdelete : "delete", |
|---|
| 154 |
TOKstar : "*", |
|---|
| 155 |
TOKsymoff : "symoff", |
|---|
| 156 |
TOKvar : "var", |
|---|
| 157 |
TOKdotvar : "dotvar", |
|---|
| 158 |
TOKdotti : "dotti", |
|---|
| 159 |
TOKdotexp : "dotexp", |
|---|
| 160 |
TOKdottype : "dottype", |
|---|
| 161 |
TOKslice : "..", |
|---|
| 162 |
TOKarraylength : "arraylength", |
|---|
| 163 |
TOKversion : "version", |
|---|
| 164 |
TOKmodule : "module", |
|---|
| 165 |
TOKdollar : "$", |
|---|
| 166 |
TOKtemplate : "template", |
|---|
| 167 |
TOKinstance : "instance", |
|---|
| 168 |
TOKdeclaration : "declaration", |
|---|
| 169 |
TOKtypeof : "typeof", |
|---|
| 170 |
TOKpragma : "pragma", |
|---|
| 171 |
TOKdsymbol : "dsymbol", |
|---|
| 172 |
TOKtypeid : "typeid", |
|---|
| 173 |
TOKuadd : "uadd", |
|---|
| 174 |
|
|---|
| 175 |
// Operators |
|---|
| 176 |
TOKlt : "<", |
|---|
| 177 |
TOKgt : ">", |
|---|
| 178 |
TOKle : "<=", |
|---|
| 179 |
TOKge : ">=", |
|---|
| 180 |
TOKequal : "==", |
|---|
| 181 |
TOKnotequal : "!=", |
|---|
| 182 |
TOKidentity : "===", |
|---|
| 183 |
TOKnotidentity : "!==", |
|---|
| 184 |
TOKindex : "[]", |
|---|
| 185 |
|
|---|
| 186 |
// NCEG floating point compares |
|---|
| 187 |
// !<>= <> <>= !> !>= !< !<= !<> |
|---|
| 188 |
|
|---|
| 189 |
// NOTE: These could be horribly wrong |
|---|
| 190 |
TOKunord : "!<>=", |
|---|
| 191 |
TOKue : "!<>", |
|---|
| 192 |
TOKlg : "<>", |
|---|
| 193 |
TOKleg : "<>=", |
|---|
| 194 |
TOKule : "!>", |
|---|
| 195 |
TOKul : "!>=", |
|---|
| 196 |
TOKuge : "!<", |
|---|
| 197 |
TOKug : "!<=", |
|---|
| 198 |
|
|---|
| 199 |
TOKshl : "<<", |
|---|
| 200 |
TOKshr : ">>", |
|---|
| 201 |
TOKshlass : "<<=", |
|---|
| 202 |
TOKshrass : ">>=", |
|---|
| 203 |
TOKushr : ">>>", |
|---|
| 204 |
TOKushrass : ">>>=", |
|---|
| 205 |
TOKcat : "~", |
|---|
| 206 |
TOKcatass : "~=", // ~ ~= |
|---|
| 207 |
TOKadd : "+", |
|---|
| 208 |
TOKmin : "-", |
|---|
| 209 |
TOKaddass : "+=", |
|---|
| 210 |
TOKminass : "-=", |
|---|
| 211 |
TOKmul : "*", |
|---|
| 212 |
TOKdiv : "/", |
|---|
| 213 |
TOKmod : "%", |
|---|
| 214 |
TOKmulass : "*=", |
|---|
| 215 |
TOKdivass : "/=", |
|---|
| 216 |
TOKmodass : "%=", |
|---|
| 217 |
TOKand : "&", |
|---|
| 218 |
TOKor : "|", |
|---|
| 219 |
TOKxor : "^", |
|---|
| 220 |
TOKandass : "&=", |
|---|
| 221 |
TOKorass : "|=", |
|---|
| 222 |
TOKxorass : "^=", |
|---|
| 223 |
TOKassign : "=", |
|---|
| 224 |
TOKnot : "!", |
|---|
| 225 |
TOKtilde : "~", |
|---|
| 226 |
TOKplusplus : "++", |
|---|
| 227 |
TOKminusminus : "--", |
|---|
| 228 |
TOKdot : ".", |
|---|
| 229 |
TOKarrow : "->", |
|---|
| 230 |
TOKcomma : ",", |
|---|
| 231 |
TOKquestion : "?", |
|---|
| 232 |
TOKandand : "&&", |
|---|
| 233 |
TOKoror : "||", |
|---|
| 234 |
|
|---|
| 235 |
// Numeric literals |
|---|
| 236 |
TOKint32v : "int32v", TOKuns32v : "uns32v", |
|---|
| 237 |
TOKint64v : "int64v", TOKuns64v : "uns64v", |
|---|
| 238 |
TOKfloat32v : "float32v", TOKfloat64v : "float64v", TOKfloat80v : "float80v", |
|---|
| 239 |
TOKimaginary32v : "imaginary32v", TOKimaginary64v : "imaginary64v", TOKimaginary80v : "imaginary80v", |
|---|
| 240 |
|
|---|
| 241 |
// Char constants |
|---|
| 242 |
TOKcharv : "charv", TOKwcharv : "wcharv", TOKdcharv : "dcharv", |
|---|
| 243 |
|
|---|
| 244 |
// Leaf operators |
|---|
| 245 |
TOKidentifier : "identifier", TOKstring : "string", |
|---|
| 246 |
TOKthis : "this", TOKsuper : "super", |
|---|
| 247 |
|
|---|
| 248 |
// Basic types |
|---|
| 249 |
TOKvoid : "void", |
|---|
| 250 |
TOKint8 : "byte", TOKuns8 : "ubyte", |
|---|
| 251 |
TOKint16 : "short", TOKuns16 : "ushort", |
|---|
| 252 |
TOKint32 : "int", TOKuns32 : "uint", |
|---|
| 253 |
TOKint64 : "long", TOKuns64 : "ulong", |
|---|
| 254 |
TOKfloat32 : "float", TOKfloat64 : "double", TOKfloat80 : "real", |
|---|
| 255 |
TOKimaginary32 : "ifloat", TOKimaginary64 : "idouble", TOKimaginary80 : "ireal", |
|---|
| 256 |
TOKcomplex32 : "cfloat", TOKcomplex64 : "cdouble", TOKcomplex80 : "creal", |
|---|
| 257 |
TOKchar : "char", TOKwchar : "wchar", TOKdchar : "dchar", TOKbit : "bit", |
|---|
| 258 |
|
|---|
| 259 |
// Aggregates |
|---|
| 260 |
TOKstruct : "struct", TOKclass : "class", TOKinterface : "interface", TOKunion : "union", TOKenum : "enum", TOKimport : "import", |
|---|
| 261 |
TOKtypedef : "typedef", TOKalias : "alias", TOKoverride : "override", TOKdelegate : "delegate", TOKfunction : "function", |
|---|
| 262 |
TOKmixin : "mixin", |
|---|
| 263 |
|
|---|
| 264 |
TOKalign : "align", TOKextern : "extern", TOKprivate : "private", TOKprotected : "protected", TOKpublic : "public", TOKexport : "export", |
|---|
| 265 |
TOKstatic : "static", /*TOKvirtual : "virtual",*/ TOKfinal : "final", TOKconst : "const", TOKabstract : "abstract", TOKvolatile : "volatile", |
|---|
| 266 |
TOKdebug : "debug", TOKdeprecated : "deprecated", TOKin : "in", TOKout : "out", TOKinout : "inout", |
|---|
| 267 |
TOKauto : "auto", TOKpackage : "package", |
|---|
| 268 |
|
|---|
| 269 |
// Statements |
|---|
| 270 |
TOKif : "if", TOKelse : "else", TOKwhile : "while", TOKfor : "for", TOKdo : "do", TOKswitch : "switch", |
|---|
| 271 |
TOKcase : "case", TOKdefault : "default", TOKbreak : "break", TOKcontinue : "continue", TOKwith : "with", |
|---|
| 272 |
TOKsynchronized : "synchronized", TOKreturn : "return", TOKgoto : "goto", TOKtry : "try", TOKcatch : "catch", TOKfinally : "finally", |
|---|
| 273 |
TOKasm : "asm", TOKforeach : "foreach", |
|---|
| 274 |
|
|---|
| 275 |
// Contracts |
|---|
| 276 |
TOKbody : "body", TOKinvariant : "invariant", |
|---|
| 277 |
|
|---|
| 278 |
// Testing |
|---|
| 279 |
TOKunittest : "unittest", |
|---|
| 280 |
]; |
|---|
| 281 |
|
|---|
| 282 |
class Identifier { |
|---|
| 283 |
int value; |
|---|
| 284 |
char[] string; |
|---|
| 285 |
|
|---|
| 286 |
this(char[] string, int value) { |
|---|
| 287 |
this.value = value; |
|---|
| 288 |
this.string = string; |
|---|
| 289 |
}; |
|---|
| 290 |
}; |
|---|
| 291 |
|
|---|
| 292 |
// A language token: |
|---|
| 293 |
class Token { |
|---|
| 294 |
// The kind of token: |
|---|
| 295 |
uint value; |
|---|
| 296 |
Token next; |
|---|
| 297 |
|
|---|
| 298 |
// The value for the token: |
|---|
| 299 |
union { |
|---|
| 300 |
// The identifier or value of the token: |
|---|
| 301 |
Identifier ident; |
|---|
| 302 |
|
|---|
| 303 |
char[] ustring; |
|---|
| 304 |
|
|---|
| 305 |
// Integers |
|---|
| 306 |
int int32value; |
|---|
| 307 |
uint uns32value; |
|---|
| 308 |
long int64value; |
|---|
| 309 |
ulong uns64value; |
|---|
| 310 |
|
|---|
| 311 |
// Floats |
|---|
| 312 |
real float80value; |
|---|
| 313 |
}; |
|---|
| 314 |
|
|---|
| 315 |
char[] toString() { |
|---|
| 316 |
return toktostr[value]; |
|---|
| 317 |
}; |
|---|
| 318 |
|
|---|
| 319 |
static char[] toChars(uint value) { |
|---|
| 320 |
return toktostr[value]; |
|---|
| 321 |
}; |
|---|
| 322 |
} |
|---|
| 323 |
|
|---|
| 324 |
// Exception thrown during parsing of D language: |
|---|
| 325 |
class DLexerException : Error { |
|---|
| 326 |
public: |
|---|
| 327 |
this(DLexer dlx, char[] msg) { |
|---|
| 328 |
// Construct an error message with the filename and line number: |
|---|
| 329 |
super(dlx.filename ~ "(" ~ format("%d", dlx.line) ~ ")" ~ ": " ~ msg); |
|---|
| 330 |
} |
|---|
| 331 |
} |
|---|
| 332 |
|
|---|
| 333 |
// Check for octal digit: |
|---|
| 334 |
int isodigit(dchar x) { |
|---|
| 335 |
if (!isdigit(x) || (x == '8') || (x == '9')) return 0; |
|---|
| 336 |
return -1; |
|---|
| 337 |
} |
|---|
| 338 |
|
|---|
| 339 |
class Loc { |
|---|
| 340 |
public: |
|---|
| 341 |
int linnum; |
|---|
| 342 |
|
|---|
| 343 |
this() { |
|---|
| 344 |
} |
|---|
| 345 |
} |
|---|
| 346 |
|
|---|
| 347 |
// The D language lexer (tokenizer): |
|---|
| 348 |
class DLexer { |
|---|
| 349 |
static uint[char[]] keywords; |
|---|
| 350 |
// Initialize the keyword->tokenvalue AA: |
|---|
| 351 |
static this() { |
|---|
| 352 |
// Add all the keywords' values into the AA: |
|---|
| 353 |
keywords["this"] = TOKthis; |
|---|
| 354 |
keywords["super"] = TOKsuper; |
|---|
| 355 |
keywords["assert"] = TOKassert; |
|---|
| 356 |
keywords["null"] = TOKnull; |
|---|
| 357 |
keywords["true"] = TOKtrue; |
|---|
| 358 |
keywords["false"] = TOKfalse; |
|---|
| 359 |
keywords["cast"] = TOKcast; |
|---|
| 360 |
keywords["new"] = TOKnew; |
|---|
| 361 |
keywords["delete"] = TOKdelete; |
|---|
| 362 |
keywords["throw"] = TOKthrow; |
|---|
| 363 |
keywords["module"] = TOKmodule; |
|---|
| 364 |
keywords["pragma"] = TOKpragma; |
|---|
| 365 |
keywords["typeof"] = TOKtypeof; |
|---|
| 366 |
keywords["typeid"] = TOKtypeid; |
|---|
| 367 |
|
|---|
| 368 |
keywords["template"] = TOKtemplate; |
|---|
| 369 |
keywords["instance"] = TOKinstance; |
|---|
| 370 |
|
|---|
| 371 |
keywords["void"] = TOKvoid; |
|---|
| 372 |
keywords["byte"] = TOKint8; |
|---|
| 373 |
keywords["ubyte"] = TOKuns8; |
|---|
| 374 |
keywords["short"] = TOKint16; |
|---|
| 375 |
keywords["ushort"] = TOKuns16; |
|---|
| 376 |
keywords["int"] = TOKint32; |
|---|
| 377 |
keywords["uint"] = TOKuns32; |
|---|
| 378 |
keywords["long"] = TOKint64; |
|---|
| 379 |
keywords["ulong"] = TOKuns64; |
|---|
| 380 |
keywords["float"] = TOKfloat32; |
|---|
| 381 |
keywords["double"] = TOKfloat64; |
|---|
| 382 |
keywords["real"] = TOKfloat80; |
|---|
| 383 |
|
|---|
| 384 |
keywords["bit"] = TOKbit; |
|---|
| 385 |
keywords["char"] = TOKchar; |
|---|
| 386 |
keywords["wchar"] = TOKwchar; |
|---|
| 387 |
keywords["dchar"] = TOKdchar; |
|---|
| 388 |
|
|---|
| 389 |
keywords["ifloat"] = TOKimaginary32; |
|---|
| 390 |
keywords["idouble"] = TOKimaginary64; |
|---|
| 391 |
keywords["ireal"] = TOKimaginary80; |
|---|
| 392 |
|
|---|
| 393 |
keywords["cfloat"] = TOKcomplex32; |
|---|
| 394 |
keywords["cdouble"] = TOKcomplex64; |
|---|
| 395 |
keywords["creal"] = TOKcomplex80; |
|---|
| 396 |
|
|---|
| 397 |
keywords["delegate"] = TOKdelegate; |
|---|
| 398 |
keywords["function"] = TOKfunction; |
|---|
| 399 |
|
|---|
| 400 |
keywords["is"] = TOKidentity; |
|---|
| 401 |
keywords["if"] = TOKif; |
|---|
| 402 |
keywords["else"] = TOKelse; |
|---|
| 403 |
keywords["while"] = TOKwhile; |
|---|
| 404 |
keywords["for"] = TOKfor; |
|---|
| 405 |
keywords["do"] = TOKdo; |
|---|
| 406 |
keywords["switch"] = TOKswitch; |
|---|
| 407 |
keywords["case"] = TOKcase; |
|---|
| 408 |
keywords["default"] = TOKdefault; |
|---|
| 409 |
keywords["break"] = TOKbreak; |
|---|
| 410 |
keywords["continue"] = TOKcontinue; |
|---|
| 411 |
keywords["synchronized"] = TOKsynchronized; |
|---|
| 412 |
keywords["return"] = TOKreturn; |
|---|
| 413 |
keywords["goto"] = TOKgoto; |
|---|
| 414 |
keywords["try"] = TOKtry; |
|---|
| 415 |
keywords["catch"] = TOKcatch; |
|---|
| 416 |
keywords["finally"] = TOKfinally; |
|---|
| 417 |
keywords["with"] = TOKwith; |
|---|
| 418 |
keywords["asm"] = TOKasm; |
|---|
| 419 |
keywords["foreach"] = TOKforeach; |
|---|
| 420 |
|
|---|
| 421 |
keywords["struct"] = TOKstruct; |
|---|
| 422 |
keywords["class"] = TOKclass; |
|---|
| 423 |
keywords["interface"] = TOKinterface; |
|---|
| 424 |
keywords["union"] = TOKunion; |
|---|
| 425 |
keywords["enum"] = TOKenum; |
|---|
| 426 |
keywords["import"] = TOKimport; |
|---|
| 427 |
keywords["mixin"] = TOKmixin; |
|---|
| 428 |
keywords["static"] = TOKstatic; |
|---|
| 429 |
/*keywords["virtual"] = TOKvirtual;*/ |
|---|
| 430 |
keywords["final"] = TOKfinal; |
|---|
| 431 |
keywords["const"] = TOKconst; |
|---|
| 432 |
keywords["typedef"] = TOKtypedef; |
|---|
| 433 |
keywords["alias"] = TOKalias; |
|---|
| 434 |
keywords["override"] = TOKoverride; |
|---|
| 435 |
keywords["abstract"] = TOKabstract; |
|---|
| 436 |
keywords["volatile"] = TOKvolatile; |
|---|
| 437 |
keywords["debug"] = TOKdebug; |
|---|
| 438 |
keywords["deprecated"] = TOKdeprecated; |
|---|
| 439 |
keywords["in"] = TOKin; |
|---|
| 440 |
keywords["out"] = TOKout; |
|---|
| 441 |
keywords["inout"] = TOKinout; |
|---|
| 442 |
keywords["auto"] = TOKauto; |
|---|
| 443 |
|
|---|
| 444 |
keywords["align"] = TOKalign; |
|---|
| 445 |
keywords["extern"] = TOKextern; |
|---|
| 446 |
keywords["private"] = TOKprivate; |
|---|
| 447 |
keywords["package"] = TOKpackage; |
|---|
| 448 |
keywords["protected"] = TOKprotected; |
|---|
| 449 |
keywords["public"] = TOKpublic; |
|---|
| 450 |
keywords["export"] = TOKexport; |
|---|
| 451 |
|
|---|
| 452 |
keywords["body"] = TOKbody; |
|---|
| 453 |
keywords["invariant"] = TOKinvariant; |
|---|
| 454 |
keywords["unittest"] = TOKunittest; |
|---|
| 455 |
keywords["version"] = TOKversion; |
|---|
| 456 |
} |
|---|
| 457 |
|
|---|
| 458 |
protected: |
|---|
| 459 |
Token token; |
|---|
| 460 |
Identifier[char[]] identifiers; |
|---|
| 461 |
Loc loc; |
|---|
| 462 |
|
|---|
| 463 |
private: |
|---|
| 464 |
char[] file; // The input file |
|---|
| 465 |
uint p; // Current character |
|---|
| 466 |
|
|---|
| 467 |
char[] wysiwygString(char tc) { |
|---|
| 468 |
char c; |
|---|
| 469 |
char[] s; |
|---|
| 470 |
uint i; |
|---|
| 471 |
|
|---|
| 472 |
i = 0; |
|---|
| 473 |
++p; |
|---|
| 474 |
s.length = 16; |
|---|
| 475 |
while (p < file.length) { |
|---|
| 476 |
c = file[p++]; |
|---|
| 477 |
switch (c) { |
|---|
| 478 |
case '\n': |
|---|
| 479 |
++line; |
|---|
| 480 |
break; |
|---|
| 481 |
|
|---|
| 482 |
case '\r': |
|---|
| 483 |
if (file[p] == '\n') |
|---|
| 484 |
continue; // ignore |
|---|
| 485 |
c = '\n'; // treat EndOfLine as \n character |
|---|
| 486 |
++line; |
|---|
| 487 |
break; |
|---|
| 488 |
|
|---|
| 489 |
case 0x1A: |
|---|
| 490 |
error("unterminated string constant starting at %s", s); |
|---|
| 491 |
return null; |
|---|
| 492 |
|
|---|
| 493 |
case '"', '`': |
|---|
| 494 |
if (c == tc) { |
|---|
| 495 |
s.length = i; |
|---|
| 496 |
return s; |
|---|
| 497 |
} |
|---|
| 498 |
break; |
|---|
| 499 |
|
|---|
| 500 |
default: |
|---|
| 501 |
break; |
|---|
| 502 |
} |
|---|
| 503 |
|
|---|
| 504 |
if (i == s.length) s.length = s.length * 2; |
|---|
| 505 |
s[i++] = c; |
|---|
| 506 |
} |
|---|
| 507 |
s.length = i; |
|---|
| 508 |
return s; |
|---|
| 509 |
} |
|---|
| 510 |
|
|---|
| 511 |
// Test this! |
|---|
| 512 |
char[] hexString() { |
|---|
| 513 |
char c; |
|---|
| 514 |
uint n = 0, i = 0; |
|---|
| 515 |
char[] s; |
|---|
| 516 |
ubyte v; |
|---|
| 517 |
|
|---|
| 518 |
p++; |
|---|
| 519 |
s.length = 16; |
|---|
| 520 |
while (p < file.length) { |
|---|
| 521 |
c = file[p++]; |
|---|
| 522 |
switch (c) { |
|---|
| 523 |
case ' ', '\t', '\v', '\f': |
|---|
| 524 |
continue; // skip white space |
|---|
| 525 |
|
|---|
| 526 |
case '\r': |
|---|
| 527 |
if (file[p] == '\n') |
|---|
| 528 |
continue; // ignore |
|---|
| 529 |
// Treat isolated '\r' as if it were a '\n' |
|---|
| 530 |
case '\n': |
|---|
| 531 |
++line; |
|---|
| 532 |
continue; |
|---|
| 533 |
|
|---|
| 534 |
case 0x1A: |
|---|
| 535 |
error("unterminated string constant starting at %s", s); |
|---|
| 536 |
return null; |
|---|
| 537 |
|
|---|
| 538 |
case '"': |
|---|
| 539 |
if (n & 1) { |
|---|
| 540 |
error("odd number (%d) of hex characters in hex string", n); |
|---|
| 541 |
return null; |
|---|
| 542 |
} |
|---|
| 543 |
s.length = i; |
|---|
| 544 |
return s; |
|---|
| 545 |
|
|---|
| 546 |
default: |
|---|
| 547 |
if (c >= '0' && c <= '9') |
|---|
| 548 |
c -= '0'; |
|---|
| 549 |
else if (c >= 'a' && c <= 'f') |
|---|
| 550 |
c -= 'a' - 10; |
|---|
| 551 |
else if (c >= 'A' && c <= 'F') |
|---|
| 552 |
c -= 'A' - 10; |
|---|
| 553 |
else |
|---|
| 554 |
error("non-hex character '%c'", c); |
|---|
| 555 |
if (n & 1) { |
|---|
| 556 |
v = (v << 4) | c; |
|---|
| 557 |
if (i == s.length) s.length = s.length * 2; |
|---|
| 558 |
s[i++] = v; |
|---|
| 559 |
} else |
|---|
| 560 |
v = c; |
|---|
| 561 |
++n; |
|---|
| 562 |
break; |
|---|
| 563 |
} |
|---|
| 564 |
} |
|---|
| 565 |
return null; |
|---|
| 566 |
} |
|---|
| 567 |
|
|---|
| 568 |
public: |
|---|
| 569 |
char[] filename; // Filename |
|---|
| 570 |
uint line; // Current line |
|---|
| 571 |
|
|---|
| 572 |
// Initialize the lexer with the full source code as a string: |
|---|
| 573 |
this(char[] filename, char[] src) {< |
|---|