📄 astprinter.java
字号:
// $Id: ASTPrinter.java 7460 2005-07-12 20:27:29Z steveebersole $package org.hibernate.hql.ast.util;import java.io.ByteArrayOutputStream;import java.io.PrintStream;import java.io.PrintWriter;import java.lang.reflect.Field;import java.lang.reflect.Modifier;import java.util.ArrayList;import java.util.HashMap;import java.util.Map;import org.hibernate.hql.ast.tree.DisplayableNode;import org.hibernate.util.StringHelper;import antlr.collections.AST;/** * An 'ASCII art' AST printer for debugging ANTLR grammars. * * @author Joshua Davis (pgmjsd@sourceforge.net) */public class ASTPrinter { private Map tokenTypeNamesByTokenType; private Class tokenTypeConstants; private boolean showClassNames = true; /** * Constructs an org.hibernate.hql.antlr.ASTPrinter, given the class that contains the token type * constants (typically the '{grammar}TokenTypes' interface generated by * ANTLR). * * @param tokenTypeConstants The class with token type constants in it. */ public ASTPrinter(Class tokenTypeConstants) { this.tokenTypeConstants = tokenTypeConstants; } /** * Returns true if the node class names will be displayed. * * @return true if the node class names will be displayed. */ public boolean isShowClassNames() { return showClassNames; } /** * Enables or disables AST node class name display. * * @param showClassNames true to enable class name display, false to disable */ public void setShowClassNames(boolean showClassNames) { this.showClassNames = showClassNames; } /** * Prints the AST in 'ASCII art' tree form to the specified print stream. * * @param ast The AST to print. * @param out The print stream. */ private void showAst(AST ast, PrintStream out) { showAst( ast, new PrintWriter( out ) ); } /** * Prints the AST in 'ASCII art' tree form to the specified print writer. * * @param ast The AST to print. * @param pw The print writer. */ public void showAst(AST ast, PrintWriter pw) { ArrayList parents = new ArrayList(); showAst( parents, pw, ast ); pw.flush(); } /** * Prints the AST in 'ASCII art' tree form into a string. * * @param ast The AST to display. * @param header The header for the display. * @return The AST in 'ASCII art' form, as a string. */ public String showAsString(AST ast, String header) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream ps = new PrintStream( baos ); ps.println( header ); showAst( ast, ps ); ps.flush(); return new String( baos.toByteArray() ); } /** * Get a single token type name in the specified set of token type constants (interface). * * @param tokenTypeConstants Token type constants interface (e.g. HqlSqlTokenTypes.class). * @param type The token type ( typically from ast.getType() ). * @return The token type name, *or* the integer value if the name could not be found for some reason. */ public static String getConstantName(Class tokenTypeConstants, int type) { String tokenTypeName = null; if ( tokenTypeConstants != null ) { Field[] fields = tokenTypeConstants.getFields(); for ( int i = 0; i < fields.length; i++ ) { Field field = fields[i]; tokenTypeName = getTokenTypeName( field, type, true ); if ( tokenTypeName != null ) { break; // Stop if found. } } // for } // if type constants were provided // Use the integer value if no token type name was found if ( tokenTypeName == null ) { tokenTypeName = Integer.toString( type ); } return tokenTypeName; } private static String getTokenTypeName(Field field, int type, boolean checkType) { if ( Modifier.isStatic( field.getModifiers() ) ) { try { Object value = field.get( null ); if ( !checkType ) { return field.getName(); } else if ( value instanceof Integer ) { Integer integer = ( Integer ) value; if ( integer.intValue() == type ) { return field.getName(); } } // if value is an integer } // try catch ( IllegalArgumentException ignore ) { } catch ( IllegalAccessException ignore ) { } } // if the field is static return null; } /** * Returns the token type name for the given token type. * * @param type The token type. * @return String - The token type name from the token type constant class, * or just the integer as a string if none exists. */ private String getTokenTypeName(int type) { // If the class with the constants in it was not supplied, just // use the integer token type as the token type name. if ( tokenTypeConstants == null ) { return Integer.toString( type ); } // Otherwise, create a type id -> name map from the class if it // hasn't already been created. if ( tokenTypeNamesByTokenType == null ) { Field[] fields = tokenTypeConstants.getFields(); tokenTypeNamesByTokenType = new HashMap(); String tokenTypeName = null; for ( int i = 0; i < fields.length; i++ ) { Field field = fields[i]; tokenTypeName = getTokenTypeName( field, type, false ); if ( tokenTypeName != null ) { try { tokenTypeNamesByTokenType.put( field.get( null ), field.getName() ); } catch ( IllegalAccessException ignore ) { } } } // for } // if the map hasn't been created. return ( String ) tokenTypeNamesByTokenType.get( new Integer( type ) ); } private void showAst(ArrayList parents, PrintWriter pw, AST ast) { if ( ast == null ) { pw.println( "AST is null!" ); return; } for ( int i = 0; i < parents.size(); i++ ) { AST parent = ( AST ) parents.get( i ); if ( parent.getNextSibling() == null ) { pw.print( " " ); } else { pw.print( " | " ); } } if ( ast.getNextSibling() == null ) { pw.print( " \\-" ); } else { pw.print( " +-" ); } showNode( pw, ast ); ArrayList newParents = new ArrayList( parents ); newParents.add( ast ); for ( AST child = ast.getFirstChild(); child != null; child = child.getNextSibling() ) { showAst( newParents, pw, child ); } newParents.clear(); } private void showNode(PrintWriter pw, AST ast) { String s = nodeToString( ast, isShowClassNames() ); pw.println( s ); } public String nodeToString(AST ast, boolean showClassName) { if ( ast == null ) { return "{null}"; } StringBuffer buf = new StringBuffer(); buf.append( "[" ).append( getTokenTypeName( ast.getType() ) ).append( "] " ); if ( showClassName ) { buf.append( StringHelper.unqualify( ast.getClass().getName() ) ).append( ": " ); } buf.append( "'" ); String text = ast.getText(); appendEscapedMultibyteChars(text, buf); buf.append( "'" ); if ( ast instanceof DisplayableNode ) { DisplayableNode displayableNode = ( DisplayableNode ) ast; // Add a space before the display text. buf.append( " " ).append( displayableNode.getDisplayText() ); } String s = buf.toString(); return s; } public static void appendEscapedMultibyteChars(String text, StringBuffer buf) { char[] chars = text.toCharArray(); for (int i = 0; i < chars.length; i++) { char aChar = chars[i]; if (aChar > 256) { buf.append("\\u"); buf.append(Integer.toHexString(aChar)); } else buf.append(aChar); } } public static String escapeMultibyteChars(String text) { StringBuffer buf = new StringBuffer(); appendEscapedMultibyteChars(text,buf); return buf.toString(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -