1 module bf_parser; 2 3 enum BFTokenEnum 4 { 5 IncPtr = '>', 6 DecPtr = '<', 7 IncVal = '+', 8 DecVal = '-', 9 OutputVal = '.', 10 InputVal = ',', 11 LoopBegin = '[', 12 LoopEnd = ']', 13 14 ProgrammBegin, 15 ProgrammEnd, 16 } 17 18 /** 19 represent RepeatedToken as uint 20 [0 .. 24] count 21 [24 .. 32] token 22 */ 23 struct RepeatedToken 24 { 25 uint _token; 26 alias _token this; 27 28 @property BFTokenEnum token() const pure 29 { 30 return cast(BFTokenEnum)(_token >> 24); 31 } 32 33 @property uint count() const pure 34 { 35 return _token & 0x00_FF_FF_FF; 36 } 37 } 38 39 RepeatedToken Token(BFTokenEnum token) pure 40 { 41 return cast(RepeatedToken)(token << 24 | 1); 42 } 43 44 const(RepeatedToken[]) parseBf(const string input) pure 45 { 46 uint pos; 47 RepeatedToken[] result; 48 result.length = input.length + 2; 49 // the maximal number of diffrent tokens is equal to the chars in the input 50 // plus the begin and end token 51 52 result[0] = Token(BFTokenEnum.ProgrammBegin); 53 uint resultLen = 0; 54 55 while (pos < input.length) 56 { 57 uint lastToken = (result[resultLen] >> 24); 58 uint thisToken = BFTokenEnum.ProgrammEnd; 59 final switch (input[pos++]) with (BFTokenEnum) 60 { 61 case '>': 62 thisToken = IncPtr; 63 break; 64 case '<': 65 thisToken = DecPtr; 66 break; 67 case '+': 68 thisToken = IncVal; 69 break; 70 case '-': 71 thisToken = DecVal; 72 break; 73 case '.': 74 thisToken = OutputVal; 75 break; 76 case ',': 77 thisToken = InputVal; 78 break; 79 case '[': 80 thisToken = LoopBegin; 81 break; 82 case ']': 83 thisToken = LoopEnd; 84 break; 85 case '\r': 86 pos++; 87 goto case '\n'; 88 case '\n': 89 //TODO handle lines and proper position informmation; 90 break; 91 } 92 93 94 if (lastToken == thisToken) 95 { 96 result[resultLen]++; 97 } 98 else if (thisToken != BFTokenEnum.ProgrammEnd) 99 { 100 result[++resultLen] = Token(cast(BFTokenEnum)thisToken); 101 } 102 103 } 104 105 result[++resultLen] = Token(BFTokenEnum.ProgrammEnd); 106 return result[0 .. resultLen + 1]; 107 }