1 module zua.pattern.parser; 2 import zua.pattern; 3 import std.bitmanip; 4 5 /** A pattern parser */ 6 final class Parser { 7 private string pattern; 8 private size_t index; 9 10 /** Create a new Parser */ 11 this(string pattern) { 12 this.pattern = pattern; 13 } 14 15 private: 16 17 bool eof() { 18 return index >= pattern.length; 19 } 20 21 char nextChar() { 22 return pattern[index++]; 23 } 24 25 char peekChar() { 26 return pattern[index]; 27 } 28 29 CharClass nextCharClass(bool sqBracket = true) { 30 char c = nextChar(); 31 if (c == '%') { 32 if (eof) { 33 throw new PatternError("malformed pattern (ends with '%')"); 34 } 35 char nc = nextChar(); 36 BitArray set; 37 set.length = 256; 38 switch (nc) { 39 case 'a': 40 set['a' .. 'z' + 1] = true; 41 set['A' .. 'Z' + 1] = true; 42 break; 43 case 'c': 44 set[0 .. 0x1f + 1] = true; 45 set[0x7f] = true; 46 break; 47 case 'd': 48 set['0' .. '9' + 1] = true; 49 break; 50 default: 51 LiteralChar res = new LiteralChar; 52 res.value = nc; 53 return res; 54 } 55 SetClass res = new SetClass; 56 res.set = set; 57 return res; 58 } 59 else if (c == '.') { 60 BitArray set; 61 set.length = 256; 62 set[] = true; 63 SetClass res = new SetClass; 64 res.set = set; 65 return res; 66 } 67 else if (c == '[' && sqBracket) { 68 if (eof) { 69 throw new PatternError("malformed pattern (missing ']')"); 70 } 71 char fc = peekChar(); 72 bool complement = false; 73 if (fc == '^') { 74 nextChar(); 75 complement = true; 76 } 77 BitArray set; 78 size_t save = index; 79 CharClass first = nextCharClass(false); 80 if (save + 1 == index) { 81 82 } 83 if (complement) set.flip(); 84 SetClass res = new SetClass; 85 res.set = set; 86 return res; 87 } 88 else { 89 LiteralChar res = new LiteralChar; 90 res.value = c; 91 return res; 92 } 93 } 94 95 }