2.1.129 [ECMA-262-1999] Section 15.10.2.5, Term

V0189:

The production Term :: Atom Quantifier evaluates as follows:

1. Evaluate Atom to obtain a Matcher m.

2. Evaluate Quantifier to obtain the three results: an integer min, an integer (or ∞) max, and boolean greedy.

3. If max is finite and less than min, then throw a #SyntaxError# __RegExpError__ exception.

4. Let parenIndex be the number of left capturing parentheses in the entire regular expression that occur to the left of this production expansion's Term. This is the total number of times the Atom :: ( Disjunction ) production is expanded prior to this production's Term plus the total number of Atom :: ( Disjunction ) productions enclosing this Term.

5. Let parenCount be the number of left capturing parentheses in the expansion of this production's Atom. This is the total number of Atom :: ( Disjunction ) productions enclosed by this production's Atom.

6. Return an internal Matcher closure that takes two arguments, a State x and a Continuation c, and performs the following:

  1. Call RepeatMatcher(m, min, max, greedy, x, c, parenIndex, parenCount) and return its result.

V0190:

The internal helper function RepeatMatcher takes eight parameters, a Matcher m, an integer min, an integer (or ∞) max, a boolean greedy, a State x, a Continuation c, an integer parenIndex, and an integer parenCount, and performs the following:

  1. If max is zero, then call c(x) and return its result.

  2. Create an internal Continuation closure d that takes one State argument y and performs the following:

    1. If min is zero and y's endIndex is equal to x's endIndex, then return failure.

    2. If min is zero then let min2 be zero; otherwise let min2 be min-1.

    3. If max is ∞, then let max2 be ∞; otherwise let max2 be max-1.

    4. Call RepeatMatcher(m, min2, max2, greedy, y, c, parenIndex, parenCount) and return its result.

  3. Let cap be a fresh copy of x's captures internal array.

  4. #For every integer k that satisfies parenIndex < k and kparenIndex+parenCount, set cap[k] to undefined.#

  5. Let e be x's endIndex.

  6. Let xr be the State (e, cap).

  7. If min is not zero, then call m(xr, d) and return its result.

  8. If greedy is true, then go to step 12.

  9. Call c(x) and let z be its result.

  10. If z is not failure, return z.

  11. Call m(xr, d) and return its result.

  12. Call m(xr, d) and let z be its result.

  13. If z is not failure, return z.

  14. Call c(x) and return its result.

V0191:

The above ordering of choice points can be used to write a regular expression that calculates the greatest common divisor of two numbers (represented in unary notation). The following example calculates the gcd of 10 and 15:

"aaaaaaaaaa,aaaaaaaaaaaaaaa".replace(/^(a+)\1*,\1+$/,"$1")

which returns the gcd in unary notation "aaaaa".

#Step 4 of the RepeatMatcher clears Atom's captures each time t is repeated. We can see its oolean in the regular expression#

#/(z)((a+)?(b+)?(c))*/.exec("zaacbbbcac")#

#which returns the array#

#["zaacbbbcac", "z", "ac", "a", undefined, "c"]#

#and not#

#["zaacbbbcac", "z", "ac", "a", "bbb", "c"]#

#because each iteration of the outermost * clears all captured strings contained in the quantified Atom, which in this case includes capture strings numbered 2, 3, and 4.#

Jscript 5.x does not clear an Atom's captures each time the Atom is repeated.