/************************************************************************************** * Copyright (C) 2008 EsperTech, Inc. All rights reserved. * * http://esper.codehaus.org * * http://www.espertech.com * * ---------------------------------------------------------------------------------- * * The software in this package is published under the terms of the GPL license * * a copy of which has been included with this distribution in the license.txt file. * **************************************************************************************/ package com.espertech.esper.antlr; import org.antlr.runtime.CommonTokenStream; import org.antlr.runtime.Token; import org.antlr.runtime.tree.Tree; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; /** * Utility class for AST node handling. */ public class ASTUtil { private static Log log = LogFactory.getLog(ASTUtil.class); private final static String PROPERTY_ENABLED_AST_DUMP = "ENABLE_AST_DUMP"; /** * Returns the first child node (shallow search) of the given parent that matches type, or null if no child node * matches type. * @param parent whose child nodes to ask for type * @param type the type looked for * @return child node if found, or null if not found */ public static Tree findFirstNode(Tree parent, int type) { for (int i = 0; i < parent.getChildCount(); i++) { Tree child = parent.getChild(i); if (child.getType() == type) { return child; } } return null; } public static List<Tree> findAllNodes(Tree parent, int type) { List<Tree> result = null; for (int i = 0; i < parent.getChildCount(); i++) { Tree child = parent.getChild(i); if (child.getType() == type) { if (result == null) { result = new ArrayList<Tree>(); } result.add(child); } } if (result == null) { return Collections.emptyList(); } return result; } /** * Dump the AST node to system.out. * @param ast to dump */ public static void dumpAST(Tree ast) { if (System.getProperty(PROPERTY_ENABLED_AST_DUMP) != null) { StringWriter writer = new StringWriter(); PrintWriter printer = new PrintWriter(writer); renderNode(new char[0], ast, printer); dumpAST(printer, ast, 2); log.info(".dumpAST ANTLR Tree dump follows...\n" + writer.toString()); } } private static void dumpAST(PrintWriter printer, Tree ast, int ident) { char[] identChars = new char[ident]; Arrays.fill(identChars, ' '); if (ast == null) { renderNode(identChars, null, printer); return; } for (int i = 0; i < ast.getChildCount(); i++) { Tree node = ast.getChild(i); if (node == null) { throw new NullPointerException("Null AST node"); } renderNode(identChars, node, printer); dumpAST(printer, node, ident + 2); } } /** * Print the token stream to the logger. * @param tokens to print */ public static void printTokens(CommonTokenStream tokens) { if (log.isDebugEnabled()) { List tokenList = tokens.getTokens(); StringWriter writer = new StringWriter(); PrintWriter printer = new PrintWriter(writer); for (int i = 0; i < tokens.size(); i++) { Token t = (Token) tokenList.get(i); String text = t.getText(); if (text.trim().length() == 0) { printer.print("'" + text + "'"); } else { printer.print(text); } printer.print('['); printer.print(t.getType()); printer.print(']'); printer.print(" "); } printer.println(); log.debug("Tokens: " + writer.toString()); } } private static void renderNode(char[] ident, Tree node, PrintWriter printer) { printer.print(ident); if (node == null) { printer.print("NULL NODE"); } else { printer.print(node.getText()); printer.print(" ["); printer.print(node.getType()); printer.print("]"); if (node.getText() == null) { printer.print(" (null value in text)"); } else if (node.getText().contains("\\")) { int count = 0; for (int i = 0; i < node.getText().length(); i++) { if (node.getText().charAt(i) == '\\') { count++; } } printer.print(" (" + count + " backlashes)"); } } printer.println(); } }