/* * Copyright 2013 Guidewire Software, Inc. */ package gw.internal.gosu.parser.java; import gw.internal.ext.org.antlr.runtime.Token; import gw.internal.gosu.parser.StringCache; import java.util.HashSet; import java.util.Stack; /** * Helper class to build trees representing the parsing process of a grammar. * * @author Yang Jiang (yang.jiang.z@gmail.com) */ public class TreeBuilder { Stack<IJavaASTNode> stack = new Stack<IJavaASTNode>(); private IJavaASTNode _node = new JavaASTNode("root"); private int _ignoreCount = 0; private IJavaASTNode IGNORE_NODE = new JavaASTNode("IGNORE"); private static HashSet<String> ignore = new HashSet<String>(); private static HashSet<String> ignore_recursive = new HashSet<String>(); static { ignore.add("classOrInterfaceDeclaration"); ignore.add("typeDeclaration"); ignore.add("classDeclaration"); ignore.add("classBodyDeclaration"); ignore.add("memberDecl"); ignore.add("formalParameterDecls"); ignore.add("interfaceDeclaration"); ignore.add("interfaceBodyDeclaration"); ignore.add("classOrInterfaceType"); ignore.add("primitiveType"); ignore.add("variableDeclarator"); ignore.add("enumConstants"); ignore.add("enumBodyDeclarations"); ignore.add("typeArguments"); ignore.add("annotationTypeElementDeclaration"); ignore.add("primary"); ignore.add("literal"); ignore.add("typeArgumentsOrDiamond"); ignore.add("nonWildcardTypeArgumentsOrDiamond"); ignore_recursive.add("block"); //ignore_recursive.add("variableInitializer"); } public IJavaASTNode addNode(String name) { if (ignore_recursive.contains(name)) { _ignoreCount++; return IGNORE_NODE; } if (ignore.contains(name) || name.contains("Expression")) { return null; } IJavaASTNode node = makeNode(name); if (_node != null) { _node.add(node); } return node; } private IJavaASTNode makeNode(String name) { if (name.equals("type")) { return new TypeASTNode(); } return new JavaASTNode(name); } /** * Same as addNode(), except that a leaf should contain no child. */ public IJavaASTNode addLeaf(String name, Token token) { if (_ignoreCount != 0 || (!isParentAnOpExpression() && (token.getType() == JavaLexer.LBRACE || token.getType() == JavaLexer.RBRACE || // Parens need to be included in expressions token.getType() == JavaLexer.LPAREN || token.getType() == JavaLexer.RPAREN || token.getType() == JavaLexer.COMMA || // Gt, Lt need to be included in expressions token.getType() == JavaLexer.GT || token.getType() == JavaLexer.LT || token.getType() == JavaLexer.SEMI || // Amp needs to be included in expressions token.getType() == JavaLexer.AMP || token.getType() == JavaLexer.PACKAGE || token.getType() == JavaLexer.EQ || token.getType() == JavaLexer.MONKEYS_AT || token.getType() == JavaLexer.DEFAULT)) ) { return null; } IJavaASTNode node = new LeafASTNode(token.getType(), StringCache.get(token.getText())); if (_node != null) { _node.add(node); } return node; } /** * Stores the current parent in the stack, this is usually called before setting a new parent. */ public void pushTop() { stack.push(_node); } /** * Restores the previous parent. */ public IJavaASTNode popTop() { IJavaASTNode ret = _node; if (_node == IGNORE_NODE) { _ignoreCount--; } _node = stack.pop(); return ret; } public void setCurrentParent(IJavaASTNode currentParent) { if (currentParent != null) { _node = currentParent; } } public IJavaASTNode getTree() { return _node; } public boolean isParentAnOpExpression() { if( _node == null ) { return false; } String text = _node.getText(); return text != null && (text.endsWith( "Op" ) || text.endsWith( "elementValue" )); } }