0

I am writting a regex parser for which, a loop-switch anti-pattern appears to be the only approach. Please ignore actual rules of parsing, as this parsing-logic is just custom made for an internal application, and deviant from common use.

 public static boolean match(String regex, String str) {
        int i = 0;
        int j = 0;

        while ((i < regex.length() && j < str.length())) {

            switch(regex.charAt(i)) {

            case '.' : i++; j++; break;

            case '*' : // do something ; break

            default  : if (regex.charAt(i) != str.charAt(j)) { return false; }  else {i++; j++};
            }
        }     
   }

How can the loop-switch be prevented in such a case ? Is there any design pattern meant for such a purpose ?

JavaDeveloper
  • 5,320
  • 16
  • 79
  • 132
  • 1
    What's wrong with loop/switch? You can easily replace the switch/case statements with if/else statements – But I'm Not A Wrapper Class Nov 17 '13 at 21:23
  • 1
    I dont see anything wrong, but I read its an anti-pattern. http://en.wikipedia.org/wiki/Loop-switch_sequence – JavaDeveloper Nov 17 '13 at 21:28
  • It's really not much of an antipattern, just a dumb thing that gets you on DailyWTF. By this I mean that it's not that using every looping construct with a `switch` is wrong, but that specifically using a `for` or `foreach` over a range that's known at compile-time with a `switch` is blatantly inane. – millimoose Nov 17 '13 at 21:38
  • 2
    @JavaDeveloper: did you actually read that article? The second paragraph begins with `it is not necessarily an antipattern to use a switch statement within a loop [...]`, and then discusses circumstances under which it is not an antipattern. It doesn't mention this use specifically, but it is definitely one that would not be considered an antipattern. – Mac Nov 17 '13 at 21:39

2 Answers2

12

This is not the Loop-Switch Anti-Pattern!

The anti-pattern occurs when a loop and switch is used to sequence some actions which could just be sequenced as statements in the program (in effect letting the processor's loop-switch known as the fetch-execute cycle handle it):

for (step = 0; step < 3; step++) {
  switch (step) {
  case 0:
    do_the_first_thing();
    break;
  case 1:
    do_the_second_thing();
    break;
  case 2:
    do_the_third_thing();
    break;
  }
}

Instead of:

do_the_first_thing();
do_the_second_thing();
do_the_third_thing();

This isn't going on in your code. Your code is processing a regular expression, and so the cases can execute in whatever order is implied by the contents of the expression.

In the above anti-pattern, de facto sequenced steps are hidden behind logic which appears to be prepared to deal with any order of execution; but in fact it doesn't process any data, only the loop dummy variable, which predictably steps from 0 to 2.

Kaz
  • 55,781
  • 9
  • 100
  • 149
0

In general you should consider changing switch statements to some kind of delegation, as it couples the loop and the implementation of the actions that each regexp character result in strongly.

This would allow you to decouple the two things that are happening here:

  1. Looping over the regexp/match string
  2. Processing the chars at a given pair of positions in regexp/match string

In this case it could be achieved by having your regexp converted from a string of dumb characters to a list of objects that consume 0, 1 or n characters from the match string. Then you would just loop over those objects with the match string + state as input to each object.

However! In this case your code is very simple as it stands. Unless you plan to implement more metacharacters this is probably the cleanest, clearest implementation.

Anders Johansen
  • 10,165
  • 7
  • 35
  • 52