ParenthesesTreeParser { static <B> TreeNode<B> parse( final String value, final Function<? super String, ? extends B> mapper ) { requireNonNull(value); requireNonNull(mapper); final TreeNode<B> root = TreeNode.of(); final Deque<TreeNode<B>> parents = new ArrayDeque<>(); TreeNode<B> current = root; for (Token token : tokenize(value.trim())) { switch (token.seq) { case "(": if (current == null) { throw new IllegalArgumentException(format( "Illegal parentheses tree string: '%s'.", value )); } final TreeNode<B> tn1 = TreeNode.of(); current.attach(tn1); parents.push(current); current = tn1; break; case ",": if (parents.isEmpty()) { throw new IllegalArgumentException(format( "Expect '(' at position %d.", token.pos )); } final TreeNode<B> tn2 = TreeNode.of(); assert parents.peek() != null; parents.peek().attach(tn2); current = tn2; break; case ")": if (parents.isEmpty()) { throw new IllegalArgumentException(format( "Unbalanced parentheses at position %d.", token.pos )); } current = parents.pop(); if (parents.isEmpty()) { current = null; } break; default: if (current == null) { throw new IllegalArgumentException(format( "More than one root element at pos %d: '%s'.", token.pos, value )); } if (current.value() == null) { current.value(mapper.apply(token.seq)); } break; } } if (!parents.isEmpty()) { throw new IllegalArgumentException( "Unbalanced parentheses: " + value ); } return root; } private  ParenthesesTreeParser();   }
@Test public void emptyTree() { Assert.assertEquals( parse("", Function.identity()), TreeNode.of() ); }
@Test public void rootTree() { Assert.assertEquals( parse("a", Function.identity()), TreeNode.of("a") ); }
@Test public void oneLevelOneTree() { Assert.assertEquals( parse("a(b)", Function.identity()), TreeNode.of("a").attach("b") ); }
@Test public void oneLevelTwoTree() { Assert.assertEquals( parse("a(b,c)", Function.identity()), TreeNode.of("a").attach("b", "c") ); }
@Test public void oneLevelTwoThreeTree() { Assert.assertEquals( parse("a(b,c,d)", Function.identity()), TreeNode.of("a").attach("b", "c", "d") ); }
@Test public void oneLevelThreeThreeTree() { Assert.assertEquals( parse("a ( b , c , d ( 1 , 2 ) )", String::trim), TreeNode.of("a") .attach("b", "c") .attach(TreeNode.of("d") .attach("1", "2")) ); }
@Test(dataProvider = "validTrees") public void parseValid(final String string, final TreeNode<String> tree) { final TreeNode<String> node = parse(string, Function.identity()); final String nodeString = node.toParenthesesString(); Assert.assertEquals(nodeString, string); Assert.assertEquals(node, tree); }
@Test(dataProvider = "invalidTrees", expectedExceptions = IllegalArgumentException.class) public void parseInvalid(final String invalid) { final Object obj = parse(invalid, Function.identity()); System.out.println(obj); }