Home | History | Annotate | Download | only in src
      1 // Copyright 2011 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   virtual void VisitSlot(Slot* node);
     55   // Individual nodes
     56 #define DECLARE_VISIT(type) virtual void Visit##type(type* node);
     57   AST_NODE_LIST(DECLARE_VISIT)
     58 #undef DECLARE_VISIT
     59 
     60  private:
     61   char* output_;  // output string buffer
     62   int size_;  // output_ size
     63   int pos_;  // current printing position
     64 
     65  protected:
     66   void Init();
     67   const char* Output() const { return output_; }
     68 
     69   virtual void PrintStatements(ZoneList<Statement*>* statements);
     70   void PrintLabels(ZoneStringList* labels);
     71   virtual void PrintArguments(ZoneList<Expression*>* arguments);
     72   void PrintLiteral(Handle<Object> value, bool quote);
     73   void PrintParameters(Scope* scope);
     74   void PrintDeclarations(ZoneList<Declaration*>* declarations);
     75   void PrintFunctionLiteral(FunctionLiteral* function);
     76   void PrintCaseClause(CaseClause* clause);
     77 };
     78 
     79 
     80 // Prints the AST structure
     81 class AstPrinter: public PrettyPrinter {
     82  public:
     83   AstPrinter();
     84   virtual ~AstPrinter();
     85 
     86   const char* PrintProgram(FunctionLiteral* program);
     87 
     88   // Individual nodes
     89   virtual void VisitSlot(Slot* node);
     90 #define DECLARE_VISIT(type) virtual void Visit##type(type* node);
     91   AST_NODE_LIST(DECLARE_VISIT)
     92 #undef DECLARE_VISIT
     93 
     94  private:
     95   friend class IndentedScope;
     96   void PrintIndented(const char* txt);
     97   void PrintIndentedVisit(const char* s, AstNode* node);
     98 
     99   void PrintStatements(ZoneList<Statement*>* statements);
    100   void PrintDeclarations(ZoneList<Declaration*>* declarations);
    101   void PrintParameters(Scope* scope);
    102   void PrintArguments(ZoneList<Expression*>* arguments);
    103   void PrintCaseClause(CaseClause* clause);
    104   void PrintLiteralIndented(const char* info, Handle<Object> value, bool quote);
    105   void PrintLiteralWithModeIndented(const char* info,
    106                                     Variable* var,
    107                                     Handle<Object> value);
    108   void PrintLabelsIndented(const char* info, ZoneStringList* labels);
    109 
    110   void inc_indent() { indent_++; }
    111   void dec_indent() { indent_--; }
    112 
    113   int indent_;
    114 };
    115 
    116 
    117 // Forward declaration of helper classes.
    118 class TagScope;
    119 class AttributesScope;
    120 
    121 // Build a C string containing a JSON representation of a function's
    122 // AST. The representation is based on JsonML (www.jsonml.org).
    123 class JsonAstBuilder: public PrettyPrinter {
    124  public:
    125   JsonAstBuilder()
    126       : indent_(0), top_tag_scope_(NULL), attributes_scope_(NULL) {
    127   }
    128   virtual ~JsonAstBuilder() {}
    129 
    130   // Controls the indentation of subsequent lines of a tag body after
    131   // the first line.
    132   static const int kTagIndentSize = 2;
    133 
    134   // Controls the indentation of subsequent lines of an attributes
    135   // blocks's body after the first line.
    136   static const int kAttributesIndentSize = 1;
    137 
    138   // Construct a JSON representation of a function literal.
    139   const char* BuildProgram(FunctionLiteral* program);
    140 
    141   // Print text indented by the current indentation level.
    142   void PrintIndented(const char* text) { Print("%*s%s", indent_, "", text); }
    143 
    144   // Change the indentation level.
    145   void increase_indent(int amount) { indent_ += amount; }
    146   void decrease_indent(int amount) { indent_ -= amount; }
    147 
    148   // The builder maintains a stack of opened AST node constructors.
    149   // Each node constructor corresponds to a JsonML tag.
    150   TagScope* tag() { return top_tag_scope_; }
    151   void set_tag(TagScope* scope) { top_tag_scope_ = scope; }
    152 
    153   // The builder maintains a pointer to the currently opened attributes
    154   // of current AST node or NULL if the attributes are not opened.
    155   AttributesScope* attributes() { return attributes_scope_; }
    156   void set_attributes(AttributesScope* scope) { attributes_scope_ = scope; }
    157 
    158   // Add an attribute to the currently opened attributes.
    159   void AddAttribute(const char* name, Handle<String> value);
    160   void AddAttribute(const char* name, const char* value);
    161   void AddAttribute(const char* name, int value);
    162   void AddAttribute(const char* name, bool value);
    163 
    164   // AST node visit functions.
    165   virtual void VisitSlot(Slot* node);
    166 #define DECLARE_VISIT(type) virtual void Visit##type(type* node);
    167   AST_NODE_LIST(DECLARE_VISIT)
    168 #undef DECLARE_VISIT
    169 
    170  private:
    171   int indent_;
    172   TagScope* top_tag_scope_;
    173   AttributesScope* attributes_scope_;
    174 
    175   // Utility function used by AddAttribute implementations.
    176   void AddAttributePrefix(const char* name);
    177 };
    178 
    179 
    180 // The JSON AST builder keeps a stack of open element tags (AST node
    181 // constructors from the current iteration point to the root of the
    182 // AST).  TagScope is a helper class to manage the opening and closing
    183 // of tags, the indentation of their bodies, and comma separating their
    184 // contents.
    185 class TagScope BASE_EMBEDDED {
    186  public:
    187   TagScope(JsonAstBuilder* builder, const char* name);
    188   ~TagScope();
    189 
    190   void use() { has_body_ = true; }
    191 
    192  private:
    193   JsonAstBuilder* builder_;
    194   TagScope* next_;
    195   bool has_body_;
    196 };
    197 
    198 
    199 // AttributesScope is a helper class to manage the opening and closing
    200 // of attribute blocks, the indentation of their bodies, and comma
    201 // separating their contents. JsonAstBuilder::AddAttribute adds an
    202 // attribute to the currently open AttributesScope. They cannot be
    203 // nested so the builder keeps an optional single scope rather than a
    204 // stack.
    205 class AttributesScope BASE_EMBEDDED {
    206  public:
    207   explicit AttributesScope(JsonAstBuilder* builder);
    208   ~AttributesScope();
    209 
    210   bool is_used() { return attribute_count_ > 0; }
    211   void use() { ++attribute_count_; }
    212 
    213  private:
    214   JsonAstBuilder* builder_;
    215   int attribute_count_;
    216 };
    217 
    218 #endif  // DEBUG
    219 
    220 } }  // namespace v8::internal
    221 
    222 #endif  // V8_PRETTYPRINTER_H_
    223