1/* 2 * Copyright (C) 2010 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.google.clearsilver.jsilver.syntax; 18 19import com.google.clearsilver.jsilver.autoescape.EscapeMode; 20import com.google.clearsilver.jsilver.exceptions.JSilverIOException; 21import com.google.clearsilver.jsilver.syntax.analysis.DepthFirstAdapter; 22import com.google.clearsilver.jsilver.syntax.node.EOF; 23import com.google.clearsilver.jsilver.syntax.node.Node; 24import com.google.clearsilver.jsilver.syntax.node.Start; 25import com.google.clearsilver.jsilver.syntax.node.Token; 26 27import java.io.BufferedReader; 28import java.io.FileReader; 29import java.io.IOException; 30import java.io.Reader; 31 32/** 33 * Dumps the syntax tree to text. Useful for debugging and understanding how the tree is structured. 34 */ 35public class SyntaxTreeDumper extends DepthFirstAdapter { 36 37 private final Appendable out; 38 39 private final String newLine = System.getProperty("line.separator"); 40 41 private int indent; 42 43 public SyntaxTreeDumper(Appendable out) { 44 this.out = out; 45 } 46 47 /** 48 * Dumps to System.out. 49 */ 50 public SyntaxTreeDumper() { 51 this(System.out); 52 } 53 54 @Override 55 public void defaultIn(Node node) { 56 write(nodeName(node) + " {"); 57 indent++; 58 } 59 60 @Override 61 public void defaultOut(Node node) { 62 indent--; 63 write("}"); 64 } 65 66 @Override 67 public void defaultCase(Node node) { 68 write(nodeName(node)); 69 } 70 71 private String nodeName(Node node) { 72 if (node instanceof Start || node instanceof EOF) { 73 return node.getClass().getSimpleName(); 74 } else if (node instanceof Token) { 75 Token token = (Token) node; 76 String tokenType = token.getClass().getSimpleName().substring(1); 77 return tokenType + " [line:" + token.getLine() + ",pos:" + token.getPos() + "] \"" 78 + escape(token.getText()) + "\""; 79 } else { 80 // Turn PSomeProduction, AConcreteSomeProduction 81 // Into SomeProduction, Concrete 82 String p = node.getClass().getSuperclass().getSimpleName().substring(1); 83 String a = node.getClass().getSimpleName().substring(1); 84 a = a.substring(0, a.length() - p.length()); 85 return "<" + a + ">" + p; 86 } 87 88 } 89 90 private String escape(String text) { 91 StringBuilder result = new StringBuilder(); 92 for (int i = 0; i < text.length(); i++) { 93 char c = text.charAt(i); 94 switch (c) { 95 case '\\': 96 result.append("\\\\"); 97 break; 98 case '"': 99 result.append("\\\""); 100 break; 101 case '\n': 102 result.append("\\n"); 103 break; 104 case '\r': 105 result.append("\\r"); 106 break; 107 case '\t': 108 result.append("\\t"); 109 break; 110 default: 111 result.append(c); 112 } 113 } 114 return result.toString(); 115 } 116 117 private void write(String text) { 118 try { 119 // Write to temp string in case output isn't buffered. 120 StringBuilder line = new StringBuilder(); 121 for (int i = 0; i < indent; i++) { 122 line.append(" "); 123 } 124 line.append(text); 125 line.append(newLine); 126 out.append(line); 127 } catch (IOException e) { 128 throw new JSilverIOException(e); 129 } 130 } 131 132 /** 133 * Simple command line tool for parsing a template and dumping out the AST. 134 */ 135 public static void main(String[] args) throws IOException { 136 if (args.length == 0) { 137 System.err.println("Provide filename of template."); 138 return; 139 } 140 String filename = args[0]; 141 Reader reader = new BufferedReader(new FileReader(filename)); 142 try { 143 SyntaxTreeBuilder builder = new SyntaxTreeBuilder(); 144 TemplateSyntaxTree tree = builder.parse(reader, filename, EscapeMode.ESCAPE_NONE); 145 tree.apply(new SyntaxTreeDumper(System.out)); 146 } finally { 147 reader.close(); 148 } 149 } 150 151} 152