1
2
3
4 package net.sourceforge.pmd.dfa;
5
6 import java.util.ArrayList;
7 import java.util.List;
8
9 /***
10 * @author raik
11 * <p/>
12 * Computes the first sequence in a list.
13 * <p/>
14 * e.g.
15 * IF_START 0
16 * WHILE_EXPR 1
17 * WHILE_END 2
18 * IF_END 3
19 * <p/>
20 * The first sequence is WHILE_EXPR und WHILE_END. It returns always the
21 * first inner nested scope.
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 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 == ((Status) nextSteps.get(i)).type) {
52 return (Status) 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 root.addStep(ifNode);
92 root.addStep(whileNode);
93 root.addStep(switchNode);
94 root.addStep(forInit);
95 root.addStep(forExpr);
96 root.addStep(forUpdate);
97 root.addStep(forSt);
98 root.addStep(doSt);
99
100 ifNode.addStep(ifSt);
101 ifNode.addStep(ifStWithoutElse);
102 ifSt.addStep(elseSt);
103 ifStWithoutElse.addStep(root);
104 elseSt.addStep(root);
105
106 whileNode.addStep(whileSt);
107 whileSt.addStep(root);
108
109 switchNode.addStep(caseSt);
110 switchNode.addStep(switchDefault);
111 switchNode.addStep(switchEnd);
112 caseSt.addStep(caseSt);
113 caseSt.addStep(switchDefault);
114 caseSt.addStep(switchEnd);
115 switchDefault.addStep(switchEnd);
116 switchDefault.addStep(caseSt);
117 switchEnd.addStep(root);
118
119 forInit.addStep(forExpr);
120 forInit.addStep(forUpdate);
121 forInit.addStep(forSt);
122 forExpr.addStep(forUpdate);
123 forExpr.addStep(forSt);
124 forUpdate.addStep(forSt);
125 forSt.addStep(forEnd);
126 forEnd.addStep(root);
127
128 doSt.addStep(doExpr);
129 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 public SequenceChecker(List bracesList) {
142 this.aktStatus = root;
143 this.bracesList = bracesList;
144 }
145
146 /***
147 * Finds the first most inner sequence e.g IFStart & IFEnd. If no sequence
148 * is found or the list is empty the method returns false.
149 */
150 public boolean run() {
151 this.aktStatus = root;
152 this.firstIndex = 0;
153 this.lastIndex = 0;
154 boolean lookAhead = false;
155
156 for (int i = 0; i < this.bracesList.size(); i++) {
157 StackObject so = (StackObject) bracesList.get(i);
158 aktStatus = this.aktStatus.step(so.getType());
159
160 if (aktStatus == null) {
161 if (lookAhead) {
162 this.lastIndex = i - 1;
163 return false;
164 }
165 this.aktStatus = root;
166 this.firstIndex = i;
167 i--;
168 continue;
169 } else {
170 if (aktStatus.isLastStep() && !aktStatus.hasMoreSteps()) {
171 this.lastIndex = i;
172 return false;
173 } else if (aktStatus.isLastStep() && aktStatus.hasMoreSteps()) {
174 lookAhead = true;
175 this.lastIndex = i;
176 }
177 }
178 }
179 return this.firstIndex == this.lastIndex;
180 }
181
182 public int getFirstIndex() {
183 return this.firstIndex;
184 }
185
186 public int getLastIndex() {
187 return this.lastIndex;
188 }
189
190 }