Actually, there is no need to check any cases "manually". You can just run the following algorithm:
Iterate over the given sequence. Start with an empty stack.
If the current char is an opening bracket, just push it to the stack.
If it's a closing bracket, check that the stack is not empty and the top element of the step is an appropriate opening bracket(that it is, matches this one). If it is not, report an error. Otherwise, pop the top element from the stack.
In the end, the sequence is correct iff the stack is empty.
Why is it correct? Here is a sketch of a proof: if this algorithm reported that the sequence is corrected, it had found a matching pair of all brackets. Thus, the sequence is indeed correct by definition. If it has reported an error:
If the stack was not empty in the end, the balance of opening and closing brackets is not zero. Thus, it is not a correct sequence.
If the stack was empty when we had to pop an element, the balance is off again.
If there was a wrong element on top of the stack, a pair of "wrong" brackets should match each other. It means that the sequence is not correct.
I have shown that:
If the algorithm has reported that the sequence is correct, it is correct.
If the algorithm has reported that the sequence is not correct, it is incorrect(note that I do not use the fact that there are no other cases except those that are mentioned in your question).
This two points imply that this algorithm works for all possible inputs.