Class: Xr

Inherits:
Object
  • Object
show all
Defined in:
lib/xr.rb

Constant Summary collapse

VERSION =
"0.1.1"
Error =
Class.new(StandardError)
UNMATCHABLE =

:nodoc:

Regexp.union([])

Instance Method Summary collapse

Constructor Details

#initialize(greedy: true) ⇒ Xr

Returns a new instance of Xr.



9
10
11
# File 'lib/xr.rb', line 9

def initialize(greedy: true)
  @greedy = greedy
end

Instance Method Details

#*(*exprs) ⇒ Object



42
43
44
45
# File 'lib/xr.rb', line 42

def *(*exprs)
  expr = try_to_s(Xr { exprs })
  Regexp.new(@greedy ? "(#{expr})*" : "(#{expr})*?")
end

#+(*exprs) ⇒ Object



47
48
49
50
# File 'lib/xr.rb', line 47

def +(*exprs)
  expr = try_to_s(Xr { exprs })
  Regexp.new(@greedy ? "(#{expr})+" : "(#{expr})+?")
end

#_(*exprs) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
# File 'lib/xr.rb', line 15

def _ *exprs
  case exprs
  in [] then Xr.new
  in Integer => num, *exprs
    expr = Xr { exprs }
    Regexp.new("(#{expr}){#{num}}")
  in Range => range, *exprs
    expr = Xr { exprs }
    Regexp.new("(#{expr}){#{range.begin},#{range.end}}")
  end
end

#_?(*exprs, &block) ⇒ Boolean

Returns:

  • (Boolean)


27
28
29
30
31
32
33
34
35
# File 'lib/xr.rb', line 27

def _? *exprs, &block
  block_given? and return Xr.new(greedy: false).instance_eval(&block)
  case exprs
  in [] then Xr.new(greedy: false)
  else
    expr = try_to_s(Xr { exprs })
    Regexp.new(@greedy ? "(#{expr})?" : "(#{expr})??")
  end
end

#any(*sets) ⇒ Object



52
53
54
55
# File 'lib/xr.rb', line 52

def any(*sets)
  set = sets.map { try_to_s(_1) }.join
  Regexp.new("[#{set}]")
end

#backref(name) ⇒ Object



71
72
73
74
75
76
77
78
79
# File 'lib/xr.rb', line 71

def backref(name)
  case name
  in Integer then ->(pre) { Regexp.new("#{pre}\\#{name}") }
  in Symbol | String
    name = name.to_s
    valid_name?(name) or raise Error, "invalid group name"
    ->(pre) { Regexp.new("#{pre}\\k<#{name}>") }
  end
end

#except(*sets) ⇒ Object



57
58
59
60
# File 'lib/xr.rb', line 57

def except(*sets)
  set = sets.map { try_to_s(_1) }.join
  Regexp.new("[^#{set}]")
end

#group(name = nil, &block) ⇒ Object



62
63
64
65
66
67
68
69
# File 'lib/xr.rb', line 62

def group(name = nil, &block)
  expr = Xr.new.instance_eval(&block)
  if name
    valid_name?(name) or raise Error, "invalid group name"
    Regexp.new("(?<#{name}>#{expr})")
  else Regexp.new("(#{expr})")
  end
end

#parse(expr) ⇒ Object

:nodoc:



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
# File 'lib/xr.rb', line 93

def parse(expr) # :nodoc:
  case expr
  in String         then Regexp.new(Regexp.escape(expr))
  in Regexp | Proc  then expr
  in Xr           then expr.instance_variable_get(:@expr)
  in Array
    pre, *exprs = *expr
    pre = try_to_s(pre).to_s
    exprs.each do |exp|
      if exp.respond_to?(:call)
        pre = exp.(pre).to_s
      else
        pre = "#{pre}#{try_to_s(exp)}"
      end
    end
    Regexp.new(pre)
  in :not_newline   then Regexp.new(".")
  in :anychar       then Regexp.new('[^a-z]')
  in :line_start    then /^/
  in :line_end      then /$/
  in :string_start  then /\A/
  in :string_end    then /\z/
  in :word_boundary then /\b/
  in :alpha | :alnum | :digit | :xdigit | :cntrl | :blank | :space |
     :lower | :upper |
     :graph | :print | :punct | :word | :ascii
    Regexp.new("[[:#{expr}:]]")
  end
end

#try_to_s(expr) ⇒ Object

:nodoc:



83
84
85
86
87
88
89
90
91
# File 'lib/xr.rb', line 83

def try_to_s(expr) # :nodoc:
  case expr
  in String then Regexp.escape(expr)
  in Regexp then expr.to_s
  in Range  then "#{expr.begin}-#{expr.end}"
  in Proc   then expr
  in Symbol then parse(expr).to_s
  end
end

#unmatchableObject



13
# File 'lib/xr.rb', line 13

def unmatchable = UNMATCHABLE

#valid_name?(name) ⇒ Boolean

:nodoc:

Returns:

  • (Boolean)


81
# File 'lib/xr.rb', line 81

def valid_name?(name) = name.match?(/ \A [a-zA-Z_][a-zA-Z0-9_]* \z /x) # :nodoc:

#|(other) ⇒ Object



37
38
39
40
# File 'lib/xr.rb', line 37

def | other
  @expr = @expr ? Regexp.union([@expr, other].map { parse(_1) }) : parse(other)
  self
end