class RedParse::ParserState

Attributes

actions[R]
dotteds[R]
name[W]

Public Class Methods

new(dotteds,index) click to toggle source
# File lib/redparse/compile.rb, line 678
def initialize(dotteds,index)
  fail if dotteds.empty? #error state
  fail unless dotteds.grep(nil).empty?
  @dotteds=dotteds
  @index=index
  sort_substates!
  @actions={} #key is an input, value is ParserState|Rule|MultiShift|MultiReduce|:accept|:error
end

Public Instance Methods

==(other) click to toggle source
# File lib/redparse/compile.rb, line 871
def == other
  ParserState===other and 
    @dotteds==other.dotteds 
end
Also aliased as: eql?
[](k) click to toggle source
# File lib/redparse/compile.rb, line 689
def [](k) 
  result=@actions[k]
  assert ACTION_PATTERN===result
  result
end
[]=(k,v) click to toggle source
# File lib/redparse/compile.rb, line 694
def []=(k,v) 
  assert ACTION_PATTERN===v
  @actions[k]=v 
end
dup() click to toggle source
Calls superclass method
# File lib/redparse/compile.rb, line 704
def dup
  result=super
  result.instance_variable_set(:@dotteds,@dotteds.dup)
  return result
end
eql?(other)
Alias for: ==
evolve(input,parser,seenlist) click to toggle source

returns ParserState|MultiShift|MultiReduce|Rule|:accept|:error

# File lib/redparse/compile.rb, line 767
    def evolve input,parser,seenlist
      result2=[]
      @dotteds.each{|dotted| 
        dotted.evolve input,parser,seenlist,result2
      }

      result= 
        #seenlist.values.flatten.compact.uniq.sort_by{|x| x.name}
      result2=result2.uniq.compact.sort_by{|x| x.name}
      #pp [result,result2].map{|x| x.map{|res| DottedRule===res ? res.name : res }}
      #pp result2.map{|res| DottedRule===res ? res.name : res }
#      result==result2 or fail

      return result=:error if result.empty?


      #ok, who wants to shift and who wants to reduce?
      shiftlist,reducelist=result.partition{|res|
        DottedRule===res or
          Conditional===res && DottedRule===res.action
      }

      #if no reducers at all, just try (multi?)shift
      return result=shiftlist2multishift?( shiftlist,parser )if reducelist.empty?

      #line up reducers by priority
      actions=reducelist \
        .sort_by{|rule| -rule.priority }
#        .map{|rule| rule.action }
      #actions is +[(Rule|Conditional[Rule]).*]
      action=actions.shift #this first (unless conditional)
      #action is Rule|Conditional[Rule]
      result=
      case action.action
      when :error; return :error
      when Class, StackMonkey
        action
      when :accept
        :accept
      when :shift #this counts as a reduce at this point, but it writes shift instructions
        shiftlist2multishift? shiftlist,parser
      when Rule #oy, vey, was a Conditional
        shiftaction=shiftlist2multishift?(shiftlist,parser)
        fail unless Rule===action.action
        case action.action.action
        when :error; huh
        when :shift, StackMonkey, :accept, Class #MultiReduce
          first_fixed_index=actions.size
          #actions is +[(Rule|Conditional[Rule]).*]
          actions.each_with_index{|act,i|
            break first_fixed_index=i unless Conditional===act
          }
          condactions=actions[0...first_fixed_index].unshift(action)
          condactions=condactions.inject([]){|sum,cond|
            act=cond.action
            act=shiftaction if act==:shift #=>shiftlist?
            sum.push cond.condition, act
          }
          #possible optimization: one or more :shift right at end could be ignored
          if actions[first_fixed_index]
            action=actions[first_fixed_index].action
          else
            action=shiftaction
          end
          MultiReduce.new condactions,action #=>shiftlist?
        else fail
        end
      else fail "#{action} not expected here"
      end
      #stack monkeys/:accept are treated like reduce here
    ensure
      assert ACTION_PATTERN===result
    end
hash() click to toggle source
# File lib/redparse/compile.rb, line 868
def hash
  -@dotteds.hash
end
looping?() click to toggle source
# File lib/redparse/compile.rb, line 877
def looping?
  @dotteds.any?{|dotted| dotted.looping? }
