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