The following should work, it would also put 'text1', 'text2', and 'text3' into the correct groups:
^(.+?)(?:\s(.*?)(?:\s;(.*))?)?$
See it working: http://www.rubular.com/r/IyPyF3wXLx
Here is an explanation:
^ # start of string
(.+?) # put text1 in group 1
(?: # start an optional non-capturing group
\s(.*?) # space followed by text2, put text2 in group 2
(?: # start an optional non-capturing group
\s;(.*) # space and semicolon, followed by text3, put text3 in group 3
)? # end of optional non-capturing group
)? # end of optional non-capturing group
$ # end of string
The optional groups in the middle allow your regex to match text2 and text3 if they are present, but still match if they are not.