1 module hunt.markdown.internal.StaggeredDelimiterProcessor; 2 3 import hunt.markdown.node.Text; 4 import hunt.markdown.parser.delimiter.DelimiterProcessor; 5 import hunt.markdown.parser.delimiter.DelimiterRun; 6 7 import hunt.collection.LinkedList; 8 // import hunt.collection.ListIterator; 9 import hunt.Exceptions; 10 import std.conv; 11 /** 12 * An implementation of DelimiterProcessor that dispatches all calls to two or more other DelimiterProcessors 13 * depending on the length of the delimiter run. All child DelimiterProcessors must have different minimum 14 * lengths. A given delimiter run is dispatched to the child with the largest acceptable minimum length. If no 15 * child is applicable, the one with the largest minimum length is chosen. 16 */ 17 class StaggeredDelimiterProcessor : DelimiterProcessor { 18 19 private char delim; 20 private int minLength = 0; 21 private LinkedList!(DelimiterProcessor) processors; // in reverse getMinLength order 22 23 this(char delim) { 24 processors = new LinkedList!(DelimiterProcessor)(); 25 this.delim = delim; 26 } 27 28 29 override public char getOpeningCharacter() { 30 return delim; 31 } 32 33 override public char getClosingCharacter() { 34 return delim; 35 } 36 37 override public int getMinLength() { 38 return minLength; 39 } 40 41 void add(DelimiterProcessor dp) { 42 int len = dp.getMinLength(); 43 // ListIterator!(DelimiterProcessor) it = processors.listIterator(); 44 bool added = false; 45 // while (it.hasNext()) { 46 // DelimiterProcessor p = it.next(); 47 // int pLen = p.getMinLength(); 48 // if (len > pLen) { 49 // it.previous(); 50 // it.add(dp); 51 // added = true; 52 // break; 53 // } else if (len == pLen) { 54 // throw new IllegalArgumentException("Cannot add two delimiter processors for char '" ~ delim ~ "' and minimum length " ~ len); 55 // } 56 // } 57 int idx = 0; 58 foreach(p; processors) { 59 int pLen = p.getMinLength(); 60 if (len > pLen) { 61 // it.previous(); 62 // it.add(dp); 63 processors.add(idx,dp); 64 added = true; 65 break; 66 } else if (len == pLen) { 67 throw new IllegalArgumentException("Cannot add two delimiter processors for char '" ~ delim ~ "' and minimum length " ~ len.to!string); 68 } 69 idx++; 70 } 71 72 if (!added) { 73 processors.add(dp); 74 this.minLength = len; 75 } 76 } 77 78 private DelimiterProcessor findProcessor(int len) { 79 foreach (DelimiterProcessor p ; processors) { 80 if (p.getMinLength() <= len) { 81 return p; 82 } 83 } 84 return processors.getFirst(); 85 } 86 87 override public int getDelimiterUse(DelimiterRun opener, DelimiterRun closer) { 88 return findProcessor(opener.length).getDelimiterUse(opener, closer); 89 } 90 91 override public void process(Text opener, Text closer, int delimiterUse) { 92 findProcessor(delimiterUse).process(opener, closer, delimiterUse); 93 } 94 }