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.



770
771
772
773
774
775
776
777
# File 'lib/redparse/compile.rb', line 770

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.



779
780
781
# File 'lib/redparse/compile.rb', line 779

def actions
  @actions
end

#dottedsObject (readonly)

Returns the value of attribute dotteds.



794
795
796
# File 'lib/redparse/compile.rb', line 794

def dotteds
  @dotteds
end

#nameObject



933
934
935
# File 'lib/redparse/compile.rb', line 933

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

Instance Method Details

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



963
964
965
966
# File 'lib/redparse/compile.rb', line 963

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

#[](k) ⇒ Object



781
782
783
784
785
# File 'lib/redparse/compile.rb', line 781

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

#[]=(k, v) ⇒ Object



786
787
788
789
# File 'lib/redparse/compile.rb', line 786

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

#dupObject



796
797
798
799
800
# File 'lib/redparse/compile.rb', line 796

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



859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
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
918
919
920
921
922
923
924
925
926
927
928
929
930
931
# File 'lib/redparse/compile.rb', line 859

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



960
961
962
# File 'lib/redparse/compile.rb', line 960

def hash
  -@dotteds.hash
end

#looping?Boolean

Returns:

  • (Boolean)


969
970
971
# File 'lib/redparse/compile.rb', line 969

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

#make_sr_goto_tables(inputs) ⇒ Object



984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
# File 'lib/redparse/compile.rb', line 984

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



951
952
953
954
955
956
957
958
# File 'lib/redparse/compile.rb', line 951

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



829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
# File 'lib/redparse/compile.rb', line 829

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



938
939
940
941
942
943
944
945
946
947
948
949
# File 'lib/redparse/compile.rb', line 938

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)


804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
# File 'lib/redparse/compile.rb', line 804

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



791
792
793
# File 'lib/redparse/compile.rb', line 791

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

#substatesObject



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

def substates; [self] end

#transition_to_loop?(input) ⇒ Boolean

not used

Returns:

  • (Boolean)


973
974
975
976
977
978
979
980
981
982
# File 'lib/redparse/compile.rb', line 973

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