View Javadoc

    1   /**
    2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
    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<Status> nextSteps = new ArrayList<Status>();
    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 == 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 bracesList;
    141
    142     private int firstIndex = -1;
    143     private int lastIndex = -1;
    144
    145     /*
    146      * Defines the logical structure.
    147      * */
    148     public SequenceChecker(List bracesList) {
    149         this.aktStatus = root;
    150         this.bracesList = bracesList;
    151     }
    152
    153     /**
    154      * Finds the first most inner sequence e.g IFStart & IFEnd. If no sequence
    155      * is found or the list is empty the method returns false.
    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 = (StackObject) 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 }