package amazon.papertest2; import java.util.ArrayList; import java.util.List; /** * About 5.Write up an analysis on the run-time complexity of your code.  * * This parser will look back and at the badest condition, the run-time * complexity is O(n*m). n stands for the length of regular expression and m * stands for the length of input. * * @author Mark Zang * */ public class SimpleRegularExpParser { public SimpleMatcher matcher; private int currIdx = 0; private String input; private static final char DOT = '.'; private static final char STAR = '*'; private SimpleRegularExpParser(String regularExp) { List<SimpleMatcher> matcherList = new ArrayList<SimpleMatcher>(regularExp.length()); SimpleMatcher lookBack = null; for (int i = 0; i < regularExp.length(); i++) { char ch = regularExp.charAt(i); SimpleMatcher curr = null; switch (ch) { case STAR: curr = new WildCharMatcher(); lookBack = curr; break; case DOT: curr = new OneCharMatcher(); break; default: curr = new CharMatcher(ch); break; } matcherList.add(curr); if (curr != lookBack) { curr.setLookBack(lookBack); } } matcher = matcherList.get(0); for (int i = 0; i < matcherList.size() - 1; i++) { matcherList.get(i).setNext(matcherList.get(i + 1)); } } public static boolean parse(String regularExp, String input) { if (regularExp == null || regularExp.length() == 0) { return false; } SimpleRegularExpParser parser = new SimpleRegularExpParser(regularExp); return parser.parse(input); } public static SimpleRegularExpParser getParser(String regularExp) { if (regularExp == null || regularExp.length() == 0) { return null; } SimpleRegularExpParser parser = new SimpleRegularExpParser(regularExp); return parser; } public boolean parse(String input) { this.input = input; currIdx = 0; SimpleMatcher currM = matcher; int len = input.length(); while (currM != null) { // not enough input to match if (currIdx >= len && (currM instanceof WildCharMatcher == false)) { return false; } boolean ret = currM.accept(); if (ret == true) { currM = currM.next; } else { if (currM.lookBack == null) { return false; } else { currM = currM.lookBack; } } } if (currIdx != len) { return false; } return true; } abstract class SimpleMatcher { SimpleMatcher lookBack; SimpleMatcher next; public SimpleMatcher() { } public SimpleMatcher getNext() { return next; } public void setNext(SimpleMatcher next) { this.next = next; } public SimpleMatcher getLookBack() { return lookBack; } public void setLookBack(SimpleMatcher lookBack) { this.lookBack = lookBack; } public abstract boolean accept(); } class CharMatcher extends SimpleMatcher { char ch; public CharMatcher(char ch) { this.ch = ch; } @Override public boolean accept() { char currChar = input.charAt(currIdx); boolean ret = (ch == currChar); if (ret == true) { currIdx++; } return ret; } } class OneCharMatcher extends SimpleMatcher { public OneCharMatcher() { } @Override public boolean accept() { currIdx++; return true; } } class WildCharMatcher extends SimpleMatcher { private int savePoint = -1; public WildCharMatcher() { } @Override public boolean accept() { if (next == null) { currIdx = input.length(); return true; } if (savePoint == -1) { savePoint = currIdx; } else { savePoint++; currIdx = savePoint; } return true; } } }