1 module ddparser.scan;
2 
3 
4 import ddparser.dparse;
5 import ddparser.parse;
6 import ddparser.dparse_tables;
7 import ddparser.util;
8 import std.stdio;
9 
10 struct ShiftResult
11 {
12     SNode* snode;
13     const(D_Shift)* shift;
14     d_loc_t	loc;
15 }
16 
17 private void do_smth(State)(ref d_loc_t loc, ref d_loc_t last_loc,
18                 ref int nresults, 
19                 ref D_Shift*[] shift, const ref D_State parse_state, ShiftResult[] results)
20 {
21     /* all matches */
22     auto st = cast(SB_!(State)[])parse_state.scanner_table;
23     auto tst = cast(SB_trans!(State)[])parse_state.transition_table;
24     State state, last, prev;
25 
26     const(char) *s = loc.s;
27     int col = loc.col, line = loc.line;
28 
29     while (true)
30     {
31         uint8 c = cast(uint8)*s++;
32         uint32 sb = c >> SCANNER_BLOCK_SHIFT;
33         uint32 so = c & SCANNER_BLOCK_MASK;
34         state = st[state].scanner_block[sb][so];
35         if (!state) break;
36 
37         --state;
38 
39         if (prev && parse_state.accepts_diff) {
40             const D_Shift*[] shift_diff = parse_state.accepts_diff[tst[prev].scanner_block[sb][so]];
41             foreach(sd; shift_diff) {
42                 results[nresults].loc = loc;
43                 results[nresults++].shift = sd;
44             }
45         }
46         prev = state;
47         if (c == '\n') { line++; col = 0; } else col++;
48         loc.s = s; loc.line = line; loc.col = col;
49         if (st[state].shift) {
50             last = state;
51             last_loc = loc;
52         }
53     }
54     shift = st[last].shift;
55 }
56 
57 int
58 scan_buffer(d_loc_t loc, const ref D_State parse_state, ShiftResult[] results) {
59     d_loc_t last_loc = loc;
60     int nresults = 0;
61     D_Shift *[]shift;
62 
63     switch (parse_state.scanner_size) {
64         case 1:
65             do_smth!ubyte(loc, last_loc, nresults, shift, parse_state, results);
66             break;
67         case 2:
68             do_smth!ushort(loc, last_loc, nresults, shift, parse_state, results);
69             break;
70         case 4:
71             do_smth!uint(loc, last_loc, nresults, shift, parse_state, results);
72             break;
73         default:
74     }
75 
76     foreach(s; shift) {
77         results[nresults].loc = last_loc;
78         results[nresults++].shift = s;
79     }
80 
81     if (nresults) {
82         bool longest = parse_state.scan_kind == D_SCAN_LONGEST;
83         const char *end = results[nresults-1].loc.s;
84 
85         int i = 0;
86         if (parse_state.scan_kind == D_SCAN_MIXED) {
87             for (i = nresults - 1; i >= 0; i--) {
88                 if (results[i].loc.s < end)
89                     break;
90                 if (results[i].shift.shift_kind == D_SCAN_LONGEST)
91                     longest = true;
92             }
93         }
94 
95         if (longest) {
96             /* keep only 'longest' */
97             i = 0;
98             for (int j = 0; j < nresults; j++) {
99                 if (results[j].loc.s == end || results[j].shift.shift_kind == D_SCAN_TRAILING) {
100                     if (i != j)
101                         results[i] = results[j];
102                     i++;
103                 }
104             }
105             nresults = i;
106         } else if (parse_state.scan_kind == D_SCAN_MIXED) {
107             /* only keep non-longest */
108             for (int j = i; j >= 0; j--)
109                 if (results[j].shift.shift_kind != D_SCAN_LONGEST) {
110                     if (i != j)
111                         results[i] = results[j];
112                     i--;
113                 }
114             nresults = nresults - i - 1;
115             if (i != -1)
116                 for (int j = 0; j < nresults; ++j)
117                     results[j] = results[i + j + 1];
118         }
119     }
120     return nresults;
121 }
122