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
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