Chromium Code Reviews| Index: src/ast.cc |
| =================================================================== |
| --- src/ast.cc (revision 830) |
| +++ src/ast.cc (working copy) |
| @@ -29,6 +29,7 @@ |
| #include "ast.h" |
| #include "scopes.h" |
| +#include "string-stream.h" |
| namespace v8 { namespace internal { |
| @@ -179,4 +180,204 @@ |
| } |
| +// ---------------------------------------------------------------------------- |
| +// Regular expressions |
| + |
| +#define MAKE_ACCEPT(Name) \ |
| + void* RegExp##Name::Accept(RegExpVisitor* visitor, void* data) { \ |
| + return visitor->Visit##Name(this, data); \ |
| + } |
| +FOR_EACH_REG_EXP_TREE_TYPE(MAKE_ACCEPT) |
| +#undef MAKE_ACCEPT |
| + |
| +#define MAKE_TYPE_CASE(Name) \ |
| + RegExp##Name* RegExpTree::As##Name() { \ |
| + return NULL; \ |
| + } \ |
| + bool RegExpTree::Is##Name() { return false; } |
| + FOR_EACH_REG_EXP_TREE_TYPE(MAKE_TYPE_CASE) |
|
Mads Ager (chromium)
2008/11/25 21:09:41
Do not indent this line.
Erik Corry
2008/11/26 12:18:36
Fixed.
|
| +#undef MAKE_TYPE_CASE |
| + |
| +#define MAKE_TYPE_CASE(Name) \ |
| + RegExp##Name* RegExp##Name::As##Name() { \ |
| + return this; \ |
| + } \ |
| + bool RegExp##Name::Is##Name() { return true; } |
| +FOR_EACH_REG_EXP_TREE_TYPE(MAKE_TYPE_CASE) |
| +#undef MAKE_TYPE_CASE |
| + |
| +RegExpEmpty RegExpEmpty::kInstance; |
| + |
| + |
| +// Convert regular expression trees to a simple sexp representation. |
| +// This representation should be different from the input grammar |
| +// in as many cases as possible, to make it more difficult for incorrect |
| +// parses to look as correct ones which is likely if the input and |
| +// output formats are alike. |
| +class RegExpUnparser: public RegExpVisitor { |
| + public: |
| + RegExpUnparser(); |
| + void VisitCharacterRange(CharacterRange that); |
| + SmartPointer<const char> ToString() { return stream_.ToCString(); } |
| +#define MAKE_CASE(Name) virtual void* Visit##Name(RegExp##Name*, void* data); |
| + FOR_EACH_REG_EXP_TREE_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->alternatives()->length(); i++) { |
| + stream()->Add(" "); |
| + that->alternatives()->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) { |
| + stream()->Add("%k", that.from()); |
| + if (!that.IsSingleton()) { |
| + stream()->Add("-%k", that.to()); |
| + } |
| +} |
| + |
| + |
| + |
| +void* RegExpUnparser::VisitCharacterClass(RegExpCharacterClass* that, |
| + void* data) { |
| + if (that->is_negated()) |
| + stream()->Add("^"); |
| + stream()->Add("["); |
| + for (int i = 0; i < that->ranges()->length(); i++) { |
| + if (i > 0) stream()->Add(" "); |
| + VisitCharacterRange(that->ranges()->at(i)); |
| + } |
| + stream()->Add("]"); |
| + return NULL; |
| +} |
| + |
| + |
| +void* RegExpUnparser::VisitAssertion(RegExpAssertion* that, void* data) { |
| + switch (that->type()) { |
| + case RegExpAssertion::START_OF_INPUT: |
| + stream()->Add("@^i"); |
| + break; |
| + case RegExpAssertion::END_OF_INPUT: |
| + stream()->Add("@$i"); |
| + break; |
| + case RegExpAssertion::START_OF_LINE: |
| + stream()->Add("@^l"); |
| + break; |
| + case RegExpAssertion::END_OF_LINE: |
| + stream()->Add("@$l"); |
| + 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("'"); |
| + Vector<const uc16> chardata = that->data(); |
| + for (int i = 0; i < chardata.length(); i++) { |
| + stream()->Add("%k", chardata[i]); |
| + } |
| + stream()->Add("'"); |
| + return NULL; |
| +} |
| + |
| + |
| +void* RegExpUnparser::VisitText(RegExpText* that, void* data) { |
| + if (that->elements()->length() == 1) { |
| + that->elements()->at(0).data.u_atom->Accept(this, data); |
| + } else { |
| + stream()->Add("(!"); |
| + for (int i = 0; i < that->elements()->length(); i++) { |
| + stream()->Add(" "); |
| + that->elements()->at(i).data.u_atom->Accept(this, data); |
| + } |
| + stream()->Add(")"); |
| + } |
| + 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::VisitBackReference(RegExpBackReference* that, |
| + void* data) { |
| + stream()->Add("(<- %i)", that->index()); |
| + return NULL; |
| +} |
| + |
| + |
| +void* RegExpUnparser::VisitEmpty(RegExpEmpty* that, void* data) { |
| + stream()->Put('%'); |
| + return NULL; |
| +} |
| + |
| + |
| +SmartPointer<const char> RegExpTree::ToString() { |
| + RegExpUnparser unparser; |
| + Accept(&unparser, NULL); |
| + return unparser.ToString(); |
| +} |
| + |
| + |
| } } // namespace v8::internal |