Hex Artifact Content
Not logged in

Artifact fb194a438f1088e9f4431213f21ad0207ee44243:


0000: 6d 6f 64 75 6c 65 20 70 6f 6c 65 6d 79 2e 6c 65  module polemy.le
0010: 78 3b 0a 69 6d 70 6f 72 74 20 70 6f 6c 65 6d 79  x;.import polemy
0020: 2e 5f 63 6f 6d 6d 6f 6e 3b 0a 2f 2a 0d 0a 20 2a  ._common;./*.. *
0030: 20 41 75 74 68 6f 72 3a 20 20 6b 2e 69 6e 61 62   Author:  k.inab
0040: 61 0d 0a 20 2a 20 4c 69 63 65 6e 73 65 3a 20 4e  a.. * License: N
0050: 59 53 4c 20 30 2e 39 39 38 32 20 28 68 74 74 70  YSL 0.9982 (http
0060: 3a 2f 2f 77 77 77 2e 6b 6d 6f 6e 6f 73 2e 6e 65  ://www.kmonos.ne
0070: 74 2f 6e 79 73 6c 2f 0d 0a 20 2a 20 20 20 4c 65  t/nysl/.. *   Le
0080: 78 65 72 20 66 6f 72 20 74 68 65 20 70 6f 6c 65  xer for the pole
0090: 6d 79 20 70 72 6f 67 72 61 6d 6d 69 6e 67 20 6c  my programming l
00a0: 61 6e 67 75 61 67 65 0d 0a 20 2a 2f 0d 0a 0d 0a  anguage.. */....
00b0: 69 6d 70 6f 72 74 20 73 74 64 2e 66 69 6c 65 20  import std.file 
00c0: 3a 20 72 65 61 64 54 65 78 74 3b 0a 69 6d 70 6f  : readText;.impo
00d0: 72 74 20 73 74 64 2e 73 74 72 69 6e 67 20 3a 20  rt std.string : 
00e0: 6d 75 6e 63 68 3b 0a 69 6d 70 6f 72 74 20 73 74  munch;.import st
00f0: 64 2e 63 74 79 70 65 3b 0d 0a 0d 0a 2f 2f 2f 20  d.ctype;..../// 
0100: 52 65 70 72 65 73 65 6e 74 73 20 61 20 70 6f 73  Represents a pos
0110: 69 74 69 6f 6e 20 69 6e 20 61 20 73 6f 75 72 63  ition in a sourc
0120: 65 20 63 6f 64 65 0a 0d 0a 63 6c 61 73 73 20 4c  e code...class L
0130: 65 78 50 6f 73 69 74 69 6f 6e 0a 7b 0a 09 69 6d  exPosition.{..im
0140: 6d 75 74 61 62 6c 65 20 73 74 72 69 6e 67 20 66  mutable string f
0150: 69 6c 65 6e 61 6d 65 3b 20 2f 2f 2f 3c 20 6e 61  ilename; ///< na
0160: 6d 65 20 6f 66 20 74 68 65 20 73 6f 75 72 63 65  me of the source
0170: 20 66 69 6c 65 0a 09 69 6d 6d 75 74 61 62 6c 65   file..immutable
0180: 20 69 6e 74 20 20 20 20 6c 69 6e 65 6e 6f 3b 20   int    lineno; 
0190: 20 20 2f 2f 2f 3c 20 6c 69 6e 65 20 6e 75 6d 62    ///< line numb
01a0: 65 72 3a 20 31 2c 20 32 2c 20 2e 2e 2e 0a 09 69  er: 1, 2, .....i
01b0: 6d 6d 75 74 61 62 6c 65 20 69 6e 74 20 20 20 20  mmutable int    
01c0: 63 6f 6c 75 6d 6e 3b 20 20 20 2f 2f 2f 3c 20 63  column;   ///< c
01d0: 6f 6c 75 6d 6e 3a 20 31 2c 20 32 2c 20 2e 2e 2e  olumn: 1, 2, ...
01e0: 0d 0a 0d 0a 09 6f 76 65 72 72 69 64 65 20 73 74  .....override st
01f0: 72 69 6e 67 20 74 6f 53 74 72 69 6e 67 28 29 20  ring toString() 
0200: 63 6f 6e 73 74 0d 0a 09 09 7b 20 72 65 74 75 72  const....{ retur
0210: 6e 20 73 70 72 69 6e 74 66 21 22 25 73 3a 25 64  n sprintf!"%s:%d
0220: 3a 25 64 22 28 66 69 6c 65 6e 61 6d 65 2c 20 6c  :%d"(filename, l
0230: 69 6e 65 6e 6f 2c 20 63 6f 6c 75 6d 6e 29 3b 20  ineno, column); 
0240: 7d 0d 0a 0a 09 6d 69 78 69 6e 20 53 69 6d 70 6c  }....mixin Simpl
0250: 65 43 6f 6e 73 74 72 75 63 74 6f 72 3b 0d 0a 09  eConstructor;...
0260: 6d 69 78 69 6e 20 53 69 6d 70 6c 65 43 6f 6d 70  mixin SimpleComp
0270: 61 72 65 3b 0a 7d 0a 0a 75 6e 69 74 74 65 73 74  are;.}..unittest
0280: 0a 7b 0a 09 61 75 74 6f 20 70 20 3d 20 6e 65 77  .{..auto p = new
0290: 20 4c 65 78 50 6f 73 69 74 69 6f 6e 28 22 68 65   LexPosition("he
02a0: 6c 6c 6f 2e 63 70 70 22 2c 20 31 32 33 2c 20 34  llo.cpp", 123, 4
02b0: 35 29 3b 0d 0a 09 61 75 74 6f 20 71 20 3d 20 6e  5);...auto q = n
02c0: 65 77 20 4c 65 78 50 6f 73 69 74 69 6f 6e 28 22  ew LexPosition("
02d0: 68 65 6c 6c 6f 2e 63 70 70 22 2c 20 31 32 33 2c  hello.cpp", 123,
02e0: 20 34 36 29 3b 0d 0a 0a 09 61 73 73 65 72 74 28   46);....assert(
02f0: 20 70 2e 66 69 6c 65 6e 61 6d 65 20 3d 3d 20 22   p.filename == "
0300: 68 65 6c 6c 6f 2e 63 70 70 22 20 29 3b 0a 09 61  hello.cpp" );..a
0310: 73 73 65 72 74 28 20 70 2e 6c 69 6e 65 6e 6f 20  ssert( p.lineno 
0320: 3d 3d 20 31 32 33 20 29 3b 0a 09 61 73 73 65 72  == 123 );..asser
0330: 74 28 20 70 2e 63 6f 6c 75 6d 6e 20 3d 3d 20 34  t( p.column == 4
0340: 35 20 29 3b 0d 0a 09 61 73 73 65 72 74 28 20 74  5 );...assert( t
0350: 6f 21 73 74 72 69 6e 67 28 70 29 20 3d 3d 20 22  o!string(p) == "
0360: 68 65 6c 6c 6f 2e 63 70 70 3a 31 32 33 3a 34 35  hello.cpp:123:45
0370: 22 20 29 3b 0d 0a 09 61 73 73 65 72 74 28 20 70  " );...assert( p
0380: 20 3c 20 71 20 29 3b 0d 0a 09 61 73 73 65 72 74   < q );...assert
0390: 28 20 70 20 21 3d 20 71 20 29 3b 0d 0a 0a 09 61  ( p != q );....a
03a0: 73 73 65 72 74 28 20 21 5f 5f 74 72 61 69 74 73  ssert( !__traits
03b0: 28 63 6f 6d 70 69 6c 65 73 2c 20 6e 65 77 20 4c  (compiles, new L
03c0: 65 78 50 6f 73 69 74 69 6f 6e 29 20 29 3b 0a 09  exPosition) );..
03d0: 61 73 73 65 72 74 28 20 21 5f 5f 74 72 61 69 74  assert( !__trait
03e0: 73 28 63 6f 6d 70 69 6c 65 73 2c 20 70 2e 66 69  s(compiles, p.fi
03f0: 6c 65 6e 61 6d 65 3d 22 66 6f 6f 22 29 20 29 3b  lename="foo") );
0400: 0a 09 61 73 73 65 72 74 28 20 21 5f 5f 74 72 61  ..assert( !__tra
0410: 69 74 73 28 63 6f 6d 70 69 6c 65 73 2c 20 70 2e  its(compiles, p.
0420: 6c 69 6e 65 6e 6f 20 20 3d 37 38 39 29 20 29 3b  lineno  =789) );
0430: 0a 09 61 73 73 65 72 74 28 20 21 5f 5f 74 72 61  ..assert( !__tra
0440: 69 74 73 28 63 6f 6d 70 69 6c 65 73 2c 20 70 2e  its(compiles, p.
0450: 63 6f 6c 75 6d 6e 20 20 3d 32 32 32 29 20 29 3b  column  =222) );
0460: 0a 7d 0a 0d 0a 2f 2f 2f 20 52 65 70 72 65 73 65  .}.../// Represe
0470: 6e 74 73 20 61 20 6c 65 78 65 72 20 74 6f 6b 65  nts a lexer toke
0480: 6e 0a 0d 0a 63 6c 61 73 73 20 54 6f 6b 65 6e 0a  n...class Token.
0490: 7b 0a 09 65 6e 75 6d 20 4b 69 6e 64 20 7b 69 64  {..enum Kind {id
04a0: 65 6e 74 69 66 69 65 72 2c 20 73 74 72 69 6e 67  entifier, string
04b0: 4c 69 74 65 72 61 6c 2c 20 6e 75 6d 62 65 72 7d  Literal, number}
04c0: 3b 0d 0a 09 69 6d 6d 75 74 61 62 6c 65 20 4c 65  ;...immutable Le
04d0: 78 50 6f 73 69 74 69 6f 6e 20 70 6f 73 3b 20 20  xPosition pos;  
04e0: 2f 2f 2f 3c 20 70 6f 73 69 74 69 6f 6e 20 77 68  ///< position wh
04f0: 65 72 65 20 74 68 65 20 74 6f 6b 65 6e 20 6f 63  ere the token oc
0500: 63 75 72 72 65 64 20 69 6e 20 74 68 65 20 73 6f  curred in the so
0510: 75 72 63 65 0a 09 69 6d 6d 75 74 61 62 6c 65 20  urce..immutable 
0520: 73 74 72 69 6e 67 20 20 20 20 20 20 73 74 72 3b  string      str;
0530: 20 20 2f 2f 2f 3c 20 74 68 65 20 74 6f 6b 65 6e    ///< the token
0540: 20 73 74 72 69 6e 67 20 69 74 73 65 6c 66 0d 0a   string itself..
0550: 09 69 6d 6d 75 74 61 62 6c 65 20 4b 69 6e 64 20  .immutable Kind 
0560: 20 20 20 20 20 20 20 6b 69 6e 64 3b 20 2f 2f 2f         kind; ///
0570: 3c 20 77 68 69 63 68 20 6b 69 6e 64 20 6f 66 20  < which kind of 
0580: 74 6f 6b 65 6e 3f 0d 0a 0d 0a 09 6d 69 78 69 6e  token?.....mixin
0590: 20 53 69 6d 70 6c 65 43 6f 6e 73 74 72 75 63 74   SimpleConstruct
05a0: 6f 72 3b 0d 0a 09 6d 69 78 69 6e 20 53 69 6d 70  or;...mixin Simp
05b0: 6c 65 43 6f 6d 70 61 72 65 3b 0a 7d 0a 0a 75 6e  leCompare;.}..un
05c0: 69 74 74 65 73 74 0a 7b 0a 09 61 75 74 6f 20 70  ittest.{..auto p
05d0: 20 3d 20 6e 65 77 20 69 6d 6d 75 74 61 62 6c 65   = new immutable
05e0: 28 4c 65 78 50 6f 73 69 74 69 6f 6e 29 28 22 68  (LexPosition)("h
05f0: 65 6c 6c 6f 2e 63 70 70 22 2c 20 31 32 33 2c 20  ello.cpp", 123, 
0600: 34 35 29 3b 0a 09 61 75 74 6f 20 74 20 3d 20 6e  45);..auto t = n
0610: 65 77 20 54 6f 6b 65 6e 28 70 2c 20 22 63 6c 61  ew Token(p, "cla
0620: 73 73 22 2c 20 54 6f 6b 65 6e 2e 4b 69 6e 64 2e  ss", Token.Kind.
0630: 69 64 65 6e 74 69 66 69 65 72 29 3b 0a 0a 09 61  identifier);...a
0640: 73 73 65 72 74 28 20 74 2e 70 6f 73 20 3d 3d 20  ssert( t.pos == 
0650: 70 20 29 3b 0a 09 61 73 73 65 72 74 28 20 74 2e  p );..assert( t.
0660: 73 74 72 20 3d 3d 20 22 63 6c 61 73 73 22 20 29  str == "class" )
0670: 3b 0d 0a 09 61 73 73 65 72 74 28 20 74 20 3d 3d  ;...assert( t ==
0680: 20 6e 65 77 20 54 6f 6b 65 6e 28 70 2c 20 22 63   new Token(p, "c
0690: 6c 61 73 73 22 2c 20 54 6f 6b 65 6e 2e 4b 69 6e  lass", Token.Kin
06a0: 64 2e 69 64 65 6e 74 69 66 69 65 72 29 20 29 3b  d.identifier) );
06b0: 0d 0a 09 61 73 73 65 72 74 28 20 74 20 3c 20 6e  ...assert( t < n
06c0: 65 77 20 54 6f 6b 65 6e 28 70 2c 20 22 73 74 72  ew Token(p, "str
06d0: 75 63 74 22 2c 20 54 6f 6b 65 6e 2e 4b 69 6e 64  uct", Token.Kind
06e0: 2e 69 64 65 6e 74 69 66 69 65 72 29 20 29 3b 0d  .identifier) );.
06f0: 0a 0a 09 61 73 73 65 72 74 28 20 21 5f 5f 74 72  ...assert( !__tr
0700: 61 69 74 73 28 63 6f 6d 70 69 6c 65 73 2c 20 6e  aits(compiles, n
0710: 65 77 20 54 6f 6b 65 6e 29 20 29 3b 0a 09 61 73  ew Token) );..as
0720: 73 65 72 74 28 20 21 5f 5f 74 72 61 69 74 73 28  sert( !__traits(
0730: 63 6f 6d 70 69 6c 65 73 2c 20 74 2e 70 6f 73 3d  compiles, t.pos=
0740: 70 29 20 29 3b 0a 09 61 73 73 65 72 74 28 20 21  p) );..assert( !
0750: 5f 5f 74 72 61 69 74 73 28 63 6f 6d 70 69 6c 65  __traits(compile
0760: 73 2c 20 74 2e 73 74 72 3d 37 38 39 29 20 29 3b  s, t.str=789) );
0770: 0a 7d 0a 0d 0a 2f 2f 2f 20 4e 61 6d 65 64 20 43  .}.../// Named C
0780: 6f 6e 73 74 72 75 74 6f 72 20 66 6f 72 20 4c 65  onstrutor for Le
0790: 78 65 72 0d 0a 0d 0a 4c 65 78 65 72 20 6c 65 78  xer....Lexer lex
07a0: 65 72 46 72 6f 6d 46 69 6c 65 28 54 2e 2e 2e 29  erFromFile(T...)
07b0: 28 20 73 74 72 69 6e 67 20 66 69 6c 65 6e 61 6d  ( string filenam
07c0: 65 2c 20 54 20 72 65 73 74 20 29 0d 0a 7b 0d 0a  e, T rest )..{..
07d0: 09 72 65 74 75 72 6e 20 6c 65 78 65 72 46 72 6f  .return lexerFro
07e0: 6d 53 74 72 69 6e 67 28 20 73 74 64 2e 66 69 6c  mString( std.fil
07f0: 65 2e 72 65 61 64 54 65 78 74 28 66 69 6c 65 6e  e.readText(filen
0800: 61 6d 65 29 2c 20 66 69 6c 65 6e 61 6d 65 2c 20  ame), filename, 
0810: 72 65 73 74 20 29 3b 0d 0a 7d 0d 0a 09 0d 0a 2f  rest );..}...../
0820: 2f 2f 20 4e 61 6d 65 64 20 43 6f 6e 73 74 72 75  // Named Constru
0830: 74 6f 72 20 66 6f 72 20 4c 65 78 65 72 0d 0a 0d  tor for Lexer...
0840: 0a 4c 65 78 65 72 20 6c 65 78 65 72 46 72 6f 6d  .Lexer lexerFrom
0850: 53 74 72 69 6e 67 28 20 73 74 72 69 6e 67 20 73  String( string s
0860: 74 72 2c 20 73 74 72 69 6e 67 20 66 69 6c 65 6e  tr, string filen
0870: 61 6d 65 3d 22 3c 75 6e 6e 61 6d 65 64 3e 22 2c  ame="<unnamed>",
0880: 20 69 6e 74 20 6c 69 6e 65 6e 6f 3d 31 2c 20 69   int lineno=1, i
0890: 6e 74 20 63 6f 6c 75 6d 6e 3d 31 20 29 0d 0a 7b  nt column=1 )..{
08a0: 0d 0a 09 72 65 74 75 72 6e 20 6e 65 77 20 4c 65  ...return new Le
08b0: 78 65 72 28 73 74 72 2c 20 66 69 6c 65 6e 61 6d  xer(str, filenam
08c0: 65 2c 20 6c 69 6e 65 6e 6f 2c 20 63 6f 6c 75 6d  e, lineno, colum
08d0: 6e 29 3b 0d 0a 7d 0d 0a 0d 0a 2f 2f 2f 20 4c 65  n);..}..../// Le
08e0: 78 65 72 20 69 73 20 61 20 66 6f 72 77 61 72 64  xer is a forward
08f0: 20 72 61 6e 67 65 20 6f 66 20 54 6f 6b 65 6e 73   range of Tokens
0900: 0d 0a 0d 0a 63 6c 61 73 73 20 4c 65 78 65 72 0a  ....class Lexer.
0910: 7b 0a 09 62 6f 6f 6c 20 65 6d 70 74 79 28 29 20  {..bool empty() 
0920: 2f 2a 40 70 72 6f 70 65 72 74 79 2a 2f 0a 09 7b  /*@property*/..{
0930: 0a 09 09 72 65 74 75 72 6e 20 63 75 72 72 65 6e  ...return curren
0940: 74 20 69 73 20 6e 75 6c 6c 3b 0a 09 7d 0a 0a 09  t is null;..}...
0950: 54 6f 6b 65 6e 20 66 72 6f 6e 74 28 29 20 2f 2a  Token front() /*
0960: 40 70 72 6f 70 65 72 74 79 2a 2f 0a 09 7b 0a 09  @property*/..{..
0970: 09 72 65 74 75 72 6e 20 73 74 64 2e 65 78 63 65  .return std.exce
0980: 70 74 69 6f 6e 2e 65 6e 66 6f 72 63 65 28 63 75  ption.enforce(cu
0990: 72 72 65 6e 74 2c 20 22 4c 65 78 65 72 20 68 61  rrent, "Lexer ha
09a0: 73 20 61 6c 72 65 61 64 79 20 72 65 61 63 68 65  s already reache
09b0: 64 20 74 68 65 20 65 6e 64 22 29 3b 0a 09 7d 0a  d the end");..}.
09c0: 0a 09 76 6f 69 64 20 70 6f 70 46 72 6f 6e 74 28  ..void popFront(
09d0: 29 20 2f 2a 40 70 72 6f 70 65 72 74 79 2a 2f 0a  ) /*@property*/.
09e0: 09 7b 0a 09 09 73 74 64 2e 65 78 63 65 70 74 69  .{...std.excepti
09f0: 6f 6e 2e 65 6e 66 6f 72 63 65 28 63 75 72 72 65  on.enforce(curre
0a00: 6e 74 2c 20 22 4c 65 78 65 72 20 68 61 73 20 61  nt, "Lexer has a
0a10: 6c 72 65 61 64 79 20 72 65 61 63 68 65 64 20 74  lready reached t
0a20: 68 65 20 65 6e 64 22 29 3b 0d 0a 09 09 63 75 72  he end");....cur
0a30: 72 65 6e 74 20 3d 20 72 65 61 64 4e 65 78 74 28  rent = readNext(
0a40: 29 3b 0a 09 7d 0a 0a 09 4c 65 78 65 72 20 73 61  );..}...Lexer sa
0a50: 76 65 28 29 20 2f 2a 40 70 72 6f 70 65 72 74 79  ve() /*@property
0a60: 2a 2f 0a 09 7b 0a 09 09 72 65 74 75 72 6e 20 6e  */..{...return n
0a70: 65 77 20 4c 65 78 65 72 28 62 75 66 66 65 72 2c  ew Lexer(buffer,
0a80: 20 66 69 6c 65 6e 61 6d 65 2c 20 6c 69 6e 65 6e   filename, linen
0a90: 6f 2c 20 63 6f 6c 75 6d 6e 2c 20 63 75 72 72 65  o, column, curre
0aa0: 6e 74 29 3b 0a 09 7d 0a 0a 70 72 69 76 61 74 65  nt);..}..private
0ab0: 3a 20 2f 2f 20 69 6d 70 6c 65 6d 65 6e 74 61 74  : // implementat
0ac0: 69 6f 6e 0a 0d 0a 09 73 74 72 69 6e 67 20 62 75  ion....string bu
0ad0: 66 66 65 72 3b 0a 09 73 74 72 69 6e 67 20 66 69  ffer;..string fi
0ae0: 6c 65 6e 61 6d 65 3b 0a 09 69 6e 74 20 20 20 20  lename;..int    
0af0: 6c 69 6e 65 6e 6f 3b 0a 09 69 6e 74 20 20 20 20  lineno;..int    
0b00: 63 6f 6c 75 6d 6e 3b 0a 09 54 6f 6b 65 6e 20 20  column;..Token  
0b10: 63 75 72 72 65 6e 74 3b 0a 0a 09 69 6e 76 61 72  current;...invar
0b20: 69 61 6e 74 28 29 0a 09 7b 0d 0a 09 09 61 73 73  iant()..{....ass
0b30: 65 72 74 28 20 62 75 66 66 65 72 2e 65 6d 70 74  ert( buffer.empt
0b40: 79 20 7c 7c 20 21 73 74 64 2e 63 74 79 70 65 2e  y || !std.ctype.
0b50: 69 73 73 70 61 63 65 28 62 75 66 66 65 72 5b 30  isspace(buffer[0
0b60: 5d 29 20 29 3b 0a 09 7d 0a 0a 09 74 68 69 73 28  ]) );..}...this(
0b70: 20 73 74 72 69 6e 67 20 62 75 66 66 65 72 2c 20   string buffer, 
0b80: 73 74 72 69 6e 67 20 66 69 6c 65 6e 61 6d 65 2c  string filename,
0b90: 20 69 6e 74 20 6c 69 6e 65 6e 6f 2c 20 69 6e 74   int lineno, int
0ba0: 20 63 6f 6c 75 6d 6e 2c 20 54 6f 6b 65 6e 20 63   column, Token c
0bb0: 75 72 72 65 6e 74 3d 6e 75 6c 6c 20 29 0a 09 7b  urrent=null )..{
0bc0: 0a 09 09 74 68 69 73 2e 62 75 66 66 65 72 20 20  ...this.buffer  
0bd0: 20 3d 20 62 75 66 66 65 72 3b 0a 09 09 74 68 69   = buffer;...thi
0be0: 73 2e 66 69 6c 65 6e 61 6d 65 20 3d 20 66 69 6c  s.filename = fil
0bf0: 65 6e 61 6d 65 3b 0a 09 09 74 68 69 73 2e 6c 69  ename;...this.li
0c00: 6e 65 6e 6f 20 20 20 3d 20 6c 69 6e 65 6e 6f 3b  neno   = lineno;
0c10: 0a 09 09 74 68 69 73 2e 63 6f 6c 75 6d 6e 20 20  ...this.column  
0c20: 20 3d 20 63 6f 6c 75 6d 6e 3b 0a 09 09 73 6b 69   = column;...ski
0c30: 70 77 73 28 29 3b 0a 09 09 74 68 69 73 2e 63 75  pws();...this.cu
0c40: 72 72 65 6e 74 20 20 3d 20 28 63 75 72 72 65 6e  rrent  = (curren
0c50: 74 20 69 73 20 6e 75 6c 6c 20 3f 20 72 65 61 64  t is null ? read
0c60: 4e 65 78 74 28 29 20 3a 20 63 75 72 72 65 6e 74  Next() : current
0c70: 29 3b 0a 09 7d 0a 0a 09 76 6f 69 64 20 73 6b 69  );..}...void ski
0c80: 70 77 73 28 29 0a 09 7b 0d 0a 09 09 62 6f 6f 6c  pws()..{....bool
0c90: 20 70 72 6f 67 72 65 73 73 20 3d 20 66 61 6c 73   progress = fals
0ca0: 65 3b 0d 0a 09 09 64 6f 0a 09 09 7b 0a 09 09 09  e;....do...{....
0cb0: 73 74 72 69 6e 67 20 77 73 20 3d 20 62 75 66 66  string ws = buff
0cc0: 65 72 2e 6d 75 6e 63 68 28 22 20 5c 74 22 29 3b  er.munch(" \t");
0cd0: 0a 09 09 09 63 6f 6c 75 6d 6e 20 2b 3d 20 77 73  ....column += ws
0ce0: 2e 6c 65 6e 67 74 68 3b 0d 0a 09 09 09 70 72 6f  .length;.....pro
0cf0: 67 72 65 73 73 20 3d 20 21 77 73 2e 65 6d 70 74  gress = !ws.empt
0d00: 79 3b 0d 0a 09 09 09 77 68 69 6c 65 28 20 21 62  y;.....while( !b
0d10: 75 66 66 65 72 2e 65 6d 70 74 79 20 26 26 20 28  uffer.empty && (
0d20: 62 75 66 66 65 72 5b 30 5d 3d 3d 27 5c 72 27 20  buffer[0]=='\r' 
0d30: 7c 7c 20 62 75 66 66 65 72 5b 30 5d 3d 3d 27 5c  || buffer[0]=='\
0d40: 6e 27 29 20 29 0a 09 09 09 7b 0d 0a 09 09 09 09  n') )....{......
0d50: 70 72 6f 67 72 65 73 73 20 3d 20 74 72 75 65 3b  progress = true;
0d60: 0a 09 09 09 09 69 66 28 20 62 75 66 66 65 72 5b  .....if( buffer[
0d70: 30 5d 20 3d 3d 20 27 5c 6e 27 20 29 0a 09 09 09  0] == '\n' )....
0d80: 09 09 62 75 66 66 65 72 20 3d 20 62 75 66 66 65  ..buffer = buffe
0d90: 72 5b 31 2e 2e 24 5d 3b 0a 09 09 09 09 65 6c 73  r[1..$];.....els
0da0: 65 20 2f 2f 20 69 66 28 20 62 75 66 66 65 72 2e  e // if( buffer.
0db0: 66 72 6f 6e 74 20 3d 3d 20 27 5c 72 27 20 29 0a  front == '\r' ).
0dc0: 09 09 09 09 7b 0a 09 09 09 09 09 62 75 66 66 65  ....{......buffe
0dd0: 72 20 3d 20 62 75 66 66 65 72 5b 31 2e 2e 24 5d  r = buffer[1..$]
0de0: 3b 0a 09 09 09 09 09 69 66 28 20 21 62 75 66 66  ;......if( !buff
0df0: 65 72 2e 65 6d 70 74 79 20 26 26 20 62 75 66 66  er.empty && buff
0e00: 65 72 5b 30 5d 3d 3d 27 5c 6e 27 20 29 0a 09 09  er[0]=='\n' )...
0e10: 09 09 09 09 62 75 66 66 65 72 20 3d 20 62 75 66  ....buffer = buf
0e20: 66 65 72 5b 31 2e 2e 24 5d 3b 0a 09 09 09 09 7d  fer[1..$];.....}
0e30: 0a 09 09 09 09 6c 69 6e 65 6e 6f 20 2b 2b 3b 0a  .....lineno ++;.
0e40: 09 09 09 09 63 6f 6c 75 6d 6e 20 3d 20 31 3b 0a  ....column = 1;.
0e50: 09 09 09 7d 0a 09 09 7d 77 68 69 6c 65 28 20 70  ...}...}while( p
0e60: 72 6f 67 72 65 73 73 20 29 3b 0a 09 7d 0a 0d 0a  rogress );..}...
0e70: 09 63 68 61 72 20 72 65 61 64 43 68 61 72 28 29  .char readChar()
0e80: 0d 0a 09 7b 0d 0a 09 09 73 63 6f 70 65 28 65 78  ...{....scope(ex
0e90: 69 74 29 20 7b 0d 0a 09 09 09 62 75 66 66 65 72  it) {.....buffer
0ea0: 20 3d 20 62 75 66 66 65 72 5b 31 2e 2e 24 5d 3b   = buffer[1..$];
0eb0: 0d 0a 09 09 09 63 6f 6c 75 6d 6e 20 2b 2b 3b 0d  .....column ++;.
0ec0: 0a 09 09 7d 0d 0a 09 09 72 65 74 75 72 6e 20 62  ...}....return b
0ed0: 75 66 66 65 72 5b 30 5d 3b 0d 0a 09 7d 0d 0a 0d  uffer[0];...}...
0ee0: 0a 09 2f 2f 2f 20 54 68 69 73 20 69 73 20 74 68  ../// This is th
0ef0: 65 20 6d 61 69 6e 20 6c 65 78 69 6e 67 20 72 6f  e main lexing ro
0f00: 75 74 69 6e 65 0a 09 54 6f 6b 65 6e 20 72 65 61  utine..Token rea
0f10: 64 4e 65 78 74 28 29 0a 09 7b 0d 0a 09 09 69 66  dNext()..{....if
0f20: 28 20 62 75 66 66 65 72 2e 65 6d 70 74 79 20 29  ( buffer.empty )
0f30: 0a 09 09 09 72 65 74 75 72 6e 20 6e 75 6c 6c 3b  ....return null;
0f40: 0a 09 09 73 63 6f 70 65 28 65 78 69 74 29 0a 09  ...scope(exit)..
0f50: 09 09 73 6b 69 70 77 73 28 29 3b 0a 0a 09 09 69  ..skipws();....i
0f60: 66 28 20 69 73 53 79 6d 62 6f 6c 28 62 75 66 66  f( isSymbol(buff
0f70: 65 72 5b 30 5d 29 20 29 0a 09 09 7b 0d 0a 09 09  er[0]) )...{....
0f80: 09 69 66 28 20 62 75 66 66 65 72 5b 30 5d 20 3d  .if( buffer[0] =
0f90: 3d 20 27 23 27 20 29 0d 0a 09 09 09 7b 0d 0a 09  = '#' ).....{...
0fa0: 09 09 09 2f 2f 20 73 6b 69 70 20 63 6f 6d 6d 65  ...// skip comme
0fb0: 6e 74 0d 0a 09 09 09 09 77 68 69 6c 65 28 20 21  nt......while( !
0fc0: 62 75 66 66 65 72 2e 65 6d 70 74 79 20 26 26 20  buffer.empty && 
0fd0: 28 62 75 66 66 65 72 5b 30 5d 21 3d 27 5c 6e 27  (buffer[0]!='\n'
0fe0: 20 26 26 20 62 75 66 66 65 72 5b 30 5d 21 3d 27   && buffer[0]!='
0ff0: 5c 72 27 29 20 29 0d 0a 09 09 09 09 09 72 65 61  \r') ).......rea
1000: 64 43 68 61 72 28 29 3b 0d 0a 09 09 09 09 73 6b  dChar();......sk
1010: 69 70 77 73 28 29 3b 0d 0a 09 09 09 09 72 65 74  ipws();......ret
1020: 75 72 6e 20 72 65 61 64 4e 65 78 74 28 29 3b 0d  urn readNext();.
1030: 0a 09 09 09 7d 0d 0a 09 09 09 65 6c 73 65 20 69  ....}.....else i
1040: 66 28 20 62 75 66 66 65 72 5b 30 5d 20 3d 3d 20  f( buffer[0] == 
1050: 27 22 27 20 29 0d 0a 09 09 09 7b 0d 0a 09 09 09  '"' ).....{.....
1060: 09 2f 2f 20 73 74 72 69 6e 67 20 6c 69 74 65 72  .// string liter
1070: 61 6c 0d 0a 09 09 09 09 61 75 74 6f 20 70 6f 73  al......auto pos
1080: 20 3d 20 63 75 72 72 65 6e 74 50 6f 73 69 74 69   = currentPositi
1090: 6f 6e 28 29 3b 0d 0a 09 09 09 09 73 74 72 69 6e  on();......strin
10a0: 67 20 6c 69 74 3b 0d 0a 09 09 09 09 72 65 61 64  g lit;......read
10b0: 43 68 61 72 28 29 3b 0d 0a 09 09 09 09 77 68 69  Char();......whi
10c0: 6c 65 28 20 21 62 75 66 66 65 72 2e 65 6d 70 74  le( !buffer.empt
10d0: 79 20 26 26 20 62 75 66 66 65 72 5b 30 5d 21 3d  y && buffer[0]!=
10e0: 27 22 27 20 29 0d 0a 09 09 09 09 7b 0d 0a 09 09  '"' )......{....
10f0: 09 09 09 2f 2f 20 72 65 61 64 20 6f 6e 65 20 63  ...// read one c
1100: 68 61 72 0d 0a 09 09 09 09 09 63 68 61 72 20 63  har.......char c
1110: 20 3d 20 72 65 61 64 43 68 61 72 28 29 3b 0d 0a   = readChar();..
1120: 09 09 09 09 09 69 66 28 20 63 20 3d 3d 20 27 5c  .....if( c == '\
1130: 5c 27 20 29 0d 0a 09 09 09 09 09 7b 0d 0a 09 09  \' ).......{....
1140: 09 09 09 09 69 66 28 20 21 62 75 66 66 65 72 2e  ....if( !buffer.
1150: 65 6d 70 74 79 20 26 26 20 28 62 75 66 66 65 72  empty && (buffer
1160: 5b 30 5d 3d 3d 27 5c 5c 27 20 7c 7c 20 62 75 66  [0]=='\\' || buf
1170: 66 65 72 5b 30 5d 3d 3d 27 22 27 29 20 29 0d 0a  fer[0]=='"') )..
1180: 09 09 09 09 09 09 09 6c 69 74 20 7e 3d 20 72 65  .......lit ~= re
1190: 61 64 43 68 61 72 28 29 3b 0d 0a 09 09 09 09 09  adChar();.......
11a0: 09 65 6c 73 65 0d 0a 09 09 09 09 09 09 09 6c 69  .else.........li
11b0: 74 20 7e 3d 20 63 3b 0d 0a 09 09 09 09 09 7d 0d  t ~= c;.......}.
11c0: 0a 09 09 09 09 09 65 6c 73 65 20 69 66 28 20 63  ......else if( c
11d0: 20 3d 3d 20 27 5c 6e 27 20 29 0d 0a 09 09 09 09   == '\n' )......
11e0: 09 7b 0d 0a 09 09 09 09 09 09 6c 69 74 20 7e 3d  .{........lit ~=
11f0: 20 63 3b 0d 0a 09 09 09 09 09 09 6c 69 6e 65 6e   c;........linen
1200: 6f 2b 2b 3b 0d 0a 09 09 09 09 09 09 63 6f 6c 75  o++;........colu
1210: 6d 6e 20 3d 20 31 3b 0d 0a 09 09 09 09 09 7d 0d  mn = 1;.......}.
1220: 0a 09 09 09 09 09 65 6c 73 65 20 69 66 28 20 63  ......else if( c
1230: 20 3d 3d 20 27 5c 72 27 20 29 0d 0a 09 09 09 09   == '\r' )......
1240: 09 7b 0d 0a 09 09 09 09 09 09 69 66 28 20 21 62  .{........if( !b
1250: 75 66 66 65 72 2e 65 6d 70 74 79 20 26 26 20 62  uffer.empty && b
1260: 75 66 66 65 72 5b 30 5d 3d 3d 27 5c 6e 27 20 29  uffer[0]=='\n' )
1270: 0d 0a 09 09 09 09 09 09 09 72 65 61 64 43 68 61  .........readCha
1280: 72 28 29 3b 0d 0a 09 09 09 09 09 09 6c 69 74 20  r();........lit 
1290: 7e 3d 20 27 5c 6e 27 3b 0d 0a 09 09 09 09 09 09  ~= '\n';........
12a0: 6c 69 6e 65 6e 6f 2b 2b 3b 0d 0a 09 09 09 09 09  lineno++;.......
12b0: 09 63 6f 6c 75 6d 6e 20 3d 20 31 3b 0d 0a 09 09  .column = 1;....
12c0: 09 09 09 7d 0d 0a 09 09 09 09 09 65 6c 73 65 0d  ...}.......else.
12d0: 0a 09 09 09 09 09 09 6c 69 74 20 7e 3d 20 63 3b  .......lit ~= c;
12e0: 0d 0a 09 09 09 09 7d 0d 0a 09 09 09 09 69 66 28  ......}......if(
12f0: 20 21 62 75 66 66 65 72 2e 65 6d 70 74 79 20 29   !buffer.empty )
1300: 0d 0a 09 09 09 09 09 72 65 61 64 43 68 61 72 28  .......readChar(
1310: 29 3b 0d 0a 09 09 09 09 72 65 74 75 72 6e 20 6e  );......return n
1320: 65 77 20 54 6f 6b 65 6e 28 70 6f 73 2c 20 6c 69  ew Token(pos, li
1330: 74 2c 20 54 6f 6b 65 6e 2e 4b 69 6e 64 2e 73 74  t, Token.Kind.st
1340: 72 69 6e 67 4c 69 74 65 72 61 6c 29 3b 0d 0a 09  ringLiteral);...
1350: 09 09 7d 0d 0a 09 09 09 65 6c 73 65 0d 0a 09 09  ..}.....else....
1360: 09 7b 0d 0a 09 09 09 09 2f 2f 20 6e 6f 72 6d 61  .{......// norma
1370: 6c 20 73 79 6d 62 6f 6c 0a 09 09 09 09 61 75 74  l symbol.....aut
1380: 6f 20 70 6f 73 20 3d 20 63 75 72 72 65 6e 74 50  o pos = currentP
1390: 6f 73 69 74 69 6f 6e 28 29 3b 0d 0a 09 09 09 09  osition();......
13a0: 61 75 74 6f 20 73 74 72 20 3d 20 22 22 7e 72 65  auto str = ""~re
13b0: 61 64 43 68 61 72 28 29 3b 0a 09 09 09 09 72 65  adChar();.....re
13c0: 74 75 72 6e 20 6e 65 77 20 54 6f 6b 65 6e 28 70  turn new Token(p
13d0: 6f 73 2c 20 73 74 72 2c 20 54 6f 6b 65 6e 2e 4b  os, str, Token.K
13e0: 69 6e 64 2e 69 64 65 6e 74 69 66 69 65 72 29 3b  ind.identifier);
13f0: 0d 0a 09 09 09 7d 0a 09 09 7d 0a 09 09 65 6c 73  .....}...}...els
1400: 65 0a 09 09 7b 0a 09 09 09 61 75 74 6f 20 70 6f  e...{....auto po
1410: 73 20 3d 20 63 75 72 72 65 6e 74 50 6f 73 69 74  s = currentPosit
1420: 69 6f 6e 28 29 3b 0a 09 09 09 69 6e 74 20 69 20  ion();....int i 
1430: 3d 20 30 3b 0a 09 09 09 77 68 69 6c 65 28 20 69  = 0;....while( i
1440: 3c 62 75 66 66 65 72 2e 6c 65 6e 67 74 68 20 26  <buffer.length &
1450: 26 20 21 73 74 64 2e 63 74 79 70 65 2e 69 73 73  & !std.ctype.iss
1460: 70 61 63 65 28 62 75 66 66 65 72 5b 69 5d 29 20  pace(buffer[i]) 
1470: 26 26 20 21 69 73 53 79 6d 62 6f 6c 28 62 75 66  && !isSymbol(buf
1480: 66 65 72 5b 69 5d 29 20 29 0a 09 09 09 09 2b 2b  fer[i]) ).....++
1490: 69 3b 0a 09 09 09 61 75 74 6f 20 73 74 72 20 3d  i;....auto str =
14a0: 20 62 75 66 66 65 72 5b 30 20 2e 2e 20 69 5d 3b   buffer[0 .. i];
14b0: 0a 09 09 09 62 75 66 66 65 72 20 20 20 3d 20 62  ....buffer   = b
14c0: 75 66 66 65 72 5b 69 20 2e 2e 20 24 5d 3b 0a 09  uffer[i .. $];..
14d0: 09 09 63 6f 6c 75 6d 6e 20 20 2b 3d 20 69 3b 0d  ..column  += i;.
14e0: 0a 09 09 09 62 6f 6f 6c 20 69 73 4e 75 6d 62 65  ....bool isNumbe
14f0: 72 20 3d 20 66 69 6e 64 21 28 60 61 3c 27 30 27  r = find!(`a<'0'
1500: 20 7c 7c 20 27 39 27 3c 61 60 29 28 73 74 72 29   || '9'<a`)(str)
1510: 2e 65 6d 70 74 79 3b 0a 09 09 09 72 65 74 75 72  .empty;....retur
1520: 6e 20 6e 65 77 20 54 6f 6b 65 6e 28 70 6f 73 2c  n new Token(pos,
1530: 20 73 74 72 2c 20 69 73 4e 75 6d 62 65 72 20 3f   str, isNumber ?
1540: 20 54 6f 6b 65 6e 2e 4b 69 6e 64 2e 6e 75 6d 62   Token.Kind.numb
1550: 65 72 20 3a 20 54 6f 6b 65 6e 2e 4b 69 6e 64 2e  er : Token.Kind.
1560: 69 64 65 6e 74 69 66 69 65 72 29 3b 0a 09 09 7d  identifier);...}
1570: 0a 09 7d 0a 0a 09 62 6f 6f 6c 20 69 73 53 79 6d  ..}...bool isSym
1580: 62 6f 6c 28 63 68 61 72 20 63 29 0a 09 7b 0a 09  bol(char c)..{..
1590: 09 72 65 74 75 72 6e 20 28 30 78 32 31 3c 3d 63  .return (0x21<=c
15a0: 20 26 26 20 63 3c 3d 30 78 37 66 20 26 26 20 21   && c<=0x7f && !
15b0: 73 74 64 2e 63 74 79 70 65 2e 69 73 61 6c 6e 75  std.ctype.isalnu
15c0: 6d 28 63 29 20 26 26 20 63 21 3d 27 5f 27 29 3b  m(c) && c!='_');
15d0: 0a 09 7d 0a 0a 09 69 6d 6d 75 74 61 62 6c 65 28  ..}...immutable(
15e0: 4c 65 78 50 6f 73 69 74 69 6f 6e 29 20 63 75 72  LexPosition) cur
15f0: 72 65 6e 74 50 6f 73 69 74 69 6f 6e 28 29 0a 09  rentPosition()..
1600: 7b 0a 09 09 72 65 74 75 72 6e 20 6e 65 77 20 69  {...return new i
1610: 6d 6d 75 74 61 62 6c 65 28 4c 65 78 50 6f 73 69  mmutable(LexPosi
1620: 74 69 6f 6e 29 28 66 69 6c 65 6e 61 6d 65 2c 20  tion)(filename, 
1630: 6c 69 6e 65 6e 6f 2c 20 63 6f 6c 75 6d 6e 29 3b  lineno, column);
1640: 0a 09 7d 0a 7d 0a 0a 75 6e 69 74 74 65 73 74 0a  ..}.}..unittest.
1650: 7b 0a 09 61 73 73 65 72 74 28 20 73 74 64 2e 72  {..assert( std.r
1660: 61 6e 67 65 2e 69 73 46 6f 72 77 61 72 64 52 61  ange.isForwardRa
1670: 6e 67 65 21 28 4c 65 78 65 72 29 20 29 3b 0a 7d  nge!(Lexer) );.}
1680: 0d 0a 0d 0a 75 6e 69 74 74 65 73 74 0d 0a 7b 0a  ....unittest..{.
1690: 09 61 75 74 6f 20 6c 65 78 20 3d 20 6c 65 78 65  .auto lex = lexe
16a0: 72 46 72 6f 6d 53 74 72 69 6e 67 28 22 74 68 69  rFromString("thi
16b0: 73 09 69 73 20 61 20 5c 74 5c 6e 20 70 65 6e 20  s.is a \t\n pen 
16c0: 3a 2d 28 20 20 20 22 29 3b 0a 09 54 6f 6b 65 6e  :-(   ");..Token
16d0: 5b 5d 20 74 73 20 3d 20 73 74 64 2e 61 72 72 61  [] ts = std.arra
16e0: 79 2e 61 72 72 61 79 28 6c 65 78 29 3b 0a 0a 09  y.array(lex);...
16f0: 61 73 73 65 72 74 28 20 74 73 5b 30 5d 2e 70 6f  assert( ts[0].po
1700: 73 2e 6c 69 6e 65 6e 6f 20 3d 3d 20 31 20 29 3b  s.lineno == 1 );
1710: 0a 09 61 73 73 65 72 74 28 20 74 73 5b 30 5d 2e  ..assert( ts[0].
1720: 70 6f 73 2e 63 6f 6c 75 6d 6e 20 3d 3d 20 31 20  pos.column == 1 
1730: 29 3b 0a 09 61 73 73 65 72 74 28 20 74 73 5b 30  );..assert( ts[0
1740: 5d 2e 6b 69 6e 64 20 3d 3d 20 54 6f 6b 65 6e 2e  ].kind == Token.
1750: 4b 69 6e 64 2e 69 64 65 6e 74 69 66 69 65 72 20  Kind.identifier 
1760: 29 3b 0d 0a 09 61 73 73 65 72 74 28 20 74 73 5b  );...assert( ts[
1770: 30 5d 2e 73 74 72 20 3d 3d 20 22 74 68 69 73 22  0].str == "this"
1780: 20 29 3b 0a 0d 0a 09 61 73 73 65 72 74 28 20 74   );....assert( t
1790: 73 5b 31 5d 2e 70 6f 73 2e 6c 69 6e 65 6e 6f 20  s[1].pos.lineno 
17a0: 3d 3d 20 31 20 29 3b 0a 09 61 73 73 65 72 74 28  == 1 );..assert(
17b0: 20 74 73 5b 31 5d 2e 70 6f 73 2e 63 6f 6c 75 6d   ts[1].pos.colum
17c0: 6e 20 3d 3d 20 36 20 29 3b 0a 09 61 73 73 65 72  n == 6 );..asser
17d0: 74 28 20 74 73 5b 31 5d 2e 6b 69 6e 64 20 3d 3d  t( ts[1].kind ==
17e0: 20 54 6f 6b 65 6e 2e 4b 69 6e 64 2e 69 64 65 6e   Token.Kind.iden
17f0: 74 69 66 69 65 72 20 29 3b 0d 0a 09 61 73 73 65  tifier );...asse
1800: 72 74 28 20 74 73 5b 31 5d 2e 73 74 72 20 3d 3d  rt( ts[1].str ==
1810: 20 22 69 73 22 20 29 3b 0a 0d 0a 09 61 73 73 65   "is" );....asse
1820: 72 74 28 20 74 73 5b 32 5d 2e 70 6f 73 2e 6c 69  rt( ts[2].pos.li
1830: 6e 65 6e 6f 20 3d 3d 20 31 20 29 3b 0a 09 61 73  neno == 1 );..as
1840: 73 65 72 74 28 20 74 73 5b 32 5d 2e 70 6f 73 2e  sert( ts[2].pos.
1850: 63 6f 6c 75 6d 6e 20 3d 3d 20 39 20 29 3b 0a 09  column == 9 );..
1860: 61 73 73 65 72 74 28 20 74 73 5b 32 5d 2e 6b 69  assert( ts[2].ki
1870: 6e 64 20 3d 3d 20 54 6f 6b 65 6e 2e 4b 69 6e 64  nd == Token.Kind
1880: 2e 69 64 65 6e 74 69 66 69 65 72 20 29 3b 0d 0a  .identifier );..
1890: 09 61 73 73 65 72 74 28 20 74 73 5b 32 5d 2e 73  .assert( ts[2].s
18a0: 74 72 20 3d 3d 20 22 61 22 20 29 3b 0a 0d 0a 09  tr == "a" );....
18b0: 61 73 73 65 72 74 28 20 74 73 5b 33 5d 2e 70 6f  assert( ts[3].po
18c0: 73 2e 6c 69 6e 65 6e 6f 20 3d 3d 20 32 20 29 3b  s.lineno == 2 );
18d0: 0a 09 61 73 73 65 72 74 28 20 74 73 5b 33 5d 2e  ..assert( ts[3].
18e0: 70 6f 73 2e 63 6f 6c 75 6d 6e 20 3d 3d 20 32 20  pos.column == 2 
18f0: 29 3b 0a 09 61 73 73 65 72 74 28 20 74 73 5b 33  );..assert( ts[3
1900: 5d 2e 6b 69 6e 64 20 3d 3d 20 54 6f 6b 65 6e 2e  ].kind == Token.
1910: 4b 69 6e 64 2e 69 64 65 6e 74 69 66 69 65 72 20  Kind.identifier 
1920: 29 3b 0d 0a 09 61 73 73 65 72 74 28 20 74 73 5b  );...assert( ts[
1930: 33 5d 2e 73 74 72 20 3d 3d 20 22 70 65 6e 22 20  3].str == "pen" 
1940: 29 3b 0a 0d 0a 09 2f 2f 20 63 6f 6e 73 65 63 75  );....// consecu
1950: 74 69 76 65 20 73 79 6d 62 6f 6c 73 20 61 72 65  tive symbols are
1960: 20 61 6c 77 61 79 73 20 73 65 70 61 72 61 74 65   always separate
1970: 64 0d 0a 09 2f 2f 20 68 65 6e 63 65 2c 20 6e 6f  d...// hence, no
1980: 20 22 2b 2b 22 20 6f 72 20 22 3c 3c 22 20 6f 72   "++" or "<<" or
1990: 20 2e 2e 2e 0d 0a 09 09 0d 0a 09 61 73 73 65 72   ..........asser
19a0: 74 28 20 74 73 5b 34 5d 2e 70 6f 73 2e 6c 69 6e  t( ts[4].pos.lin
19b0: 65 6e 6f 20 3d 3d 20 32 20 29 3b 0a 09 61 73 73  eno == 2 );..ass
19c0: 65 72 74 28 20 74 73 5b 34 5d 2e 70 6f 73 2e 63  ert( ts[4].pos.c
19d0: 6f 6c 75 6d 6e 20 3d 3d 20 36 20 29 3b 0a 09 61  olumn == 6 );..a
19e0: 73 73 65 72 74 28 20 74 73 5b 34 5d 2e 73 74 72  ssert( ts[4].str
19f0: 20 3d 3d 20 22 3a 22 20 29 3b 0a 0d 0a 09 61 73   == ":" );....as
1a00: 73 65 72 74 28 20 74 73 5b 35 5d 2e 70 6f 73 2e  sert( ts[5].pos.
1a10: 6c 69 6e 65 6e 6f 20 3d 3d 20 32 20 29 3b 0a 09  lineno == 2 );..
1a20: 61 73 73 65 72 74 28 20 74 73 5b 35 5d 2e 70 6f  assert( ts[5].po
1a30: 73 2e 63 6f 6c 75 6d 6e 20 3d 3d 20 37 20 29 3b  s.column == 7 );
1a40: 0a 09 61 73 73 65 72 74 28 20 74 73 5b 35 5d 2e  ..assert( ts[5].
1a50: 73 74 72 20 3d 3d 20 22 2d 22 20 29 3b 20 0a 0d  str == "-" ); ..
1a60: 0a 09 61 73 73 65 72 74 28 20 74 73 5b 36 5d 2e  ..assert( ts[6].
1a70: 70 6f 73 2e 6c 69 6e 65 6e 6f 20 3d 3d 20 32 20  pos.lineno == 2 
1a80: 29 3b 0a 09 61 73 73 65 72 74 28 20 74 73 5b 36  );..assert( ts[6
1a90: 5d 2e 70 6f 73 2e 63 6f 6c 75 6d 6e 20 3d 3d 20  ].pos.column == 
1aa0: 38 20 29 3b 0a 09 61 73 73 65 72 74 28 20 74 73  8 );..assert( ts
1ab0: 5b 36 5d 2e 73 74 72 20 3d 3d 20 22 28 22 20 29  [6].str == "(" )
1ac0: 3b 0a 0d 0a 09 61 73 73 65 72 74 28 20 74 73 2e  ;....assert( ts.
1ad0: 6c 65 6e 67 74 68 20 3d 3d 20 37 20 29 3b 0a 7d  length == 7 );.}
1ae0: 0d 0a 0d 0a 75 6e 69 74 74 65 73 74 0d 0a 7b 0a  ....unittest..{.
1af0: 09 61 75 74 6f 20 6c 65 78 32 20 3d 20 6c 65 78  .auto lex2 = lex
1b00: 65 72 46 72 6f 6d 53 74 72 69 6e 67 28 22 20 61  erFromString(" a
1b10: 31 32 5c 6e 33 61 20 35 20 22 29 3b 0a 09 61 73  12\n3a 5 ");..as
1b20: 73 65 72 74 28 20 6c 65 78 32 2e 66 72 6f 6e 74  sert( lex2.front
1b30: 2e 73 74 72 20 3d 3d 20 22 61 31 32 22 20 29 3b  .str == "a12" );
1b40: 0d 0a 09 61 73 73 65 72 74 28 20 6c 65 78 32 2e  ...assert( lex2.
1b50: 66 72 6f 6e 74 2e 6b 69 6e 64 20 3d 3d 20 54 6f  front.kind == To
1b60: 6b 65 6e 2e 4b 69 6e 64 2e 69 64 65 6e 74 69 66  ken.Kind.identif
1b70: 69 65 72 20 29 3b 0d 0a 09 6c 65 78 32 2e 70 6f  ier );...lex2.po
1b80: 70 46 72 6f 6e 74 3b 0a 09 61 75 74 6f 20 6c 65  pFront;..auto le
1b90: 78 33 20 3d 20 6c 65 78 32 2e 73 61 76 65 3b 0a  x3 = lex2.save;.
1ba0: 09 61 73 73 65 72 74 28 20 6c 65 78 32 2e 66 72  .assert( lex2.fr
1bb0: 6f 6e 74 2e 73 74 72 20 3d 3d 20 22 33 61 22 20  ont.str == "3a" 
1bc0: 29 3b 0d 0a 09 61 73 73 65 72 74 28 20 6c 65 78  );...assert( lex
1bd0: 32 2e 66 72 6f 6e 74 2e 6b 69 6e 64 20 3d 3d 20  2.front.kind == 
1be0: 54 6f 6b 65 6e 2e 4b 69 6e 64 2e 69 64 65 6e 74  Token.Kind.ident
1bf0: 69 66 69 65 72 20 29 3b 0d 0a 09 6c 65 78 32 2e  ifier );...lex2.
1c00: 70 6f 70 46 72 6f 6e 74 3b 0a 09 61 73 73 65 72  popFront;..asser
1c10: 74 28 20 6c 65 78 33 2e 66 72 6f 6e 74 2e 73 74  t( lex3.front.st
1c20: 72 20 3d 3d 20 22 33 61 22 20 29 3b 0a 09 61 73  r == "3a" );..as
1c30: 73 65 72 74 28 20 6c 65 78 33 2e 66 72 6f 6e 74  sert( lex3.front
1c40: 2e 6b 69 6e 64 20 3d 3d 20 54 6f 6b 65 6e 2e 4b  .kind == Token.K
1c50: 69 6e 64 2e 69 64 65 6e 74 69 66 69 65 72 20 29  ind.identifier )
1c60: 3b 0d 0a 09 61 73 73 65 72 74 28 20 6c 65 78 32  ;...assert( lex2
1c70: 2e 66 72 6f 6e 74 2e 73 74 72 20 3d 3d 20 22 35  .front.str == "5
1c80: 22 20 29 3b 0a 09 61 73 73 65 72 74 28 20 6c 65  " );..assert( le
1c90: 78 32 2e 66 72 6f 6e 74 2e 6b 69 6e 64 20 3d 3d  x2.front.kind ==
1ca0: 20 54 6f 6b 65 6e 2e 4b 69 6e 64 2e 6e 75 6d 62   Token.Kind.numb
1cb0: 65 72 20 29 3b 0d 0a 09 6c 65 78 32 2e 70 6f 70  er );...lex2.pop
1cc0: 46 72 6f 6e 74 3b 0a 09 6c 65 78 33 2e 70 6f 70  Front;..lex3.pop
1cd0: 46 72 6f 6e 74 3b 0a 09 61 73 73 65 72 74 28 20  Front;..assert( 
1ce0: 6c 65 78 32 2e 65 6d 70 74 79 20 29 3b 0a 09 61  lex2.empty );..a
1cf0: 73 73 65 72 74 28 20 21 6c 65 78 33 2e 65 6d 70  ssert( !lex3.emp
1d00: 74 79 20 29 3b 0a 09 61 73 73 65 72 74 28 20 6c  ty );..assert( l
1d10: 65 78 33 2e 66 72 6f 6e 74 2e 73 74 72 20 3d 3d  ex3.front.str ==
1d20: 20 22 35 22 20 29 3b 0d 0a 09 61 73 73 65 72 74   "5" );...assert
1d30: 28 20 6c 65 78 33 2e 66 72 6f 6e 74 2e 6b 69 6e  ( lex3.front.kin
1d40: 64 20 3d 3d 20 54 6f 6b 65 6e 2e 4b 69 6e 64 2e  d == Token.Kind.
1d50: 6e 75 6d 62 65 72 20 29 3b 0d 0a 7d 0d 0a 0d 0a  number );..}....
1d60: 75 6e 69 74 74 65 73 74 0d 0a 7b 0d 0a 2f 2f 21  unittest..{..//!
1d70: 21 20 62 65 20 73 75 72 65 20 74 6f 20 72 75 6e  ! be sure to run
1d80: 20 74 68 65 20 75 6e 69 74 74 65 73 74 20 6f 6e   the unittest on
1d90: 20 74 68 65 20 72 6f 6f 74 20 6f 66 20 74 68 65   the root of the
1da0: 20 73 6f 75 72 63 65 20 64 69 72 65 63 74 6f 72   source director
1db0: 79 0d 0a 09 61 75 74 6f 20 6c 65 78 66 20 3d 20  y...auto lexf = 
1dc0: 6c 65 78 65 72 46 72 6f 6d 46 69 6c 65 28 22 70  lexerFromFile("p
1dd0: 6f 6c 65 6d 79 2f 6c 65 78 2e 64 22 29 3b 09 0d  olemy/lex.d");..
1de0: 0a 09 61 73 73 65 72 74 28 20 6c 65 78 66 2e 66  ..assert( lexf.f
1df0: 72 6f 6e 74 2e 73 74 72 20 3d 3d 20 22 6d 6f 64  ront.str == "mod
1e00: 75 6c 65 22 2c 20 6c 65 78 66 2e 66 72 6f 6e 74  ule", lexf.front
1e10: 2e 73 74 72 20 29 3b 0d 0a 09 61 73 73 65 72 74  .str );...assert
1e20: 28 20 6c 65 78 66 2e 66 72 6f 6e 74 2e 70 6f 73  ( lexf.front.pos
1e30: 2e 66 69 6c 65 6e 61 6d 65 20 3d 3d 20 22 70 6f  .filename == "po
1e40: 6c 65 6d 79 2f 6c 65 78 2e 64 22 20 29 3b 0d 0a  lemy/lex.d" );..
1e50: 09 61 73 73 65 72 74 28 20 6c 65 78 66 2e 66 72  .assert( lexf.fr
1e60: 6f 6e 74 2e 70 6f 73 2e 6c 69 6e 65 6e 6f 20 3d  ont.pos.lineno =
1e70: 3d 20 31 20 29 3b 0d 0a 09 61 73 73 65 72 74 28  = 1 );...assert(
1e80: 20 6c 65 78 66 2e 66 72 6f 6e 74 2e 70 6f 73 2e   lexf.front.pos.
1e90: 63 6f 6c 75 6d 6e 20 3d 3d 20 31 20 29 3b 0d 0a  column == 1 );..
1ea0: 09 6c 65 78 66 2e 70 6f 70 46 72 6f 6e 74 3b 0d  .lexf.popFront;.
1eb0: 0a 09 61 73 73 65 72 74 28 20 6c 65 78 66 2e 66  ..assert( lexf.f
1ec0: 72 6f 6e 74 2e 73 74 72 20 3d 3d 20 22 70 6f 6c  ront.str == "pol
1ed0: 65 6d 79 22 20 29 3b 0d 0a 09 61 73 73 65 72 74  emy" );...assert
1ee0: 28 20 6c 65 78 66 2e 66 72 6f 6e 74 2e 70 6f 73  ( lexf.front.pos
1ef0: 2e 6c 69 6e 65 6e 6f 20 3d 3d 20 31 20 29 3b 0d  .lineno == 1 );.
1f00: 0a 09 61 73 73 65 72 74 28 20 6c 65 78 66 2e 66  ..assert( lexf.f
1f10: 72 6f 6e 74 2e 70 6f 73 2e 63 6f 6c 75 6d 6e 20  ront.pos.column 
1f20: 3d 3d 20 38 20 29 3b 0d 0a 09 6c 65 78 66 2e 70  == 8 );...lexf.p
1f30: 6f 70 46 72 6f 6e 74 3b 0d 0a 09 61 73 73 65 72  opFront;...asser
1f40: 74 28 20 6c 65 78 66 2e 66 72 6f 6e 74 2e 73 74  t( lexf.front.st
1f50: 72 20 3d 3d 20 22 2e 22 20 29 3b 0d 0a 09 6c 65  r == "." );...le
1f60: 78 66 2e 70 6f 70 46 72 6f 6e 74 3b 0d 0a 09 61  xf.popFront;...a
1f70: 73 73 65 72 74 28 20 6c 65 78 66 2e 66 72 6f 6e  ssert( lexf.fron
1f80: 74 2e 73 74 72 20 3d 3d 20 22 6c 65 78 22 20 29  t.str == "lex" )
1f90: 3b 0d 0a 09 6c 65 78 66 2e 70 6f 70 46 72 6f 6e  ;...lexf.popFron
1fa0: 74 3b 0d 0a 09 61 73 73 65 72 74 28 20 6c 65 78  t;...assert( lex
1fb0: 66 2e 66 72 6f 6e 74 2e 73 74 72 20 3d 3d 20 22  f.front.str == "
1fc0: 3b 22 20 29 3b 0d 0a 09 6c 65 78 66 2e 70 6f 70  ;" );...lexf.pop
1fd0: 46 72 6f 6e 74 3b 0d 0a 09 61 73 73 65 72 74 28  Front;...assert(
1fe0: 20 6c 65 78 66 2e 66 72 6f 6e 74 2e 73 74 72 20   lexf.front.str 
1ff0: 3d 3d 20 22 69 6d 70 6f 72 74 22 20 29 3b 0d 0a  == "import" );..
2000: 09 61 73 73 65 72 74 28 20 6c 65 78 66 2e 66 72  .assert( lexf.fr
2010: 6f 6e 74 2e 70 6f 73 2e 6c 69 6e 65 6e 6f 20 3d  ont.pos.lineno =
2020: 3d 20 32 20 29 3b 0d 0a 09 61 73 73 65 72 74 28  = 2 );...assert(
2030: 20 6c 65 78 66 2e 66 72 6f 6e 74 2e 70 6f 73 2e   lexf.front.pos.
2040: 63 6f 6c 75 6d 6e 20 3d 3d 20 31 20 29 3b 0d 0a  column == 1 );..
2050: 7d 0d 0a 0d 0a 75 6e 69 74 74 65 73 74 0d 0a 7b  }....unittest..{
2060: 0d 0a 09 61 75 74 6f 20 6c 65 78 20 3d 20 6c 65  ...auto lex = le
2070: 78 65 72 46 72 6f 6d 53 74 72 69 6e 67 28 60 6d  xerFromString(`m
2080: 79 20 23 20 63 6f 6d 6d 65 6e 74 20 73 68 6f 75  y # comment shou
2090: 6c 64 0d 0a 23 20 68 65 79 21 21 0d 0a 62 65 20  ld..# hey!!..be 
20a0: 69 67 6e 6f 72 65 64 2e 0d 0a 68 61 68 61 68 61  ignored...hahaha
20b0: 22 68 69 68 69 68 69 22 22 68 75 5c 5c 5c 22 68  "hihihi""hu\\\"h
20c0: 75 68 75 22 23 31 32 33 20 61 61 0d 0a 31 32 33  uhu"#123 aa..123
20d0: 20 61 61 20 22 61 61 61 0d 0a 62 62 62 20 23 20   aa "aaa..bbb # 
20e0: 31 32 33 0d 0a 65 65 65 22 0d 0a 7a 7a 7a 0d 0a  123..eee"..zzz..
20f0: 60 29 3b 0d 0a 09 54 6f 6b 65 6e 5b 5d 20 74 73  `);...Token[] ts
2100: 20 3d 20 73 74 64 2e 61 72 72 61 79 2e 61 72 72   = std.array.arr
2110: 61 79 28 6c 65 78 29 3b 0d 0a 09 61 73 73 65 72  ay(lex);...asser
2120: 74 28 20 74 73 5b 30 5d 2e 73 74 72 20 3d 3d 20  t( ts[0].str == 
2130: 22 6d 79 22 20 29 3b 0d 0a 09 61 73 73 65 72 74  "my" );...assert
2140: 28 20 74 73 5b 30 5d 2e 70 6f 73 2e 6c 69 6e 65  ( ts[0].pos.line
2150: 6e 6f 20 3d 3d 20 31 20 29 3b 0d 0a 09 61 73 73  no == 1 );...ass
2160: 65 72 74 28 20 74 73 5b 31 5d 2e 73 74 72 20 3d  ert( ts[1].str =
2170: 3d 20 22 62 65 22 20 29 3b 0d 0a 09 61 73 73 65  = "be" );...asse
2180: 72 74 28 20 74 73 5b 31 5d 2e 70 6f 73 2e 6c 69  rt( ts[1].pos.li
2190: 6e 65 6e 6f 20 3d 3d 20 33 20 29 3b 0d 0a 09 61  neno == 3 );...a
21a0: 73 73 65 72 74 28 20 74 73 5b 32 5d 2e 73 74 72  ssert( ts[2].str
21b0: 20 3d 3d 20 22 69 67 6e 6f 72 65 64 22 20 29 3b   == "ignored" );
21c0: 0d 0a 09 61 73 73 65 72 74 28 20 74 73 5b 33 5d  ...assert( ts[3]
21d0: 2e 73 74 72 20 3d 3d 20 22 2e 22 20 29 3b 0d 0a  .str == "." );..
21e0: 09 61 73 73 65 72 74 28 20 74 73 5b 34 5d 2e 73  .assert( ts[4].s
21f0: 74 72 20 3d 3d 20 22 68 61 68 61 68 61 22 20 29  tr == "hahaha" )
2200: 3b 0d 0a 09 61 73 73 65 72 74 28 20 74 73 5b 34  ;...assert( ts[4
2210: 5d 2e 70 6f 73 2e 6c 69 6e 65 6e 6f 20 3d 3d 20  ].pos.lineno == 
2220: 34 20 29 3b 0d 0a 09 61 73 73 65 72 74 28 20 74  4 );...assert( t
2230: 73 5b 34 5d 2e 6b 69 6e 64 20 3d 3d 20 54 6f 6b  s[4].kind == Tok
2240: 65 6e 2e 4b 69 6e 64 2e 69 64 65 6e 74 69 66 69  en.Kind.identifi
2250: 65 72 20 29 3b 0d 0a 09 61 73 73 65 72 74 28 20  er );...assert( 
2260: 74 73 5b 35 5d 2e 73 74 72 20 3d 3d 20 22 68 69  ts[5].str == "hi
2270: 68 69 68 69 22 20 29 3b 0d 0a 09 61 73 73 65 72  hihi" );...asser
2280: 74 28 20 74 73 5b 35 5d 2e 70 6f 73 2e 6c 69 6e  t( ts[5].pos.lin
2290: 65 6e 6f 20 3d 3d 20 34 20 29 3b 0d 0a 09 61 73  eno == 4 );...as
22a0: 73 65 72 74 28 20 74 73 5b 35 5d 2e 6b 69 6e 64  sert( ts[5].kind
22b0: 20 3d 3d 20 54 6f 6b 65 6e 2e 4b 69 6e 64 2e 73   == Token.Kind.s
22c0: 74 72 69 6e 67 4c 69 74 65 72 61 6c 20 29 3b 0d  tringLiteral );.
22d0: 0a 09 61 73 73 65 72 74 28 20 74 73 5b 36 5d 2e  ..assert( ts[6].
22e0: 73 74 72 20 3d 3d 20 60 68 75 5c 22 68 75 68 75  str == `hu\"huhu
22f0: 60 20 29 3b 0d 0a 09 61 73 73 65 72 74 28 20 74  ` );...assert( t
2300: 73 5b 36 5d 2e 6b 69 6e 64 20 3d 3d 20 54 6f 6b  s[6].kind == Tok
2310: 65 6e 2e 4b 69 6e 64 2e 73 74 72 69 6e 67 4c 69  en.Kind.stringLi
2320: 74 65 72 61 6c 20 29 3b 0d 0a 09 61 73 73 65 72  teral );...asser
2330: 74 28 20 74 73 5b 36 5d 2e 70 6f 73 2e 6c 69 6e  t( ts[6].pos.lin
2340: 65 6e 6f 20 3d 3d 20 34 20 29 3b 0d 0a 09 61 73  eno == 4 );...as
2350: 73 65 72 74 28 20 74 73 5b 37 5d 2e 73 74 72 20  sert( ts[7].str 
2360: 3d 3d 20 22 31 32 33 22 20 29 3b 0d 0a 09 61 73  == "123" );...as
2370: 73 65 72 74 28 20 74 73 5b 37 5d 2e 70 6f 73 2e  sert( ts[7].pos.
2380: 6c 69 6e 65 6e 6f 20 3d 3d 20 35 20 29 3b 0d 0a  lineno == 5 );..
2390: 09 61 73 73 65 72 74 28 20 74 73 5b 37 5d 2e 6b  .assert( ts[7].k
23a0: 69 6e 64 20 3d 3d 20 54 6f 6b 65 6e 2e 4b 69 6e  ind == Token.Kin
23b0: 64 2e 6e 75 6d 62 65 72 20 29 3b 0d 0a 09 61 73  d.number );...as
23c0: 73 65 72 74 28 20 74 73 5b 38 5d 2e 73 74 72 20  sert( ts[8].str 
23d0: 3d 3d 20 22 61 61 22 20 29 3b 0d 0a 09 61 73 73  == "aa" );...ass
23e0: 65 72 74 28 20 74 73 5b 39 5d 2e 70 6f 73 2e 6c  ert( ts[9].pos.l
23f0: 69 6e 65 6e 6f 20 3d 3d 20 35 20 29 3b 0d 0a 09  ineno == 5 );...
2400: 61 73 73 65 72 74 28 20 74 73 5b 39 5d 2e 73 74  assert( ts[9].st
2410: 72 20 3d 3d 20 22 61 61 61 5c 6e 62 62 62 20 23  r == "aaa\nbbb #
2420: 20 31 32 33 5c 6e 65 65 65 22 20 29 3b 0d 0a 09   123\neee" );...
2430: 61 73 73 65 72 74 28 20 74 73 5b 39 5d 2e 6b 69  assert( ts[9].ki
2440: 6e 64 20 3d 3d 20 54 6f 6b 65 6e 2e 4b 69 6e 64  nd == Token.Kind
2450: 2e 73 74 72 69 6e 67 4c 69 74 65 72 61 6c 20 29  .stringLiteral )
2460: 3b 0d 0a 09 61 73 73 65 72 74 28 20 74 73 5b 31  ;...assert( ts[1
2470: 30 5d 2e 70 6f 73 2e 6c 69 6e 65 6e 6f 20 3d 3d  0].pos.lineno ==
2480: 20 38 20 29 3b 0d 0a 09 61 73 73 65 72 74 28 20   8 );...assert( 
2490: 74 73 2e 6c 65 6e 67 74 68 20 3d 3d 20 31 31 20  ts.length == 11 
24a0: 29 3b 0d 0a 7d 0d 0a                             );..}..