| OLD | NEW |
| 1 // Copyright 2007 The RE2 Authors. All Rights Reserved. | 1 // Copyright 2007 The RE2 Authors. All Rights Reserved. |
| 2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
| 3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 // Compile regular expression to Prog. | 5 // Compile regular expression to Prog. |
| 6 // | 6 // |
| 7 // Prog and Inst are defined in prog.h. | 7 // Prog and Inst are defined in prog.h. |
| 8 // This file's external interface is just Regexp::CompileToProg. | 8 // This file's external interface is just Regexp::CompileToProg. |
| 9 // The Compiler class defined in this file is private. | 9 // The Compiler class defined in this file is private. |
| 10 | 10 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 103 | 103 |
| 104 // Compiled program fragment. | 104 // Compiled program fragment. |
| 105 struct Frag { | 105 struct Frag { |
| 106 uint32 begin; | 106 uint32 begin; |
| 107 PatchList end; | 107 PatchList end; |
| 108 | 108 |
| 109 Frag() : begin(0) { end.p = 0; } // needed so Frag can go in vector | 109 Frag() : begin(0) { end.p = 0; } // needed so Frag can go in vector |
| 110 Frag(uint32 begin, PatchList end) : begin(begin), end(end) {} | 110 Frag(uint32 begin, PatchList end) : begin(begin), end(end) {} |
| 111 }; | 111 }; |
| 112 | 112 |
| 113 static Frag kNullFrag; | 113 static Frag NullFrag() { |
| 114 return Frag(); |
| 115 } |
| 114 | 116 |
| 115 // Input encodings. | 117 // Input encodings. |
| 116 enum Encoding { | 118 enum Encoding { |
| 117 kEncodingUTF8 = 1, // UTF-8 (0-10FFFF) | 119 kEncodingUTF8 = 1, // UTF-8 (0-10FFFF) |
| 118 kEncodingLatin1, // Latin1 (0-FF) | 120 kEncodingLatin1, // Latin1 (0-FF) |
| 119 }; | 121 }; |
| 120 | 122 |
| 121 class Compiler : public Regexp::Walker<Frag> { | 123 class Compiler : public Regexp::Walker<Frag> { |
| 122 public: | 124 public: |
| 123 explicit Compiler(); | 125 explicit Compiler(); |
| (...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 581 // Four-byte | 583 // Four-byte |
| 582 { 4, 0x90, 0xBF, }, // 6: 90-BF 80-BF 80-BF | 584 { 4, 0x90, 0xBF, }, // 6: 90-BF 80-BF 80-BF |
| 583 { 6, 0xF0, 0xF0, }, // 7: F0 90-BF 80-BF 80-BF* | 585 { 6, 0xF0, 0xF0, }, // 7: F0 90-BF 80-BF 80-BF* |
| 584 { 4, 0x80, 0xBF, }, // 8: 80-BF 80-BF 80-BF | 586 { 4, 0x80, 0xBF, }, // 8: 80-BF 80-BF 80-BF |
| 585 { 8, 0xF1, 0xF3, }, // 9: F1-F3 80-BF 80-BF 80-BF* | 587 { 8, 0xF1, 0xF3, }, // 9: F1-F3 80-BF 80-BF 80-BF* |
| 586 { 4, 0x80, 0x8F, }, // 10: 80-8F 80-BF 80-BF | 588 { 4, 0x80, 0x8F, }, // 10: 80-8F 80-BF 80-BF |
| 587 { 10, 0xF4, 0xF4, }, // 11: F4 80-8F 80-BF 80-BF* | 589 { 10, 0xF4, 0xF4, }, // 11: F4 80-8F 80-BF 80-BF* |
| 588 }; | 590 }; |
| 589 | 591 |
| 590 void Compiler::Add_80_10ffff() { | 592 void Compiler::Add_80_10ffff() { |
| 591 int inst[arraysize(prog_80_10ffff)]; | 593 int inst[arraysize(prog_80_10ffff)] = { 0 }; // does not need to be initialize
d; silences gcc warning |
| 592 for (int i = 0; i < arraysize(prog_80_10ffff); i++) { | 594 for (int i = 0; i < arraysize(prog_80_10ffff); i++) { |
| 593 const ByteRangeProg& p = prog_80_10ffff[i]; | 595 const ByteRangeProg& p = prog_80_10ffff[i]; |
| 594 int next = 0; | 596 int next = 0; |
| 595 if (p.next >= 0) | 597 if (p.next >= 0) |
| 596 next = inst[p.next]; | 598 next = inst[p.next]; |
| 597 inst[i] = UncachedRuneByteSuffix(p.lo, p.hi, false, next); | 599 inst[i] = UncachedRuneByteSuffix(p.lo, p.hi, false, next); |
| 598 if ((p.lo & 0xC0) != 0x80) | 600 if ((p.lo & 0xC0) != 0x80) |
| 599 AddSuffix(inst[i]); | 601 AddSuffix(inst[i]); |
| 600 } | 602 } |
| 601 } | 603 } |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 676 failed_ = true; | 678 failed_ = true; |
| 677 return NoMatch(); | 679 return NoMatch(); |
| 678 } | 680 } |
| 679 | 681 |
| 680 // Called before traversing a node's children during the walk. | 682 // Called before traversing a node's children during the walk. |
| 681 Frag Compiler::PreVisit(Regexp* re, Frag, bool* stop) { | 683 Frag Compiler::PreVisit(Regexp* re, Frag, bool* stop) { |
| 682 // Cut off walk if we've already failed. | 684 // Cut off walk if we've already failed. |
| 683 if (failed_) | 685 if (failed_) |
| 684 *stop = true; | 686 *stop = true; |
| 685 | 687 |
| 686 return kNullFrag; // not used by caller | 688 return NullFrag(); // not used by caller |
| 687 } | 689 } |
| 688 | 690 |
| 689 Frag Compiler::Literal(Rune r, bool foldcase) { | 691 Frag Compiler::Literal(Rune r, bool foldcase) { |
| 690 switch (encoding_) { | 692 switch (encoding_) { |
| 691 default: | 693 default: |
| 692 return kNullFrag; | 694 return NullFrag(); |
| 693 | 695 |
| 694 case kEncodingLatin1: | 696 case kEncodingLatin1: |
| 695 return ByteRange(r, r, foldcase); | 697 return ByteRange(r, r, foldcase); |
| 696 | 698 |
| 697 case kEncodingUTF8: { | 699 case kEncodingUTF8: { |
| 698 if (r < Runeself) // Make common case fast. | 700 if (r < Runeself) // Make common case fast. |
| 699 return ByteRange(r, r, foldcase); | 701 return ByteRange(r, r, foldcase); |
| 700 uint8 buf[UTFmax]; | 702 uint8 buf[UTFmax]; |
| 701 int n = runetochar(reinterpret_cast<char*>(buf), &r); | 703 int n = runetochar(reinterpret_cast<char*>(buf), &r); |
| 702 Frag f = ByteRange((uint8)buf[0], buf[0], false); | 704 Frag f = ByteRange((uint8)buf[0], buf[0], false); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 725 case kRegexpNoMatch: | 727 case kRegexpNoMatch: |
| 726 return NoMatch(); | 728 return NoMatch(); |
| 727 | 729 |
| 728 case kRegexpEmptyMatch: | 730 case kRegexpEmptyMatch: |
| 729 return Nop(); | 731 return Nop(); |
| 730 | 732 |
| 731 case kRegexpHaveMatch: { | 733 case kRegexpHaveMatch: { |
| 732 Frag f = Match(re->match_id()); | 734 Frag f = Match(re->match_id()); |
| 733 // Remember unanchored match to end of string. | 735 // Remember unanchored match to end of string. |
| 734 if (anchor_ != RE2::ANCHOR_BOTH) | 736 if (anchor_ != RE2::ANCHOR_BOTH) |
| 735 f = Cat(DotStar(), f); | 737 f = Cat(DotStar(), Cat(EmptyWidth(kEmptyEndText), f)); |
| 736 return f; | 738 return f; |
| 737 } | 739 } |
| 738 | 740 |
| 739 case kRegexpConcat: { | 741 case kRegexpConcat: { |
| 740 Frag f = child_frags[0]; | 742 Frag f = child_frags[0]; |
| 741 for (int i = 1; i < nchild_frags; i++) | 743 for (int i = 1; i < nchild_frags; i++) |
| 742 f = Cat(f, child_frags[i]); | 744 f = Cat(f, child_frags[i]); |
| 743 return f; | 745 return f; |
| 744 } | 746 } |
| 745 | 747 |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 998 Regexp* sre = re->Simplify(); | 1000 Regexp* sre = re->Simplify(); |
| 999 if (sre == NULL) | 1001 if (sre == NULL) |
| 1000 return NULL; | 1002 return NULL; |
| 1001 | 1003 |
| 1002 // Record whether prog is anchored, removing the anchors. | 1004 // Record whether prog is anchored, removing the anchors. |
| 1003 // (They get in the way of other optimizations.) | 1005 // (They get in the way of other optimizations.) |
| 1004 bool is_anchor_start = IsAnchorStart(&sre, 0); | 1006 bool is_anchor_start = IsAnchorStart(&sre, 0); |
| 1005 bool is_anchor_end = IsAnchorEnd(&sre, 0); | 1007 bool is_anchor_end = IsAnchorEnd(&sre, 0); |
| 1006 | 1008 |
| 1007 // Generate fragment for entire regexp. | 1009 // Generate fragment for entire regexp. |
| 1008 Frag f = c.WalkExponential(sre, kNullFrag, 2*c.max_inst_); | 1010 Frag f = c.WalkExponential(sre, NullFrag(), 2*c.max_inst_); |
| 1009 sre->Decref(); | 1011 sre->Decref(); |
| 1010 if (c.failed_) | 1012 if (c.failed_) |
| 1011 return NULL; | 1013 return NULL; |
| 1012 | 1014 |
| 1013 // Success! Finish by putting Match node at end, and record start. | 1015 // Success! Finish by putting Match node at end, and record start. |
| 1014 // Turn off c.reversed_ (if it is set) to force the remaining concatenations | 1016 // Turn off c.reversed_ (if it is set) to force the remaining concatenations |
| 1015 // to behave normally. | 1017 // to behave normally. |
| 1016 c.reversed_ = false; | 1018 c.reversed_ = false; |
| 1017 Frag all = c.Cat(f, c.Match(0)); | 1019 Frag all = c.Cat(f, c.Match(0)); |
| 1018 c.prog_->set_start(all.begin); | 1020 c.prog_->set_start(all.begin); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1089 | 1091 |
| 1090 // Compiles RE set to Prog. | 1092 // Compiles RE set to Prog. |
| 1091 Prog* Compiler::CompileSet(const RE2::Options& options, RE2::Anchor anchor, | 1093 Prog* Compiler::CompileSet(const RE2::Options& options, RE2::Anchor anchor, |
| 1092 Regexp* re) { | 1094 Regexp* re) { |
| 1093 Compiler c; | 1095 Compiler c; |
| 1094 | 1096 |
| 1095 Regexp::ParseFlags pf = static_cast<Regexp::ParseFlags>(options.ParseFlags()); | 1097 Regexp::ParseFlags pf = static_cast<Regexp::ParseFlags>(options.ParseFlags()); |
| 1096 c.Setup(pf, options.max_mem(), anchor); | 1098 c.Setup(pf, options.max_mem(), anchor); |
| 1097 | 1099 |
| 1098 // Compile alternation of fragments. | 1100 // Compile alternation of fragments. |
| 1099 Frag all = c.WalkExponential(re, kNullFrag, 2*c.max_inst_); | 1101 Frag all = c.WalkExponential(re, NullFrag(), 2*c.max_inst_); |
| 1100 re->Decref(); | 1102 re->Decref(); |
| 1101 if (c.failed_) | 1103 if (c.failed_) |
| 1102 return NULL; | 1104 return NULL; |
| 1103 | 1105 |
| 1104 if (anchor == RE2::UNANCHORED) { | 1106 if (anchor == RE2::UNANCHORED) { |
| 1105 // The trailing .* was added while handling kRegexpHaveMatch. | 1107 // The trailing .* was added while handling kRegexpHaveMatch. |
| 1106 // We just have to add the leading one. | 1108 // We just have to add the leading one. |
| 1107 all = c.Cat(c.DotStar(), all); | 1109 all = c.Cat(c.DotStar(), all); |
| 1108 } | 1110 } |
| 1109 | 1111 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1129 | 1131 |
| 1130 return prog; | 1132 return prog; |
| 1131 } | 1133 } |
| 1132 | 1134 |
| 1133 Prog* Prog::CompileSet(const RE2::Options& options, RE2::Anchor anchor, | 1135 Prog* Prog::CompileSet(const RE2::Options& options, RE2::Anchor anchor, |
| 1134 Regexp* re) { | 1136 Regexp* re) { |
| 1135 return Compiler::CompileSet(options, anchor, re); | 1137 return Compiler::CompileSet(options, anchor, re); |
| 1136 } | 1138 } |
| 1137 | 1139 |
| 1138 } // namespace re2 | 1140 } // namespace re2 |
| OLD | NEW |