Home | History | Annotate | Download | only in src
      1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #ifndef V8_PRETTYPRINTER_H_
     29 #define V8_PRETTYPRINTER_H_
     30 
     31 #include "ast.h"
     32 
     33 namespace v8 {
     34 namespace internal {
     35 
     36 #ifdef DEBUG
     37 
     38 class PrettyPrinter: public AstVisitor {
     39  public:
     40   PrettyPrinter();
     41   virtual ~PrettyPrinter();
     42 
     43   // The following routines print a node into a string.
     44   // The result string is alive as long as the PrettyPrinter is alive.
     45   const char* Print(AstNode* node);
     46   const char* PrintExpression(FunctionLiteral* program);
     47   const char* PrintProgram(FunctionLiteral* program);
     48 
     49   void Print(const char* format, ...);
     50 
     51   // Print a node to stdout.
     52   static void PrintOut(AstNode* node);
     53 
     54   // Individual nodes
     55 #define DECLARE_VISIT(type) virtual void Visit##type(type* node);
     56   AST_NODE_LIST(DECLARE_VISIT)
     57 #undef DECLARE_VISIT
     58 
     59  private:
     60   char* output_;  // output string buffer
     61   int size_;  // output_ size
     62   int pos_;  // current printing position
     63 
     64  protected:
     65   void Init();
     66   const char* Output() const { return output_; }
     67 
     68   virtual void PrintStatements(ZoneList<Statement*>* statements);
     69   void PrintLabels(ZoneStringList* labels);
     70   virtual void PrintArguments(ZoneList<Expression*>* arguments);
     71   void PrintLiteral(Handle<Object> value, bool quote);
     72   void PrintParameters(Scope* scope);
     73   void PrintDeclarations(ZoneList<Declaration*>* declarations);
     74   void PrintFunctionLiteral(FunctionLiteral* function);
     75   void PrintCaseClause(CaseClause* clause);
     76 };
     77 
     78 
     79 // Prints the AST structure
     80 class AstPrinter: public PrettyPrinter {
     81  public:
     82   AstPrinter();
     83   virtual ~AstPrinter();
     84 
     85   const char* PrintProgram(FunctionLiteral* program);
     86 
     87   // Individual nodes
     88 #define DECLARE_VISIT(type) virtual void Visit##type(type* node);
     89   AST_NODE_LIST(DECLARE_VISIT)
     90 #undef DECLARE_VISIT
     91  private:
     92   friend class IndentedScope;
     93   void PrintIndented(const char* txt);
     94   void PrintIndentedVisit(const char* s, AstNode* node);
     95 
     96   void PrintStatements(ZoneList<Statement*>* statements);
     97   void PrintDeclarations(ZoneList<Declaration*>* declarations);
     98   void PrintParameters(Scope* scope);
     99   void PrintArguments(ZoneList<Expression*>* arguments);
    100   void PrintCaseClause(CaseClause* clause);
    101   void PrintLiteralIndented(const char* info, Handle<Object> value, bool quote);
    102   void PrintLiteralWithModeIndented(const char* info,
    103                                     Variable* var,
    104                                     Handle<Object> value,
    105                                     StaticType* type,
    106                                     int num);
    107   void PrintLabelsIndented(const char* info, ZoneStringList* labels);
    108 
    109   void inc_indent() { indent_++; }
    110   void dec_indent() { indent_--; }
    111 
    112   static int indent_;
    113 };
    114 
    115 
    116 // Forward declaration of helper classes.
    117 class TagScope;
    118 class AttributesScope;
    119 
    120 // Build a C string containing a JSON representation of a function's
    121 // AST. The representation is based on JsonML (www.jsonml.org).
    122 class JsonAstBuilder: public PrettyPrinter {
    123  public:
    124   JsonAstBuilder()
    125       : indent_(0), top_tag_scope_(NULL), attributes_scope_(NULL) {
    126   }
    127   virtual ~JsonAstBuilder() {}
    128 
    129   // Controls the indentation of subsequent lines of a tag body after
    130   // the first line.
    131   static const int kTagIndentSize = 2;
    132 
    133   // Controls the indentation of subsequent lines of an attributes
    134   // blocks's body after the first line.
    135   static const int kAttributesIndentSize = 1;
    136 
    137   // Construct a JSON representation of a function literal.
    138   const char* BuildProgram(FunctionLiteral* program);
    139 
    140   // Print text indented by the current indentation level.
    141   void PrintIndented(const char* text) { Print("%*s%s", indent_, "", text); }
    142 
    143   // Change the indentation level.
    144   void increase_indent(int amount) { indent_ += amount; }
    145   void decrease_indent(int amount) { indent_ -= amount; }
    146 
    147   // The builder maintains a stack of opened AST node constructors.
    148   // Each node constructor corresponds to a JsonML tag.
    149   TagScope* tag() { return top_tag_scope_; }
    150   void set_tag(TagScope* scope) { top_tag_scope_ = scope; }
    151 
    152   // The builder maintains a pointer to the currently opened attributes
    153   // of current AST node or NULL if the attributes are not opened.
    154   AttributesScope* attributes() { return attributes_scope_; }
    155   void set_attributes(AttributesScope* scope) { attributes_scope_ = scope; }
    156 
    157   // Add an attribute to the currently opened attributes.
    158   void AddAttribute(const char* name, Handle<String> value);
    159   void AddAttribute(const char* name, const char* value);
    160   void AddAttribute(const char* name, int value);
    161   void AddAttribute(const char* name, bool value);
    162 
    163   // AST node visit functions.
    164 #define DECLARE_VISIT(type) virtual void Visit##type(type* node);
    165   AST_NODE_LIST(DECLARE_VISIT)
    166 #undef DECLARE_VISIT
    167 
    168  private:
    169   int indent_;
    170   TagScope* top_tag_scope_;
    171   AttributesScope* attributes_scope_;
    172 
    173   // Utility function used by AddAttribute implementations.
    174   void AddAttributePrefix(const char* name);
    175 };
    176 
    177 
    178 // The JSON AST builder keeps a stack of open element tags (AST node
    179 // constructors from the current iteration point to the root of the
    180 // AST).  TagScope is a helper class to manage the opening and closing
    181 // of tags, the indentation of their bodies, and comma separating their
    182 // contents.
    183 class TagScope BASE_EMBEDDED {
    184  public:
    185   TagScope(JsonAstBuilder* builder, const char* name);
    186   ~TagScope();
    187 
    188   void use() { has_body_ = true; }
    189 
    190  private:
    191   JsonAstBuilder* builder_;
    192   TagScope* next_;
    193   bool has_body_;
    194 };
    195 
    196 
    197 // AttributesScope is a helper class to manage the opening and closing
    198 // of attribute blocks, the indentation of their bodies, and comma
    199 // separating their contents. JsonAstBuilder::AddAttribute adds an
    200 // attribute to the currently open AttributesScope. They cannot be
    201 // nested so the builder keeps an optional single scope rather than a
    202 // stack.
    203 class AttributesScope BASE_EMBEDDED {
    204  public:
    205   explicit AttributesScope(JsonAstBuilder* builder);
    206   ~AttributesScope();
    207 
    208   bool is_used() { return attribute_count_ > 0; }
    209   void use() { ++attribute_count_; }
    210 
    211  private:
    212   JsonAstBuilder* builder_;
    213   int attribute_count_;
    214 };
    215 
    216 #endif  // DEBUG
    217 
    218 } }  // namespace v8::internal
    219 
    220 #endif  // V8_PRETTYPRINTER_H_
    221