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