Chromium Code Reviews| Index: src/ast.cc |
| diff --git a/src/ast.cc b/src/ast.cc |
| index 2f21d926c396aec37a05ff4335f82342aa2339fb..5bc68810da773eea493678443d5711b92bbc4208 100644 |
| --- a/src/ast.cc |
| +++ b/src/ast.cc |
| @@ -29,6 +29,7 @@ |
| #include "ast.h" |
| #include "scopes.h" |
| +#include "string-stream.h" |
| namespace v8 { namespace internal { |
| @@ -179,4 +180,156 @@ void Visitor::VisitExpressions(ZoneList<Expression*>* expressions) { |
| } |
| +// ---------------------------------------------------------------------------- |
| +// Regular expressions |
| + |
| +#define MAKE_ACCEPT(Name) \ |
| + void* RegExp##Name::Accept(RegExpVisitor* visitor, void* data) { \ |
| + return visitor->Visit##Name(this, data); \ |
| + } |
| +FOR_EACH_REG_EXP_NODE_TYPE(MAKE_ACCEPT) |
| +#undef MAKE_ACCEPT |
| + |
| + |
| +RegExpEmpty RegExpEmpty::kInstance; |
| + |
| + |
| +class RegExpUnparser: public RegExpVisitor { |
|
Lasse Reichstein
2008/10/27 13:12:58
Would be nice with a comment describing the syntax
Christian Plesner Hansen
2008/10/27 18:57:02
I can't be bothered to write the full format but I
|
| + public: |
| + RegExpUnparser(); |
| + void VisitCharacterRange(CharacterRange that); |
| + SmartPointer<char> ToString() { return stream_.ToCString(); } |
| +#define MAKE_CASE(Name) virtual void* Visit##Name(RegExp##Name*, void* data); |
| + FOR_EACH_REG_EXP_NODE_TYPE(MAKE_CASE) |
| +#undef MAKE_CASE |
| + private: |
| + StringStream* stream() { return &stream_; } |
| + HeapStringAllocator alloc_; |
| + StringStream stream_; |
| +}; |
| + |
| + |
| +RegExpUnparser::RegExpUnparser() : stream_(&alloc_) { |
| +} |
| + |
| + |
| +void* RegExpUnparser::VisitDisjunction(RegExpDisjunction* that, void* data) { |
| + stream()->Add("(|"); |
| + for (int i = 0; i < that->nodes()->length(); i++) { |
| + stream()->Add(" "); |
| + that->nodes()->at(i)->Accept(this, data); |
| + } |
| + stream()->Add(")"); |
| + return NULL; |
| +} |
| + |
| + |
| +void* RegExpUnparser::VisitAlternative(RegExpAlternative* that, void* data) { |
| + stream()->Add("(:"); |
| + for (int i = 0; i < that->nodes()->length(); i++) { |
| + stream()->Add(" "); |
| + that->nodes()->at(i)->Accept(this, data); |
| + } |
| + stream()->Add(")"); |
| + return NULL; |
| +} |
| + |
| + |
| +void RegExpUnparser::VisitCharacterRange(CharacterRange that) { |
| + if (that.is_special()) { |
| + stream()->Add("&%c", that.from()); |
| + } else if (that.IsSingleton()) { |
| + stream()->Add("%c", that.from()); |
| + } else { |
| + stream()->Add("%c-%c", that.from(), that.to()); |
| + } |
| +} |
| + |
| + |
| + |
| +void* RegExpUnparser::VisitCharacterClass(RegExpCharacterClass* that, |
| + void* data) { |
| + if (that->is_negated()) |
| + stream()->Add("^"); |
|
Lasse Reichstein
2008/10/27 13:12:58
Needs sqiggly quotes around the then-statement or
Christian Plesner Hansen
2008/10/27 18:57:02
Nope, the style guide allows both forms. "In gene
|
| + stream()->Add("["); |
| + bool first = true; |
| + for (int i = 0; i < that->ranges()->length(); i++) { |
| + if (first) first = false; |
|
Lasse Reichstein
2008/10/27 13:12:58
"first" is equivalent to "i == 0", so it can be om
Christian Plesner Hansen
2008/10/27 18:57:02
Good point.
|
| + else stream()->Add(" "); |
| + VisitCharacterRange(that->ranges()->at(i)); |
| + } |
| + stream()->Add("]"); |
| + return NULL; |
| +} |
| + |
| + |
| +void* RegExpUnparser::VisitAssertion(RegExpAssertion* that, void* data) { |
| + switch (that->type()) { |
| + case RegExpAssertion::START: |
| + stream()->Add("@^"); |
| + break; |
| + case RegExpAssertion::END: |
| + stream()->Add("@$"); |
| + break; |
| + case RegExpAssertion::BOUNDARY: |
| + stream()->Add("@b"); |
| + break; |
| + case RegExpAssertion::NON_BOUNDARY: |
| + stream()->Add("@B"); |
| + break; |
| + } |
| + return NULL; |
| +} |
| + |
| + |
| +void* RegExpUnparser::VisitAtom(RegExpAtom* that, void* data) { |
| + stream()->Add("'%w'", that->data()); |
| + return NULL; |
| +} |
| + |
| + |
| +void* RegExpUnparser::VisitQuantifier(RegExpQuantifier* that, void* data) { |
| + stream()->Add("(# %i ", that->min()); |
| + if (that->max() == RegExpQuantifier::kInfinity) { |
| + stream()->Add("- "); |
| + } else { |
| + stream()->Add("%i ", that->max()); |
| + } |
| + stream()->Add(that->is_greedy() ? "g " : "n "); |
| + that->body()->Accept(this, data); |
| + stream()->Add(")"); |
| + return NULL; |
| +} |
| + |
| + |
| +void* RegExpUnparser::VisitCapture(RegExpCapture* that, void* data) { |
| + stream()->Add("(^ "); |
| + that->body()->Accept(this, data); |
| + stream()->Add(")"); |
| + return NULL; |
| +} |
| + |
| + |
| +void* RegExpUnparser::VisitLookahead(RegExpLookahead* that, void* data) { |
| + stream()->Add("(-> "); |
| + stream()->Add(that->is_positive() ? "+ " : "- "); |
| + that->body()->Accept(this, data); |
| + stream()->Add(")"); |
| + return NULL; |
| +} |
| + |
| + |
| +void* RegExpUnparser::VisitEmpty(RegExpEmpty* that, void* data) { |
| + stream()->Put('%'); |
| + return NULL; |
| +} |
| + |
| + |
| +SmartPointer<char> RegExpTree::ToString() { |
| + RegExpUnparser unparser; |
| + Accept(&unparser, NULL); |
| + return unparser.ToString(); |
| +} |
| + |
| + |
| } } // namespace v8::internal |