Match opening tags improvements
I've made a couple of alterations to the opening tag regex.
I've changed the non-capturing group that previously grouped attributes to use Atomic Grouping (?>...) so that states are not saved and therefore reducing any uneccessary backtracking. I've also added a negative lookahead assertion at the beginning of that group so that, if the ending tag is found the whole group will fail and I can step out of the group immediately. This also allows me to remove the lazy (...)*? quantifer at the end of the group and allow it to become (...)*
The entire pattern now looks like this:
(?'openTag'<)
\s*?
(?'tagName'\??\w+)
(?>
(?!=[\/\?]?>)
\s*?
(?'attribName'\w+)
(?:\s*(?'attribSign'=)\s*)
(?'attribValue'
(?:\'[^\']*\'|\"[^\"]*\"|\w+)
)
)*
\s*?
(?'closeTag'[\/\?]?>)
Or, rendered as a single string...
(?'openingTag'<)\s*?(?'tagName'\??\w+)(\s*?(?>(?!=[\/\?]?>)(?'attribName'\w+)(?:\s*(?'attribSign'=)\s*)(?'attribValue'(?:\'[^\']*\'|\""[^\""]*\""|\w+))))*\s*?(?'closeTag'[\/\?]?>)