ast.cc revision e46be819fca9468a0cd4e74859ce0f778eb8ca60
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2006-2008 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "ast.h"
31d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "parser.h"
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "scopes.h"
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "string-stream.h"
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockVariableProxySentinel VariableProxySentinel::this_proxy_(true);
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockVariableProxySentinel VariableProxySentinel::identifier_proxy_(false);
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockValidLeftHandSideSentinel ValidLeftHandSideSentinel::instance_;
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockProperty Property::this_property_(VariableProxySentinel::this_proxy(), NULL, 0);
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCall Call::sentinel_(NULL, NULL, 0);
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// All the Accept member functions for each syntax tree node type.
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define DECL_ACCEPT(type)                \
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void type::Accept(AstVisitor* v) {        \
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (v->CheckStackOverflow()) return; \
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v->Visit##type(this);                \
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockAST_NODE_LIST(DECL_ACCEPT)
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef DECL_ACCEPT
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Implementation of other node functionality.
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockVariableProxy::VariableProxy(Handle<String> name,
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                             bool is_this,
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                             bool inside_with)
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  : name_(name),
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var_(NULL),
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    is_this_(is_this),
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    inside_with_(inside_with) {
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // names must be canonicalized for fast equality checks
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(name->IsSymbol());
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // at least one access, otherwise no need for a VariableProxy
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var_uses_.RecordRead(1);
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockVariableProxy::VariableProxy(bool is_this)
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  : is_this_(is_this) {
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid VariableProxy::BindTo(Variable* var) {
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(var_ == NULL);  // must be bound only once
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(var != NULL);  // must bind
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((is_this() && var->is_this()) || name_.is_identical_to(var->name()));
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Ideally CONST-ness should match. However, this is very hard to achieve
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // because we don't know the exact semantics of conflicting (const and
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // non-const) multiple variable declarations, const vars introduced via
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // eval() etc.  Const-ness and variable declarations are a complete mess
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // in JS. Sigh...
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var_ = var;
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var->var_uses()->RecordUses(&var_uses_);
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var->obj_uses()->RecordUses(&obj_uses_);
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockToken::Value Assignment::binary_op() const {
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (op_) {
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::ASSIGN_BIT_OR: return Token::BIT_OR;
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::ASSIGN_BIT_XOR: return Token::BIT_XOR;
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::ASSIGN_BIT_AND: return Token::BIT_AND;
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::ASSIGN_SHL: return Token::SHL;
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::ASSIGN_SAR: return Token::SAR;
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::ASSIGN_SHR: return Token::SHR;
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::ASSIGN_ADD: return Token::ADD;
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::ASSIGN_SUB: return Token::SUB;
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::ASSIGN_MUL: return Token::MUL;
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::ASSIGN_DIV: return Token::DIV;
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::ASSIGN_MOD: return Token::MOD;
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default: UNREACHABLE();
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Token::ILLEGAL;
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool FunctionLiteral::AllowsLazyCompilation() {
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return scope()->AllowsLazyCompilation();
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObjectLiteral::Property::Property(Literal* key, Expression* value) {
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  key_ = key;
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value_ = value;
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Object* k = *key->handle();
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (k->IsSymbol() && Heap::Proto_symbol()->Equals(String::cast(k))) {
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    kind_ = PROTOTYPE;
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (value_->AsMaterializedLiteral() != NULL) {
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    kind_ = MATERIALIZED_LITERAL;
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (value_->AsLiteral() != NULL) {
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    kind_ = CONSTANT;
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    kind_ = COMPUTED;
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObjectLiteral::Property::Property(bool is_getter, FunctionLiteral* value) {
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  key_ = new Literal(value->name());
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  value_ = value;
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  kind_ = is_getter ? GETTER : SETTER;
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
142d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockbool ObjectLiteral::Property::IsCompileTimeValue() {
143d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return kind_ == CONSTANT ||
144d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      (kind_ == MATERIALIZED_LITERAL &&
145d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block       CompileTimeValue::IsCompileTimeValue(value_));
146d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
147d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
148d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool ObjectLiteral::IsValidJSON() {
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int length = properties()->length();
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < length; i++) {
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Property* prop = properties()->at(i);
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!prop->value()->IsValidJSON())
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return false;
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool ArrayLiteral::IsValidJSON() {
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int length = values()->length();
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < length; i++) {
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!values()->at(i)->IsValidJSON())
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return false;
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid TargetCollector::AddTarget(BreakTarget* target) {
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Add the label to the collector, but discard duplicates.
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int length = targets_->length();
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < length; i++) {
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (targets_->at(i) == target) return;
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  targets_->Add(target);
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Implementation of AstVisitor
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid AstVisitor::VisitDeclarations(ZoneList<Declaration*>* declarations) {
1853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (int i = 0; i < declarations->length(); i++) {
1863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    Visit(declarations->at(i));
1873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
1883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
1893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid AstVisitor::VisitStatements(ZoneList<Statement*>* statements) {
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < statements->length(); i++) {
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Visit(statements->at(i));
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid AstVisitor::VisitExpressions(ZoneList<Expression*>* expressions) {
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < expressions->length(); i++) {
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The variable statement visiting code may pass NULL expressions
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // to this code. Maybe this should be handled by introducing an
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // undefined expression or literal?  Revisit this code if this
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // changes
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Expression* expression = expressions->at(i);
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (expression != NULL) Visit(expression);
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Regular expressions
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define MAKE_ACCEPT(Name)                                            \
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void* RegExp##Name::Accept(RegExpVisitor* visitor, void* data) {   \
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return visitor->Visit##Name(this, data);                         \
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFOR_EACH_REG_EXP_TREE_TYPE(MAKE_ACCEPT)
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef MAKE_ACCEPT
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define MAKE_TYPE_CASE(Name)                                         \
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RegExp##Name* RegExpTree::As##Name() {                             \
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return NULL;                                                     \
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }                                                                  \
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool RegExpTree::Is##Name() { return false; }
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFOR_EACH_REG_EXP_TREE_TYPE(MAKE_TYPE_CASE)
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef MAKE_TYPE_CASE
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define MAKE_TYPE_CASE(Name)                                        \
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RegExp##Name* RegExp##Name::As##Name() {                          \
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return this;                                                    \
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }                                                                 \
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool RegExp##Name::Is##Name() { return true; }
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFOR_EACH_REG_EXP_TREE_TYPE(MAKE_TYPE_CASE)
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef MAKE_TYPE_CASE
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpEmpty RegExpEmpty::kInstance;
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic Interval ListCaptureRegisters(ZoneList<RegExpTree*>* children) {
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Interval result = Interval::Empty();
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < children->length(); i++)
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    result = result.Union(children->at(i)->CaptureRegisters());
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return result;
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockInterval RegExpAlternative::CaptureRegisters() {
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return ListCaptureRegisters(nodes());
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockInterval RegExpDisjunction::CaptureRegisters() {
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return ListCaptureRegisters(alternatives());
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockInterval RegExpLookahead::CaptureRegisters() {
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return body()->CaptureRegisters();
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockInterval RegExpCapture::CaptureRegisters() {
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Interval self(StartRegister(index()), EndRegister(index()));
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return self.Union(body()->CaptureRegisters());
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockInterval RegExpQuantifier::CaptureRegisters() {
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return body()->CaptureRegisters();
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool RegExpAssertion::IsAnchored() {
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return type() == RegExpAssertion::START_OF_INPUT;
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool RegExpAlternative::IsAnchored() {
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ZoneList<RegExpTree*>* nodes = this->nodes();
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < nodes->length(); i++) {
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RegExpTree* node = nodes->at(i);
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (node->IsAnchored()) { return true; }
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (node->max_match() > 0) { return false; }
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return false;
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool RegExpDisjunction::IsAnchored() {
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ZoneList<RegExpTree*>* alternatives = this->alternatives();
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < alternatives->length(); i++) {
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!alternatives->at(i)->IsAnchored())
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return false;
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool RegExpLookahead::IsAnchored() {
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return is_positive() && body()->IsAnchored();
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool RegExpCapture::IsAnchored() {
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return body()->IsAnchored();
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Convert regular expression trees to a simple sexp representation.
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This representation should be different from the input grammar
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// in as many cases as possible, to make it more difficult for incorrect
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// parses to look as correct ones which is likely if the input and
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// output formats are alike.
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass RegExpUnparser: public RegExpVisitor {
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RegExpUnparser();
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void VisitCharacterRange(CharacterRange that);
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SmartPointer<const char> ToString() { return stream_.ToCString(); }
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define MAKE_CASE(Name) virtual void* Visit##Name(RegExp##Name*, void* data);
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  FOR_EACH_REG_EXP_TREE_TYPE(MAKE_CASE)
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef MAKE_CASE
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StringStream* stream() { return &stream_; }
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  HeapStringAllocator alloc_;
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StringStream stream_;
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpUnparser::RegExpUnparser() : stream_(&alloc_) {
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid* RegExpUnparser::VisitDisjunction(RegExpDisjunction* that, void* data) {
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  stream()->Add("(|");
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i <  that->alternatives()->length(); i++) {
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    stream()->Add(" ");
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    that->alternatives()->at(i)->Accept(this, data);
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  stream()->Add(")");
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return NULL;
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid* RegExpUnparser::VisitAlternative(RegExpAlternative* that, void* data) {
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  stream()->Add("(:");
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i <  that->nodes()->length(); i++) {
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    stream()->Add(" ");
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    that->nodes()->at(i)->Accept(this, data);
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  stream()->Add(")");
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return NULL;
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpUnparser::VisitCharacterRange(CharacterRange that) {
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  stream()->Add("%k", that.from());
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!that.IsSingleton()) {
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    stream()->Add("-%k", that.to());
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid* RegExpUnparser::VisitCharacterClass(RegExpCharacterClass* that,
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                          void* data) {
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (that->is_negated())
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    stream()->Add("^");
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  stream()->Add("[");
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < that->ranges()->length(); i++) {
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (i > 0) stream()->Add(" ");
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    VisitCharacterRange(that->ranges()->at(i));
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  stream()->Add("]");
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return NULL;
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid* RegExpUnparser::VisitAssertion(RegExpAssertion* that, void* data) {
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (that->type()) {
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case RegExpAssertion::START_OF_INPUT:
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      stream()->Add("@^i");
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case RegExpAssertion::END_OF_INPUT:
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      stream()->Add("@$i");
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case RegExpAssertion::START_OF_LINE:
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      stream()->Add("@^l");
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case RegExpAssertion::END_OF_LINE:
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      stream()->Add("@$l");
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       break;
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case RegExpAssertion::BOUNDARY:
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      stream()->Add("@b");
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case RegExpAssertion::NON_BOUNDARY:
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      stream()->Add("@B");
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return NULL;
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid* RegExpUnparser::VisitAtom(RegExpAtom* that, void* data) {
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  stream()->Add("'");
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Vector<const uc16> chardata = that->data();
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < chardata.length(); i++) {
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    stream()->Add("%k", chardata[i]);
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  stream()->Add("'");
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return NULL;
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid* RegExpUnparser::VisitText(RegExpText* that, void* data) {
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (that->elements()->length() == 1) {
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    that->elements()->at(0).data.u_atom->Accept(this, data);
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    stream()->Add("(!");
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int i = 0; i < that->elements()->length(); i++) {
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      stream()->Add(" ");
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      that->elements()->at(i).data.u_atom->Accept(this, data);
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    stream()->Add(")");
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return NULL;
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid* RegExpUnparser::VisitQuantifier(RegExpQuantifier* that, void* data) {
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  stream()->Add("(# %i ", that->min());
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (that->max() == RegExpTree::kInfinity) {
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    stream()->Add("- ");
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    stream()->Add("%i ", that->max());
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
436e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  stream()->Add(that->is_greedy() ? "g " : that->is_possessive() ? "p " : "n ");
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  that->body()->Accept(this, data);
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  stream()->Add(")");
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return NULL;
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid* RegExpUnparser::VisitCapture(RegExpCapture* that, void* data) {
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  stream()->Add("(^ ");
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  that->body()->Accept(this, data);
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  stream()->Add(")");
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return NULL;
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid* RegExpUnparser::VisitLookahead(RegExpLookahead* that, void* data) {
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  stream()->Add("(-> ");
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  stream()->Add(that->is_positive() ? "+ " : "- ");
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  that->body()->Accept(this, data);
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  stream()->Add(")");
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return NULL;
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid* RegExpUnparser::VisitBackReference(RegExpBackReference* that,
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                         void* data) {
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  stream()->Add("(<- %i)", that->index());
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return NULL;
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid* RegExpUnparser::VisitEmpty(RegExpEmpty* that, void* data) {
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  stream()->Put('%');
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return NULL;
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockSmartPointer<const char> RegExpTree::ToString() {
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RegExpUnparser unparser;
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Accept(&unparser, NULL);
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return unparser.ToString();
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpDisjunction::RegExpDisjunction(ZoneList<RegExpTree*>* alternatives)
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    : alternatives_(alternatives) {
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(alternatives->length() > 1);
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RegExpTree* first_alternative = alternatives->at(0);
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  min_match_ = first_alternative->min_match();
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  max_match_ = first_alternative->max_match();
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 1; i < alternatives->length(); i++) {
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RegExpTree* alternative = alternatives->at(i);
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    min_match_ = Min(min_match_, alternative->min_match());
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    max_match_ = Max(max_match_, alternative->max_match());
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpAlternative::RegExpAlternative(ZoneList<RegExpTree*>* nodes)
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    : nodes_(nodes) {
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(nodes->length() > 1);
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  min_match_ = 0;
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  max_match_ = 0;
499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < nodes->length(); i++) {
500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RegExpTree* node = nodes->at(i);
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    min_match_ += node->min_match();
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int node_max_match = node->max_match();
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (kInfinity - max_match_ < node_max_match) {
504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      max_match_ = kInfinity;
505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      max_match_ += node->max_match();
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
513