Home | History | Annotate | Download | only in syntax
      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 
     17 package com.google.clearsilver.jsilver.syntax;
     18 
     19 import com.google.clearsilver.jsilver.autoescape.EscapeMode;
     20 import com.google.clearsilver.jsilver.exceptions.JSilverIOException;
     21 import com.google.clearsilver.jsilver.syntax.analysis.DepthFirstAdapter;
     22 import com.google.clearsilver.jsilver.syntax.node.EOF;
     23 import com.google.clearsilver.jsilver.syntax.node.Node;
     24 import com.google.clearsilver.jsilver.syntax.node.Start;
     25 import com.google.clearsilver.jsilver.syntax.node.Token;
     26 
     27 import java.io.BufferedReader;
     28 import java.io.FileReader;
     29 import java.io.IOException;
     30 import java.io.Reader;
     31 
     32 /**
     33  * Dumps the syntax tree to text. Useful for debugging and understanding how the tree is structured.
     34  */
     35 public 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