View Javadoc

1   /*
2    * Created on 11.07.2004
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       * Element of logical structure of brace nodes.
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      * Defines the logical structure.
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 }