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 }