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
eql?(other;)
Alias for: ==
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