SyntaxTreeDumper.java revision 56ed4167b942ec265f9cee70ac4d71d10b3835ce
15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/* 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Copyright (C) 2010 Google Inc. 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Licensed under the Apache License, Version 2.0 (the "License"); 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * you may not use this file except in compliance with the License. 6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * You may obtain a copy of the License at 7116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * http://www.apache.org/licenses/LICENSE-2.0 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * Unless required by applicable law or agreed to in writing, software 11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * distributed under the License is distributed on an "AS IS" BASIS, 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * See the License for the specific language governing permissions and 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * limitations under the License. 15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)package com.google.clearsilver.jsilver.syntax; 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 19116680a4aac90f2aa7413d9095a592090648e557Ben Murdochimport com.google.clearsilver.jsilver.autoescape.EscapeMode; 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport com.google.clearsilver.jsilver.exceptions.JSilverIOException; 21116680a4aac90f2aa7413d9095a592090648e557Ben Murdochimport com.google.clearsilver.jsilver.syntax.analysis.DepthFirstAdapter; 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)import com.google.clearsilver.jsilver.syntax.node.EOF; 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)import com.google.clearsilver.jsilver.syntax.node.Node; 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)import com.google.clearsilver.jsilver.syntax.node.Start; 25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)import com.google.clearsilver.jsilver.syntax.node.Token; 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)import java.io.BufferedReader; 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)import 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