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
|
# frozen_string_literal: true
module JSONSchemer
class EcmaRegexp
class Syntax < Regexp::Syntax::Base
# regexp_parser >= 2.3.0 uses syntax classes directly instead of instances
# :nocov:
SYNTAX = respond_to?(:implements) ? self : new
# :nocov:
SYNTAX.implements :anchor, Anchor::Extended
SYNTAX.implements :assertion, Assertion::All
# literal %i[number] to support regexp_parser < 2.2.0 (Backreference::Plain)
SYNTAX.implements :backref, %i[number] + Backreference::Name
# :meta_sequence, :bell, and :escape are not supported in ecma
SYNTAX.implements :escape, Escape::Basic + (Escape::Control - %i[meta_sequence]) + (Escape::ASCII - %i[bell escape]) + Escape::Unicode + Escape::Meta + Escape::Hex + Escape::Octal
SYNTAX.implements :property, UnicodeProperty::All
SYNTAX.implements :nonproperty, UnicodeProperty::All
# :comment is not supported in ecma
SYNTAX.implements :free_space, (FreeSpace::All - %i[comment])
SYNTAX.implements :group, Group::Basic + Group::Named + Group::Passive
SYNTAX.implements :literal, Literal::All
SYNTAX.implements :meta, Meta::Extended
SYNTAX.implements :quantifier, Quantifier::Greedy + Quantifier::Reluctant + Quantifier::Interval + Quantifier::IntervalReluctant
SYNTAX.implements :set, CharacterSet::Basic
SYNTAX.implements :type, CharacterType::Extended
end
RUBY_EQUIVALENTS = {
:anchor => {
:bol => '\A',
:eol => '\z'
},
:type => {
:space => '[\t\r\n\f\v\uFEFF\u2029\p{Zs}]',
:nonspace => '[^\t\r\n\f\v\uFEFF\u2029\p{Zs}]'
}
}.freeze
class << self
def ruby_equivalent(pattern)
Regexp::Scanner.scan(pattern).map do |type, token, text|
Syntax::SYNTAX.check!(*Syntax::SYNTAX.normalize(type, token))
RUBY_EQUIVALENTS.dig(type, token) || text
rescue Regexp::Syntax::NotImplementedError
raise InvalidEcmaRegexp, "invalid token #{text.inspect} (#{type}:#{token}) in #{pattern.inspect}"
end.join
rescue Regexp::Scanner::ScannerError
raise InvalidEcmaRegexp, "invalid pattern #{pattern.inspect}"
end
end
end
end
|