end
make_sr_goto_tables(inputs) click to toggle source
# File lib/redparse/compile.rb, line 892
def make_sr_goto_tables inputs
  name2exemplar={}
  inputs.each{|i| name2exemplar[i.name]=i }

  @goto={}; @sr={}
  goto_counts=Hash.new(0); sr_counts=Hash.new(0)
  actions.each_pair{|k,v| 
    if Node===name2exemplar[k]
      @goto[k]=v
      goto_counts[v]+=1
    else
      assert(Token===name2exemplar[k])
      @sr[k]=v
      sr_counts[v]+=1
    end
  }
  dflt=goto_counts.sort_by{|v,c| c}.last[0]
  @goto.delete_if{|k,v| v==dflt }
  @goto.default=dflt

  dflt=sr_counts.sort_by{|v,c| c}.last[0]
  @sr.delete_if{|k,v| v==dflt }
  @sr.default=dflt

  @actions=nil
end
most_prominent_members() click to toggle source
# File lib/redparse/compile.rb, line 859
def most_prominent_members
  result=@dotteds.select{|dr| dr.pos==@dotteds.first.pos }
  close2end=@dotteds.map{|dr| [dr,dr.rule.patterns.size-dr.pos]}.sort_by{|(o,k)| -k}
  result+=close2end.select{|(dr,k)| k==close2end.first.last}.map{|(dr,k)| dr}
  result2=result.reject{|dr| dr.pos==0 or dr.pos==1&&dr.rule.lookback?}
  result=result2 unless result2.empty?
  return result
end
name() click to toggle source
# File lib/redparse/compile.rb, line 841
def name
  @name||@dotteds.map{|dotted| dotted.name}.join(",")
end
old_perhaps_also_allow(morerules,parser) click to toggle source
# File lib/redparse/compile.rb, line 737
def old_perhaps_also_allow(morerules,parser)
  morerules=morerules.dup
  need_sort=false
  scan_rules=@dotteds
  added={}
  while true
    adding=[]
    morerules.each{|morerule|
      next if added[morerule]
      fake_rule=morerule.final_promised_rule
      final_more_dr=DottedRule.create(fake_rule,0,parser)
      scan_rules.each{|dotted|
        if dotted.optionally_combine final_more_dr,parser
          adding<<DottedRule.create(morerule,0,parser)
          added[morerule]=1
          break
        end
      }
    }
    break if adding.empty?
    @dotteds.concat adding
    need_sort=true
    scan_rules=adding
  end
  sort_substates! if need_sort
end
Also aliased as: perhaps_also_allow
perhaps_also_allow(morerules,parser) click to toggle source

given a list of rules, see if any of them are compatible with a current substate. (compatibility means the aggregate patterns can be anded together and still be able to conceivably match something.) if any of morerules are actually compatible, add it to current state.

# File lib/redparse/compile.rb, line 732
def perhaps_also_allow(morerules,parser)
  fail unless morerules==parser.all_rules
  @dotteds.concat @dotteds.map{|d| d.also_allow }.flatten.compact.uniq
  sort_substates!
end
rename(name2count) click to toggle source
# File lib/redparse/compile.rb, line 846
def rename(name2count)
  return @name if defined? @name
  name=most_prominent_members.map{|dotted| dotted.name}.join(",")
  if name2count[name]
    name2count[name]+=1
    name+="___"+name2count[name].to_s
  else
    name2count[name]=1
  end

  @name=name
end
shiftlist2multishift?(shiftlist,parser) click to toggle source
# File lib/redparse/compile.rb, line 712
def shiftlist2multishift? shiftlist,parser
  return :error if shiftlist.empty?
  parser.sl2ms_cache||={}
  cache=parser.sl2ms_cache[shiftlist]
  return cache if cache
  fixed,varying=shiftlist.partition{|res| DottedRule===res}
  result=ParserState.new(fixed,nil)
  result.perhaps_also_allow parser.all_rules,parser
  unless varying.empty? #MultiShift
    varying.map!{|v| [v.condition,v.action]}.flatten
    result=MultiShift.new(result,varying)
  end
  parser.sl2ms_cache[shiftlist]=result
  return result
end
sort_substates!() click to toggle source
# File lib/redparse/compile.rb, line 699
def sort_substates!
  @dotteds=@dotteds.sort_by{|dotted| -dotted.pos}.uniq
end
substates() click to toggle source
# File lib/redparse/compile.rb, line 710
def substates; [self] end
transition_to_loop?(input) click to toggle source
# File lib/redparse/compile.rb, line 881
def transition_to_loop? input #not used
  action=@actions.input
  case action
  when :error; false
  when ParserState; action.looping? and action!=self
  when MultiShift,MultiReduce;
    action.transition_to_loop? input
  else fail
  end
end