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 }