[regexp] Implement regexp groups as wrapper.
Non-capturing groups so far did not have any effect, so we elided them in the regexp parser. However, they do affect how lookarounds are parsed: in unicode mode, lookarounds are not quantifiable. They are however if wrapped in a group. BUG=v8:5845 Review-Url: https://codereview.chromium.org/2636883002 Cr-Commit-Position: refs/heads/master@{#42436}
This commit is contained in:
parent
2851866cfe
commit
92acec568c
@ -264,6 +264,12 @@ void* RegExpUnparser::VisitCapture(RegExpCapture* that, void* data) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* RegExpUnparser::VisitGroup(RegExpGroup* that, void* data) {
|
||||
os_ << "(?: ";
|
||||
that->body()->Accept(this, data);
|
||||
os_ << ")";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* RegExpUnparser::VisitLookaround(RegExpLookaround* that, void* data) {
|
||||
os_ << "(";
|
||||
|
@ -21,12 +21,12 @@ namespace internal {
|
||||
VISIT(Atom) \
|
||||
VISIT(Quantifier) \
|
||||
VISIT(Capture) \
|
||||
VISIT(Group) \
|
||||
VISIT(Lookaround) \
|
||||
VISIT(BackReference) \
|
||||
VISIT(Empty) \
|
||||
VISIT(Text)
|
||||
|
||||
|
||||
#define FORWARD_DECLARE(Name) class RegExp##Name;
|
||||
FOR_EACH_REG_EXP_TREE_TYPE(FORWARD_DECLARE)
|
||||
#undef FORWARD_DECLARE
|
||||
@ -440,6 +440,26 @@ class RegExpCapture final : public RegExpTree {
|
||||
const ZoneVector<uc16>* name_;
|
||||
};
|
||||
|
||||
class RegExpGroup final : public RegExpTree {
|
||||
public:
|
||||
explicit RegExpGroup(RegExpTree* body) : body_(body) {}
|
||||
void* Accept(RegExpVisitor* visitor, void* data) override;
|
||||
RegExpNode* ToNode(RegExpCompiler* compiler,
|
||||
RegExpNode* on_success) override {
|
||||
return body_->ToNode(compiler, on_success);
|
||||
}
|
||||
RegExpGroup* AsGroup() override;
|
||||
bool IsAnchoredAtStart() override { return body_->IsAnchoredAtStart(); }
|
||||
bool IsAnchoredAtEnd() override { return body_->IsAnchoredAtEnd(); }
|
||||
bool IsGroup() override;
|
||||
int min_match() override { return body_->min_match(); }
|
||||
int max_match() override { return body_->max_match(); }
|
||||
Interval CaptureRegisters() override { return body_->CaptureRegisters(); }
|
||||
RegExpTree* body() { return body_; }
|
||||
|
||||
private:
|
||||
RegExpTree* body_;
|
||||
};
|
||||
|
||||
class RegExpLookaround final : public RegExpTree {
|
||||
public:
|
||||
|
@ -216,7 +216,9 @@ RegExpTree* RegExpParser::ParseDisjunction() {
|
||||
RegExpCapture* capture = GetCapture(capture_index);
|
||||
capture->set_body(body);
|
||||
body = capture;
|
||||
} else if (group_type != GROUPING) {
|
||||
} else if (group_type == GROUPING) {
|
||||
body = new (zone()) RegExpGroup(body);
|
||||
} else {
|
||||
DCHECK(group_type == POSITIVE_LOOKAROUND ||
|
||||
group_type == NEGATIVE_LOOKAROUND);
|
||||
bool is_positive = (group_type == POSITIVE_LOOKAROUND);
|
||||
|
@ -199,8 +199,8 @@ void TestRegExpParser(bool lookbehind) {
|
||||
CheckParseEq("xyz{1,}?", "(: 'xy' (# 1 - n 'z'))");
|
||||
CheckParseEq("a\\fb\\nc\\rd\\te\\vf", "'a\\x0cb\\x0ac\\x0dd\\x09e\\x0bf'");
|
||||
CheckParseEq("a\\nb\\bc", "(: 'a\\x0ab' @b 'c')");
|
||||
CheckParseEq("(?:foo)", "'foo'");
|
||||
CheckParseEq("(?: foo )", "' foo '");
|
||||
CheckParseEq("(?:foo)", "(?: 'foo')");
|
||||
CheckParseEq("(?: foo )", "(?: ' foo ')");
|
||||
CheckParseEq("(foo|bar|baz)", "(^ (| 'foo' 'bar' 'baz'))");
|
||||
CheckParseEq("foo|(bar|baz)|quux", "(| 'foo' (^ (| 'bar' 'baz')) 'quux')");
|
||||
CheckParseEq("foo(?=bar)baz", "(: 'foo' (-> + 'bar') 'baz')");
|
||||
@ -294,7 +294,7 @@ void TestRegExpParser(bool lookbehind) {
|
||||
CheckParseEq("(?!\\1(a\\1)\\1)\\1",
|
||||
"(: (-> - (: (<- 1) (^ 'a') (<- 1))) (<- 1))");
|
||||
CheckParseEq("\\1\\2(a(?:\\1(b\\1\\2))\\2)\\1",
|
||||
"(: (<- 1) (<- 2) (^ (: 'a' (^ 'b') (<- 2))) (<- 1))");
|
||||
"(: (<- 1) (<- 2) (^ (: 'a' (?: (^ 'b')) (<- 2))) (<- 1))");
|
||||
if (lookbehind) {
|
||||
CheckParseEq("\\1\\2(a(?<=\\1(b\\1\\2))\\2)\\1",
|
||||
"(: (<- 1) (<- 2) (^ (: 'a' (<- + (^ 'b')) (<- 2))) (<- 1))");
|
||||
|
6
test/mjsunit/regress/regress-5845.js
Normal file
6
test/mjsunit/regress/regress-5845.js
Normal file
@ -0,0 +1,6 @@
|
||||
// Copyright 2017 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
assertDoesNotThrow('/(?:(?=(foo)))?/u.exec("foo")');
|
||||
assertThrows('/(?=(foo))?/u.exec("foo")');
|
Loading…
Reference in New Issue
Block a user