1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
require_relative '../spec_helper'
require_relative 'fixtures/classes'
describe "Literal Regexps" do
it "matches against $_ (last input) in a conditional if no explicit matchee provided" do
-> {
eval <<-EOR
$_ = nil
(true if /foo/).should_not == true
$_ = "foo"
(true if /foo/).should == true
EOR
}.should complain(/regex literal in condition/)
end
it "yields a Regexp" do
/Hello/.should be_kind_of(Regexp)
end
it "is frozen" do
/Hello/.should.frozen?
end
it "caches the Regexp object" do
rs = []
2.times do |i|
rs << /foo/
end
rs[0].should equal(rs[1])
end
it "throws SyntaxError for malformed literals" do
-> { eval('/(/') }.should raise_error(SyntaxError)
end
#############################################################################
# %r
#############################################################################
it "supports paired delimiters with %r" do
LanguageSpecs.paired_delimiters.each do |p0, p1|
eval("%r#{p0} foo #{p1}").should == / foo /
end
end
it "supports grouping constructs that are also paired delimiters" do
LanguageSpecs.paired_delimiters.each do |p0, p1|
eval("%r#{p0} () [c]{1} #{p1}").should == / () [c]{1} /
end
end
it "allows second part of paired delimiters to be used as non-paired delimiters" do
LanguageSpecs.paired_delimiters.each do |p0, p1|
eval("%r#{p1} foo #{p1}").should == / foo /
end
end
it "disallows first part of paired delimiters to be used as non-paired delimiters" do
LanguageSpecs.paired_delimiters.each do |p0, p1|
-> { eval("%r#{p0} foo #{p0}") }.should raise_error(SyntaxError)
end
end
it "supports non-paired delimiters delimiters with %r" do
LanguageSpecs.non_paired_delimiters.each do |c|
eval("%r#{c} foo #{c}").should == / foo /
end
end
it "disallows alphabets as non-paired delimiter with %r" do
-> { eval('%ra foo a') }.should raise_error(SyntaxError)
end
it "disallows spaces after %r and delimiter" do
-> { eval('%r !foo!') }.should raise_error(SyntaxError)
end
it "allows unescaped / to be used with %r" do
%r[/].to_s.should == /\//.to_s
end
#############################################################################
# Specs for the matching semantics
#############################################################################
it "supports . (any character except line terminator)" do
# Basic matching
/./.match("foo").to_a.should == ["f"]
# Basic non-matching
/./.match("").should be_nil
/./.match("\n").should be_nil
/./.match("\0").to_a.should == ["\0"]
end
it "supports | (alternations)" do
/a|b/.match("a").to_a.should == ["a"]
end
it "supports (?> ) (embedded subexpression)" do
/(?>foo)(?>bar)/.match("foobar").to_a.should == ["foobar"]
/(?>foo*)obar/.match("foooooooobar").should be_nil # it is possessive
end
it "supports (?# )" do
/foo(?#comment)bar/.match("foobar").to_a.should == ["foobar"]
/foo(?#)bar/.match("foobar").to_a.should == ["foobar"]
end
it "supports (?<= ) (positive lookbehind)" do
/foo.(?<=\d)/.match("fooA foo1").to_a.should == ["foo1"]
end
ruby_bug "#13671", ""..."3.4" do # https://bugs.ruby-lang.org/issues/13671
it "handles a lookbehind with ss characters" do
r = Regexp.new("(?<!dss)", Regexp::IGNORECASE)
r.should =~ "✨"
end
end
it "supports (?<! ) (negative lookbehind)" do
/foo.(?<!\d)/.match("foo1 fooA").to_a.should == ["fooA"]
end
it "supports \\g (named backreference)" do
/(?<foo>foo.)bar\g<foo>/.match("foo1barfoo2").to_a.should == ["foo1barfoo2", "foo2"]
end
it "supports character class composition" do
/[a-z&&[^a-c]]+/.match("abcdef").to_a.should == ["def"]
/[a-z&&[^d-i&&[^d-f]]]+/.match("abcdefghi").to_a.should == ["abcdef"]
end
it "supports possessive quantifiers" do
/fooA++bar/.match("fooAAAbar").to_a.should == ["fooAAAbar"]
/fooA++Abar/.match("fooAAAbar").should be_nil
/fooA?+Abar/.match("fooAAAbar").should be_nil
/fooA*+Abar/.match("fooAAAbar").should be_nil
end
it "supports conditional regular expressions with positional capture groups" do
pattern = /\A(foo)?(?(1)(T)|(F))\z/
pattern.should =~ 'fooT'
pattern.should =~ 'F'
pattern.should_not =~ 'fooF'
pattern.should_not =~ 'T'
end
it "supports conditional regular expressions with named capture groups" do
pattern = /\A(?<word>foo)?(?(<word>)(T)|(F))\z/
pattern.should =~ 'fooT'
pattern.should =~ 'F'
pattern.should_not =~ 'fooF'
pattern.should_not =~ 'T'
end
it "support handling unicode 9.0 characters with POSIX bracket expressions" do
char_lowercase = "\u{104D8}" # OSAGE SMALL LETTER A
/[[:lower:]]/.match(char_lowercase).to_s.should == char_lowercase
char_uppercase = "\u{104B0}" # OSAGE CAPITAL LETTER A
/[[:upper:]]/.match(char_uppercase).to_s.should == char_uppercase
end
end
|