|
1 |
| |
|
2 |
| |
|
3 |
| |
|
4 |
| package net.sourceforge.pmd.dfa; |
|
5 |
| |
|
6 |
| import java.util.ArrayList; |
|
7 |
| import java.util.List; |
|
8 |
| |
|
9 |
| |
|
10 |
| |
|
11 |
| |
|
12 |
| |
|
13 |
| |
|
14 |
| |
|
15 |
| |
|
16 |
| |
|
17 |
| |
|
18 |
| |
|
19 |
| |
|
20 |
| |
|
21 |
| |
|
22 |
| |
|
23 |
| public class SequenceChecker { |
|
24 |
| |
|
25 |
| |
|
26 |
| |
|
27 |
| |
|
28 |
| private static class Status { |
|
29 |
| public static final int ROOT = -1; |
|
30 |
| |
|
31 |
| private List nextSteps = new ArrayList(); |
|
32 |
| private int type; |
|
33 |
| private boolean lastStep; |
|
34 |
| |
|
35 |
| |
|
36 |
48
| public Status(int type) {
|
|
37 |
48
| this(type, false);
|
|
38 |
| } |
|
39 |
| |
|
40 |
72
| public Status(int type, boolean lastStep) {
|
|
41 |
72
| this.type = type;
|
|
42 |
72
| this.lastStep = lastStep;
|
|
43 |
| } |
|
44 |
| |
|
45 |
136
| public void addStep(Status type) {
|
|
46 |
136
| nextSteps.add(type);
|
|
47 |
| } |
|
48 |
| |
|
49 |
300
| public Status step(int type) {
|
|
50 |
300
| for (int i = 0; i < this.nextSteps.size(); i++) {
|
|
51 |
500
| if (type == ((Status) nextSteps.get(i)).type) {
|
|
52 |
270
| return (Status) nextSteps.get(i);
|
|
53 |
| } |
|
54 |
| } |
|
55 |
30
| return null;
|
|
56 |
| } |
|
57 |
| |
|
58 |
482
| public boolean isLastStep() {
|
|
59 |
482
| return this.lastStep;
|
|
60 |
| } |
|
61 |
| |
|
62 |
58
| public boolean hasMoreSteps() {
|
|
63 |
58
| return this.nextSteps.size() > 1;
|
|
64 |
| } |
|
65 |
| } |
|
66 |
| |
|
67 |
| private static Status root; |
|
68 |
| |
|
69 |
| static { |
|
70 |
4
| root = new Status(Status.ROOT);
|
|
71 |
4
| Status ifNode = new Status(NodeType.IF_EXPR);
|
|
72 |
4
| Status ifSt = new Status(NodeType.IF_LAST_STATEMENT);
|
|
73 |
4
| Status ifStWithoutElse = new Status(NodeType.IF_LAST_STATEMENT_WITHOUT_ELSE, true);
|
|
74 |
4
| Status elseSt = new Status(NodeType.ELSE_LAST_STATEMENT, true);
|
|
75 |
4
| Status whileNode = new Status(NodeType.WHILE_EXPR);
|
|
76 |
4
| Status whileSt = new Status(NodeType.WHILE_LAST_STATEMENT, true);
|
|
77 |
4
| Status switchNode = new Status(NodeType.SWITCH_START);
|
|
78 |
4
| Status caseSt = new Status(NodeType.CASE_LAST_STATEMENT);
|
|
79 |
4
| Status switchDefault = new Status(NodeType.SWITCH_LAST_DEFAULT_STATEMENT);
|
|
80 |
4
| Status switchEnd = new Status(NodeType.SWITCH_END, true);
|
|
81 |
| |
|
82 |
4
| Status forInit = new Status(NodeType.FOR_INIT);
|
|
83 |
4
| Status forExpr = new Status(NodeType.FOR_EXPR);
|
|
84 |
4
| Status forUpdate = new Status(NodeType.FOR_UPDATE);
|
|
85 |
4
| Status forSt = new Status(NodeType.FOR_BEFORE_FIRST_STATEMENT);
|
|
86 |
4
| Status forEnd = new Status(NodeType.FOR_END, true);
|
|
87 |
| |
|
88 |
4
| Status doSt = new Status(NodeType.DO_BEFORE_FIRST_STATEMENT);
|
|
89 |
4
| Status doExpr = new Status(NodeType.DO_EXPR, true);
|
|
90 |
| |
|
91 |
4
| root.addStep(ifNode);
|
|
92 |
4
| root.addStep(whileNode);
|
|
93 |
4
| root.addStep(switchNode);
|
|
94 |
4
| root.addStep(forInit);
|
|
95 |
4
| root.addStep(forExpr);
|
|
96 |
4
| root.addStep(forUpdate);
|
|
97 |
4
| root.addStep(forSt);
|
|
98 |
4
| root.addStep(doSt);
|
|
99 |
| |
|
100 |
4
| ifNode.addStep(ifSt);
|
|
101 |
4
| ifNode.addStep(ifStWithoutElse);
|
|
102 |
4
| ifSt.addStep(elseSt);
|
|
103 |
4
| ifStWithoutElse.addStep(root);
|
|
104 |
4
| elseSt.addStep(root);
|
|
105 |
| |
|
106 |
4
| whileNode.addStep(whileSt);
|
|
107 |
4
| whileSt.addStep(root);
|
|
108 |
| |
|
109 |
4
| switchNode.addStep(caseSt);
|
|
110 |
4
| switchNode.addStep(switchDefault);
|
|
111 |
4
| switchNode.addStep(switchEnd);
|
|
112 |
4
| caseSt.addStep(caseSt);
|
|
113 |
4
| caseSt.addStep(switchDefault);
|
|
114 |
4
| caseSt.addStep(switchEnd);
|
|
115 |
4
| switchDefault.addStep(switchEnd);
|
|
116 |
4
| switchDefault.addStep(caseSt);
|
|
117 |
4
| switchEnd.addStep(root);
|
|
118 |
| |
|
119 |
4
| forInit.addStep(forExpr);
|
|
120 |
4
| forInit.addStep(forUpdate);
|
|
121 |
4
| forInit.addStep(forSt);
|
|
122 |
4
| forExpr.addStep(forUpdate);
|
|
123 |
4
| forExpr.addStep(forSt);
|
|
124 |
4
| forUpdate.addStep(forSt);
|
|
125 |
4
| forSt.addStep(forEnd);
|
|
126 |
4
| forEnd.addStep(root);
|
|
127 |
| |
|
128 |
4
| doSt.addStep(doExpr);
|
|
129 |
4
| doExpr.addStep(root);
|
|
130 |
| } |
|
131 |
| |
|
132 |
| private Status aktStatus; |
|
133 |
| private List bracesList; |
|
134 |
| |
|
135 |
| private int firstIndex = -1; |
|
136 |
| private int lastIndex = -1; |
|
137 |
| |
|
138 |
| |
|
139 |
| |
|
140 |
| |
|
141 |
40
| public SequenceChecker(List bracesList) {
|
|
142 |
40
| this.aktStatus = root;
|
|
143 |
40
| this.bracesList = bracesList;
|
|
144 |
| } |
|
145 |
| |
|
146 |
| |
|
147 |
| |
|
148 |
| |
|
149 |
| |
|
150 |
98
| public boolean run() {
|
|
151 |
98
| this.aktStatus = root;
|
|
152 |
98
| this.firstIndex = 0;
|
|
153 |
98
| this.lastIndex = 0;
|
|
154 |
98
| boolean lookAhead = false;
|
|
155 |
| |
|
156 |
98
| for (int i = 0; i < this.bracesList.size(); i++) {
|
|
157 |
300
| StackObject so = (StackObject) bracesList.get(i);
|
|
158 |
300
| aktStatus = this.aktStatus.step(so.getType());
|
|
159 |
| |
|
160 |
300
| if (aktStatus == null) {
|
|
161 |
30
| if (lookAhead) {
|
|
162 |
0
| this.lastIndex = i - 1;
|
|
163 |
0
| return false;
|
|
164 |
| } |
|
165 |
30
| this.aktStatus = root;
|
|
166 |
30
| this.firstIndex = i;
|
|
167 |
30
| i--;
|
|
168 |
30
| continue;
|
|
169 |
| } else { |
|
170 |
270
| if (aktStatus.isLastStep() && !aktStatus.hasMoreSteps()) {
|
|
171 |
58
| this.lastIndex = i;
|
|
172 |
58
| return false;
|
|
173 |
212
| } else if (aktStatus.isLastStep() && aktStatus.hasMoreSteps()) {
|
|
174 |
0
| lookAhead = true;
|
|
175 |
0
| this.lastIndex = i;
|
|
176 |
| } |
|
177 |
| } |
|
178 |
| } |
|
179 |
40
| return this.firstIndex == this.lastIndex;
|
|
180 |
| } |
|
181 |
| |
|
182 |
464
| public int getFirstIndex() {
|
|
183 |
464
| return this.firstIndex;
|
|
184 |
| } |
|
185 |
| |
|
186 |
198
| public int getLastIndex() {
|
|
187 |
198
| return this.lastIndex;
|
|
188 |
| } |
|
189 |
| |
|
190 |
| } |