Data Structures, Algorithms, & Applications in Java
Chapter 9, Exercise 15

The code is quite similar to that for Exercise 14. It is given below.
public class ParenthesisMatching4
{
   // top-level nested class  
   private static class StackElement
   {
      char theChar;         // character being stored
      int location;         // location of theChar

      // constructor
      public StackElement(char theChar, int theLocation)
      {
         location = theLocation;
         this.theChar = theChar;
      }
   }

   /** output the matched pairs of parentheses and brackets
     * in the string expr */
   public static void printMatchedPairs(String expr)
   {
      ArrayStack s = new ArrayStack();
      int length = expr.length();
   
      // scan expression expr for ( and )
      for (int i = 0; i < length; i++)
      {
         char newChar = expr.charAt(i);
         if (newChar == '(' || newChar == '[' || newChar == '{')
            // save left delimiter and its location
            s.push(new StackElement(newChar, i));
         else
            if (newChar == ')' || newChar == ']' || newChar == '}')
      	    try
            {// get possible matching left delimiter from stack
               StackElement stackElement = (StackElement) s.peek();
               if ((stackElement.theChar == '[' && newChar == ']') ||
                   (stackElement.theChar == '(' && newChar == ')') ||
                   (stackElement.theChar == '{' && newChar == '}'))
               {// we have a match
                  System.out.println(stackElement.location + "  " + i);
                  s.pop();  // matched this left delimiter
               }
               else
                  // no match
                  System.out.println("No match for right delimiter"
                                      + " at " + i);
            }
            catch (Exception e)
            {// stack was empty, no match exists
                System.out.println("No match for right delimiter"
                                    + " at " + i);
            }
         }
   
      // remaining left delimiters in stack are unmatched
      while (!s.empty())
         System.out.println("No match for left delimiter at "
                            + ((StackElement) s.pop()).location);
   }
}

The test program, input, and output are in the files ParenthesisMatching4.*.