Class: Randexp::Parser

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

Class Method Summary collapse

Class Method Details

.balanced?(*args) ⇒ Boolean

Returns:

  • (Boolean)


50
51
52
# File 'lib/randexp/parser.rb', line 50

def self.balanced?(*args)
  args.all? {|s| s.count('(') == s.count(')')}
end

.intersection(lhs, rhs) ⇒ Object



81
82
83
84
85
86
87
# File 'lib/randexp/parser.rb', line 81

def self.intersection(lhs, rhs)
  if rhs.first == :intersection
    [:intersection, lhs] + rhs[1..-1]
  else
    [:intersection, lhs, rhs]
  end
end

.literal(word) ⇒ Object



93
94
95
# File 'lib/randexp/parser.rb', line 93

def self.literal(word)
  [:literal, word]
end

.parse(source) ⇒ Object Also known as: []



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
# File 'lib/randexp/parser.rb', line 3

def self.parse(source)
  case
  when source =~ /^(.*)(\*|\*\?|\+|\+\?|\?)$/ && balanced?($1, $2)
    parse_quantified($1, $2.to_sym)                                 # ends with *, +, or ?: /(..)?/
  when source =~ /^(.*)\{(\d+)\,(\d+)\}$/ && balanced?($1, $2)
    parse_quantified($1, ($2.to_i)..($3.to_i))                      #ends with a range: /(..){..,..}/
  when source =~ /^(.*)\{(\d+)\}$/ && balanced?($1, $2)
    parse_quantified($1, $2.to_i)                                   #ends with a range: /..(..){..}/
  when source =~ /^\((.*)\)\((.*)\)$/ && balanced?($1, $2)
    union(parse($1), parse($2))                                     #balanced union: /(..)(..)/
  when source =~ /^(\(.*\))\|(\(.*\))$/ && balanced?($1, $2)
    intersection(parse($1), parse($2))                              #balanced intersection: /(..)|(..)/
  when source =~ /^(.*)\|(.*)$/ && balanced?($1, $2)
    intersection(parse($1), parse($2))                              #implied intersection: /..|../
  when source =~ /^(.*)\|\((\(.*\))\)$/ && balanced?($1, $2)
    intersection(parse($1), parse($2))                              #unbalanced intersection: /(..)|((...))/
  when source =~ /^(.+)(\(.*\))$/ && balanced?($1, $2)
    union(parse($1), parse($2))                                     #unbalanced union: /...(...)/
  when source =~ /^\((.*)\)$/ && balanced?($1)
    union(parse($1))                                                #explicit group: /(..)/
  when source =~ /^([^()]*)(\(.*\))$/ && balanced?($1, $2)
    union(parse($1), parse($2))                                     #implied group: /..(..)/
  when source =~ /^(.*)\[\:(.*)\:\]$/
    union(parse($1), random($2))                                    #custom random: /[:word:]/
  when source =~ /^(.*)\\([wsdc])$/
    union(parse($1), random($2))                                    #reserved random: /..\w/
  when source =~ /^(.*)\\(.)$/ || source =~ /(.*)(.|\s)$/
    union(parse($1), literal($2))                                   #end with literal or space: /... /
  else
    nil
  end
end

.parse_quantified(source, multiplicity) ⇒ Object



36
37
38
39
40
41
42
43
44
# File 'lib/randexp/parser.rb', line 36

def self.parse_quantified(source, multiplicity)
  case source
  when /^[^()]*$/     then quantify_rhs(parse(source), multiplicity)    #implied union: /...+/
  when /^(\(.*\))$/   then quantify(parse(source), multiplicity)        #group: /(...)?/
  when /^(.*\))$/     then quantify_rhs(parse(source), multiplicity)    #implied union: /...(...)?/
  when /^(.*[^)]+)$/  then quantify_rhs(parse(source), multiplicity)    #implied union: /...(...)...?/
  else quantify(parse(source), multiplicity)
  end
end

.quantify(lhs, sym) ⇒ Object



64
65
66
# File 'lib/randexp/parser.rb', line 64

def self.quantify(lhs, sym)
  [:quantify, lhs, sym]
end

.quantify_rhs(sexp, multiplicity) ⇒ Object



54
55
56
57
58
59
60
61
62
# File 'lib/randexp/parser.rb', line 54

def self.quantify_rhs(sexp, multiplicity)
  case sexp.first
  when :union
    rhs = sexp.pop
    sexp << quantify(rhs, multiplicity)
  else
    quantify(sexp, multiplicity)
  end
end

.random(char) ⇒ Object



89
90
91
# File 'lib/randexp/parser.rb', line 89

def self.random(char)
  [:random, char.to_sym]
end

.union(lhs, *rhs) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/randexp/parser.rb', line 68

def self.union(lhs, *rhs)
  if lhs.nil?
    union(*rhs)
  elsif rhs.empty?
    lhs
  elsif lhs.first == :union
    rhs.each {|s| lhs << s}
    lhs
  else
    [:union, lhs, *rhs]
  end
end