Class: RedParse::RuleSet

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

Constant Summary collapse

@@FFS_TABLE =
[nil]

Instance Method Summary collapse

Constructor Details

#initialize(rules) ⇒ RuleSet

Returns a new instance of RuleSet.



43
44
45
46
47
48
49
# File 'lib/redparse/compile.rb', line 43

def initialize(rules)
  @rules=rules.reverse
  #rule order must be reversed relative to the usual RedParse rule
  #order... merely so that ffs can work right.
  @maxmask=(1<<@rules.size)-1
  @subclasses_of=child_relations_among(*STACKABLE_CLASSES())
end

Instance Method Details

#[](i) ⇒ Object



241
242
243
# File 'lib/redparse/compile.rb', line 241

def [](i)
  @rules[i]
end

#each_rule(mask = @maxmask) ⇒ Object



76
77
78
79
80
# File 'lib/redparse/compile.rb', line 76

def each_rule(mask=-1)
  @rules.each_with_index{|r,i|
    yield r,i if mask&(1<<i)
  }
end

#juice(m) ⇒ Object



180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/redparse/compile.rb', line 180

def juice(m)
  case m  #
  when Class; 
    return [m] unless @subclasses_of
    result=[m]  # and subclasses too
    i=0
    while item=result[i]
      #p item
      result.concat @subclasses_of[item]
      i += 1
    end
    result
  when String,Regexp; juice(RedParse.KW(m))
  when Reg::And; m.subregs.map{|x| juice(x).flatten.compact}.inject{|sum,rr| sum&rr} 
  when Reg::Or; m.subregs.map( &method(:juice) )
  when Reg::Not;  
    m=m.subregs[0]
    if Class===m or (Reg::Or===m  and 
         m.subregs.inject{|sum,x| sum && (Class===x) })
      j=juice(m)
      STACKABLE_CLASSES()-j.flatten.compact rescue j
    else 
      STACKABLE_CLASSES()
    end
  else STACKABLE_CLASSES()
  end
end

#LEFTObject

just the left side (the stack/lookahead matchers)



150
151
152
# File 'lib/redparse/compile.rb', line 150

def LEFT
  @rules.map{|r| r.left.subregs }.flatten
end

#LEFT_NO_LOOKINGObject

remove lookahead and lookback decoration



155
156
157
158
159
160
161
162
163
164
165
# File 'lib/redparse/compile.rb', line 155

def LEFT_NO_LOOKING
l=LEFT()
l.map!{|m| 
  case m #
  when Reg::LookAhead,Reg::LookBack; m.subregs[0]
  when Proc; []
  else m #
  end #
} 
l
end

#LOOKAHEAD_CLASSES(rule) ⇒ Object



221
222
223
224
225
226
# File 'lib/redparse/compile.rb', line 221

def LOOKAHEAD_CLASSES rule
  last=rule.left.subregs.last 
  return STACKABLE_CLASSES() unless Reg::LookAhead===last
  la= last.subregs[0]
  return juice(la).flatten.compact
end

#mask2rules(mask) ⇒ Object



59
60
61
62
63
64
65
# File 'lib/redparse/compile.rb', line 59

def mask2rules(mask)
  rules=[]
  @rules.each_with_index{|r,i|
    rules<<r if mask&(1<<i)
  }
  return rules
end

#rb_ffs(mask) ⇒ Object



95
96
97
98
99
100
101
102
103
104
# File 'lib/redparse/compile.rb', line 95

def rb_ffs(mask)
  chunks=0
  until mask.zero?
    result=@@FFS_TABLE[mask&0xFF]
    return result+(chunks<<3) if result
    chunks+=1
    mask>>=8
  end
  return 0
end

#rules2mask(rules) ⇒ Object



51
52
53
54
55
56
57
# File 'lib/redparse/compile.rb', line 51

def rules2mask(rules)
  mask=0
  @rules.each_with_index{|r,i| 
     mask |= 1<<i if rules.include? r
  }
  return mask
end

#sc_juice(m) ⇒ Object



208
209
210
211
212
213
214
215
216
217
218
219
# File 'lib/redparse/compile.rb', line 208

def sc_juice(m) 
  case m #
  when Class; [m]
  when String,Regexp; juice(RedParse.KW(m))
#      when String,Regexp; [KeywordToken]
  when Reg::And; m.subregs.map{|x| sc_juice(x)}.compact.map{|x| x.flatten.compact}.inject{|sum,rr| sum&rr }
  when Reg::Or; m.subregs.map( &method(:sc_juice) )
  when Reg::Not; sc_juice(m.subregs[0])
  when Reg::LookAhead, Reg::LookBack; sc_juice(m.subregs[0])
  else []
  end
end

#STACKABLE_CLASSESObject

all classes mentioned in rules, on left and right sides



168
169
170
171
172
173
174
175
176
177
178
# File 'lib/redparse/compile.rb', line 168

def STACKABLE_CLASSES #
  return @sc_result unless  @sc_result.nil? 
  @sc_result=false
  l=LEFT_NO_LOOKING()
  l=l.map{|lm| sc_juice lm}.flatten.compact
  r=  @rules.map{|rr| rr.right }.grep(Class) #classes in productions
  result=l+r 
  @sc_result=result.grep(Class).uniq
  fail if @sc_result.empty?
  return @sc_result
end

#TOS_CLASSES(rule) ⇒ Object



228
229
230
231
232
233
234
235
236
237
238
239
# File 'lib/redparse/compile.rb', line 228

def TOS_CLASSES rule
  i=-1
  mats=rule.left.subregs
  m=mats[i]
  m=mats[i-=1] if Reg::LookAhead===m || Proc===m
  result=[]
  while Reg::Repeat===m and m.times.min.zero?
    result<<juice(m.subregs[0])
    m=mats[i-=1]
  end
  return (result+juice(m)).flatten.compact
end