Efficiency of regular expressions
johndcook.com
johndcook.com
The worst case I ever saw had many .* running over some c++ source which would take several minutes per file. Presumably trying all combinations of backtracking. With the negated character class [^x] it was < .1 of a second.
Edit: I see his twitter feed has .* as the icon. Ha!
Edit2: My * are getting eaten by the formatter. There should be no space after them
This makes the match non greedy.
Using regular expressions to break the input text into tokens ("tokenizing" or "lexing") and then matching the sequence of tokens according to a grammar ("parsing") is usually much simpler. The two-phase approach often factors out some complexity - only the lexer needs to care about things like whitespace, for example.
While most compiler textbooks cover lexing and parsing, I particularly recommend Andrew Appel's _Modern Compiler Implementation in ML_ and Niklaus Wirth's _Compiler Construction_ (free online, http://www-old.oberon.ethz.ch/WirthPubl/CBEAll.pdf).
More recommendations on learning parsing here: http://news.ycombinator.com/item?id=1820858
Subexpression capture is great, and at least that can be done in (low-order) polynomial time with a nondeterministic automaton approach. So really, the only problem is the backreferences.
One problem with Scheme itself appears to be that there is no way to examine a portion of a string. The substring function actually makes a whole new copy of the part you want to examine (which may be the remainder of the input string after the token you just lexed, as it was in my case).
Most of the string functions in Common Lisp are set up so that you can specify a starting index in a string so that it is possible to examine portions of a string without making a whole new copy.