It is instructive to look at how the matcher handles the string "aba" for the regular expression (a + ab)(a + b).
The greedy match is to peel off an a. That eventually fails and the matcher has to try ab instead.
accept (a + ab)(a + b) "aba"
== match (a + ab)(a + b) [a,b,a] List.null
[Times]
== match (a + ab) [a,b,a] (fn cs' => match (a + b) cs' List.null)
[Plus]
== match a [a,b,a] (fn cs' => match (a + b) cs' List.null)
orelse
match ab [a,b,a] (fn cs' => match (a + b) cs' List.null)
Now let's examine the first half of that orelse:
match a [a,b,a] (fn cs' => match (a + b) List.null)
[Char]
== (a=a) andalso (fn cs' => match (a + b) cs' List.null)([b,a])
== match (a + b) [b,a] List.null
[Plus]
== (match a [b,a] List.null) orelse (match b [b,a] List.null)
[Char]
== ((a=b) andalso List.null[a]) orelse (match b [b,a] List.null)
== false orelse (match b [b,a] List.null)
[Char]
== (b=b) andalso List.null[a]
== true andalso false
== false
Now let's examine the second half of the orginal orelse:
match ab [a,b,a] (fn cs' => match (a + b) cs' List.null)
[Times]
== match a [a,b,a] (fn cs'' => match b cs'' (fn cs' => match (a + b) cs' List.null))
[Char]
== (a=a) andalso (fn cs'' => match b cs'' (fn cs' => match (a + b) cs' List.null))([b,a])
== match b [b,a] (fn cs' => match (a + b) cs' List.null)
[Char]
== (b=b) andalso (fn cs' => match (a + b) cs' List.null)([a])
== match (a + b) [a] List.null
[Plus]
== (match a [a] List.null) orelse (match b [a] List.null)
[Char]
== ((a=a) andalso List.null[]) orelse (match b [a] List.null)
== (true andalso true) orelse (match b [a] List.null)
== true
And that is how the matcher recognizes that the string "aba" lies in the language of the regular expression (a + ab)(a + b).