class RedParse::DottedRule
Attributes
also_allow[RW]
pos[R]
rule[R]
Public Class Methods
create(rule,pos,parser)
click to toggle source
# File lib/redparse/compile.rb, line 417 def self.create(rule,pos,parser) result=rule.drs[pos] and return result result=rule.drs[pos]=DottedRule.new(rule,pos,parser) unless defined? $OLD_PAA result.also_allow=result.compute_also_allow(parser) if parser end return result end
new(rule,pos,parser)
click to toggle source
# File lib/redparse/compile.rb, line 395 def initialize(rule,pos,parser) @rule,@pos=rule,pos fail unless (0...rule.patterns.size)===@pos # @also_allow= compute_also_allow(parser) if parser unless defined? $OLD_PAA end
Public Instance Methods
==(other;)
click to toggle source
# File lib/redparse/compile.rb, line 427 def == other; DottedRule===other and @pos==other.pos and @rule==other.rule end
Also aliased as: eql?
compute_also_allow(parser,provisional=[false])
click to toggle source
# File lib/redparse/compile.rb, line 400 def compute_also_allow(parser,provisional=[false]) parser.all_initial_dotted_rules.map{|dr| next if dr==self fake_rule=dr.rule.final_promised_rule final_more_dr=DottedRule.create(fake_rule,0,nil) also=dr.also_allow unless also provisional[0]||=0 provisional[0]+=1 also=[] end also+[dr] if optionally_combine final_more_dr,parser }.flatten.compact.uniq end
evolve(input, parser, seenlist,result2)
click to toggle source
returns Conditional|Rule|DottedRule|[DottedRule.
]|nil
# File lib/redparse/compile.rb, line 437 def evolve input, parser, seenlist,result2 #print "[" #$stdout.flush idname=input.identity_name idname=parser.identity_name_alias? idname cache=seenlist[[self,idname]] unless cache==:dunno_yet result2.concat Array(cache).flatten.compact.uniq.sort_by{|x| x.name} return cache end i=pos lasti=i-1 result=[] result=loop do #might need multiple tries if optional matcher(s) here fail unless i>lasti lasti=i p=@rule.at(i) #what is current pattern in this dottedrule? fail if Proc===p #shouldnt happen anymore if parser.pattern_matches_nodes? p #if any dotted rules have nodes at this point, #also include the set of rules@0 which #can (possibly indirectly) generate that node. #(match tokens found on left sides of productions for p) seenlist[[self,idname]]=result if false result.concat recurse_match_drs(parser).uniq.map{|dr| dr and #begin print "{#{dr.name}" dr.evolve input,parser,seenlist,result2 #ensure print "}" end }.flatten.compact.uniq end end @saw_item_that={} if p===input i+=1 unless @rule.looping?(i) fail if i>@rule.patterns.size if !@saw_item_that.empty? p(:saw_item_that!) fail unless @saw_item_that.size==1 pair=@saw_item_that.to_a.first fail unless p.equal? pair.last it=pair.first action= if i==@rule.patterns.size @rule else DottedRule.create(@rule,i,parser) end break Conditional.new(it,action) end @saw_item_that=nil if i == @rule.patterns.size break @rule else break result<<DottedRule.create(@rule,i,parser) end elsif !@rule.optional?(i) break result.empty? ? nil : result elsif (i+=1) >= @rule.patterns.size break @rule #else next p end end #loop seenlist[[self,idname]]=result result2.concat Array(result).flatten.compact.uniq.sort_by{|x| x.name} return result #ensure print "]" end
hash()
click to toggle source
# File lib/redparse/compile.rb, line 426 def hash; (@rule.priority<<3)^@pos end
looping?()
click to toggle source
# File lib/redparse/compile.rb, line 432 def looping? @rule.looping?(@pos) end
name()
click to toggle source
# File lib/redparse/compile.rb, line 430 def name; @rule.name+"@#@pos" end
optionally_combine(weaker,parser)
click to toggle source
# File lib/redparse/compile.rb, line 566 def optionally_combine weaker,parser #lotsa caching needed if this is ever to be performant if parser.oc_cache result=parser.oc_cache[[self,weaker]] return result unless result.nil? else parser.oc_cache={} end other=weaker mymatches,myposes= self.outcomes matches, poses = other.outcomes matches.each_with_index{|match,i| mymatches.each_with_index{|mymatch,myi| intersect=parser.inputs.grep(match&mymatch) unless intersect.empty? #but don't allow matches that would be matched #by an earlier (but optional) pattern. disallowed=Reg::Or.new( *possible_matchers_til(myi)+ other.possible_matchers_til(i) ) intersect.reject{|x| disallowed===x } if intersect.empty? return result=false elsif poses[i]>=other.rule.patterns.size return result=true #success if weaker rule is at an end elsif myposes[myi]>=rule.patterns.size return result=false #fail if stronger rule at an end else p [:**,rule.name,myposes[myi]] mynew=DottedRule.create(rule,myposes[myi],parser) new=DottedRule.create(other.rule,poses[i],parser) return result=mynew.optionally_combine( new,parser ) end end } } return result=false ensure parser.oc_cache[[self,weaker]]=result end
outcomes()
click to toggle source
# File lib/redparse/compile.rb, line 618 def outcomes til=@rule.patterns.size at=@pos result=[[],[]] loop do m=@rule.patterns[at] case m when Proc; result.first.push Object result.last.push at+1 break when Reg::Repeat assert @rule.optional?(at) to=at to+=1 unless @rule.looping? at result.first.push m.subregs[0] result.last.push to else result.first.push m result.last.push at+1 break end at+=1 break if at>=til end return result end
possible_matchers_til(i)
click to toggle source
# File lib/redparse/compile.rb, line 611 def possible_matchers_til i (pos...i-1).map{|j| m=rule.at(j) Reg::Repeat===m ? m.subregs[0] : m } end
recurse_match_drs(parser, result=nil)
click to toggle source
returns +[(DottedRule|nil).*]
# File lib/redparse/compile.rb, line 511 def recurse_match_drs parser, result=nil unless result table=parser.rmd_cache if table cache=table[self] return cache if cache else parser.rmd_cache={} end result=[] end #print "(" #print @rule.name+"@#@pos" p=@rule.at(@pos) #find set of nodes that could match here nodes_here=parser.exemplars_that_match(p&Node) #find the set of rules that could generate a node in our list rrules=parser.all_rules.select{|rule| !rule.unruly? and !nodes_here.grep(rule.action).empty? }.map{|rule| DottedRule.create(rule,0,parser) } #if any generating rules match a node in the leftmost pattern, #add the rules which can generate _that_ node too. result.push self #force self to be excluded from future recursion oldsize=result.size unless rrules.empty? result.concat rrules unless result.respond_to? :index_of class<<result attr_accessor :index_of end result.index_of={} end rio=result.index_of oldsize.upto(result.size){|i| rio[result[i]]||=i } rrules.each{|rrule| i=rio[rrule] or fail #index() inside each() == O(N**2) complexity. this is the slow line. #but skip recursion on rules already done at a higher level rrule.recurse_match_drs parser,result if i>=oldsize } end result[oldsize-1]=nil #don't actually include self in result #result.update_indices oldsize-1, oldsize-1 parser.rmd_cache[self]=result return result #ensure print ")" end