Class: RedParse::ParserState

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

Overview

a union of dotted rules

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(dotteds, index) ⇒ ParserState

Returns a new instance of ParserState.



678
679
680
681
682
683
684
685
# 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

Instance Attribute Details

#actionsObject (readonly)

Returns the value of attribute actions.



687
688
689
# File 'lib/redparse/compile.rb', line 687

def actions
  @actions
end

#dottedsObject (readonly)

Returns the value of attribute dotteds.



702
703
704
# File 'lib/redparse/compile.rb', line 702

def dotteds
  @dotteds
end

#nameObject



841
842
843
# File 'lib/redparse/compile.rb', line 841

def name
  @name||@dotteds.map{|dotted| dotted.name}.join(",")
end

Instance Method Details

#==(other) ⇒ Object Also known as: eql?



871
872
873
874
# File 'lib/redparse/compile.rb', line 871

def == other
  ParserState===other and 
    @dotteds==other.dotteds 
end

#[](k) ⇒ Object



689
690
691
692
693
# File 'lib/redparse/compile.rb', line 689

def [](k) 
  result=@actions[k]
  assert ACTION_PATTERN===result
  result
end

#[]=(k, v) ⇒ Object



694
695
696
697
# File 'lib/redparse/compile.rb', line 694

def []=(k,v) 
  assert ACTION_PATTERN===v
  @actions[k]=v 
end

#dupObject



704
705
706
707
708
# 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) ⇒ Object

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



767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
# 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

#hashObject



868
869
870
# File 'lib/redparse/compile.rb', line 868

def hash
  -@dotteds.hash
end

#looping?Boolean

Returns:

  • (Boolean)


877
878
879
# File 'lib/redparse/compile.rb', line 877

def looping?
  @dotteds.any?{|dotted| dotted.looping? }
end

#make_sr_goto_tables(inputs) ⇒ Object



892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
# 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_membersObject



859
860
861
862
863
864
865
866
# 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

#old_perhaps_also_allow(morerules, parser) ⇒ Object Also known as: perhaps_also_allow



737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
# 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

#rename(name2count) ⇒ Object



846
847
848
849
850
851
852
853
854
855
856
857
# 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) ⇒ Boolean

Returns:

  • (Boolean)


712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
# 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!Object



699
700
701
# File 'lib/redparse/compile.rb', line 699

def sort_substates!
  @dotteds=@dotteds.sort_by{|dotted| -dotted.pos}.uniq
end

#substatesObject



710
# File 'lib/redparse/compile.rb', line 710

def substates; [self] end

#transition_to_loop?(input) ⇒ Boolean

not used

Returns:

  • (Boolean)


881
882
883
884
885
886
887
888
889
890
# 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