import java.util.Scanner; /* This class has a method that tests a String to see whether it is properly ** nested with respect to a given set of pairs of matching parenthesis ** symbols. (The three most common species of parenthesis come in these ** pairs: '(' with ')', '[' with ']', and '{' with '}'. ** ** One purpose is to illustrate the use of a stack. ** ** Author: R. McCloskey ** Date: January 2020 */ public class ParenNestingTester { /* Returns -1 if the given String (s) is properly nested with respect to ** the matching lists of left and right "parentheses" described by the ** second and third parameters. Otherwise, returns the lowest-numbered ** position in s where a violation of proper nesting occurs. There are ** two kinds of violations, one being an occurrence of a right parenthesis ** having no matching mate to its left. The other is that the string ** has unmatched left parentheses (and thus would have to be extended ** with matching right parentheses in order to be valid). In the latter ** case, the value returned is the length of s. ** Any characters in s that appear in neither leftParens nor rightParens ** are ignored. ** ** Example: Suppose that leftParens = "([{" and rightParens = ")]}", ** corresponding to the most common species of parentheses. Then the ** string "{()glorp} [ ] " is properly nested, but "[([]}[])" fails ** at position 3 because an unmatched '}' appears there. The string ** "[(()" fails at position 4 because it ends there with unmatched ** left parentheses. ** ** pre: leftParens.length() == rightParens.length() && ** no character appears in both leftParens and rightParens */ public static int isProperlyNested(String s, String leftParens, String rightParens) { boolean goodSoFar = true; //Stack stk = new StackViaArray(); Stack stk = new StackViaLink1(); int k = 0; while (k != s.length() && goodSoFar) { char ch = s.charAt(k); if (leftParens.indexOf(ch) != -1) { // ch is a left parenthesis, stk.push(ch); // so push it onto the stack k = k+1; } else { // ch is not a left parenthesis int r = rightParens.indexOf(ch); if (r != -1) { // ch is a right parenthesis if (stk.isEmpty() || stk.topOf() != leftParens.charAt(r)) { goodSoFar = false; // no matching left paren on stack } else { stk.pop(); // ch is matched by symbol on top of stack, k = k+1; // so pop it off } } else { // ch is neither a left nor right parenthesis, so ignore it k = k+1; } } } // At this point, s has passed the test iff we've reached its end // and the stack is empty. if (k == s.length() && stk.isEmpty()) { k = -1; } return k; } /* For each string entered by the user, it is tested for proper nesting ** with respect to the standard three species of parentheses. */ public static void main(String[] args) { String LEFT = "([{"; String RIGHT = ")]}"; Scanner keyboard = new Scanner(System.in); do { System.out.print("\nEnter string to test for proper nesting:"); String str = keyboard.nextLine(); int m = isProperlyNested(str, LEFT, RIGHT); if (m == -1) { System.out.println(" Correctly nested"); } else { System.out.println(str); printChars(' ', m); System.out.println("^ Error here"); } } while (true); } /* Prints the specified character the specified number of times. */ private static void printChars(char ch, int times) { for (int i=0; i != times; i++) { System.out.print(ch); } } }